summaryrefslogtreecommitdiffstats
path: root/libglusterfs/src
diff options
context:
space:
mode:
authorAnand Avati <avati@redhat.com>2013-02-21 00:17:26 -0800
committerAnand Avati <avati@redhat.com>2013-02-21 22:57:04 -0800
commit72ad9a3a8b684595dc394252c88c76c859919a45 (patch)
treeef6eb57e7d817b9bf3f8f942ea9ba137cd61d16f /libglusterfs/src
parent1dbe9a05feac5032990457058f7cef686a293973 (diff)
synctask: support for (assymetric) counted barriers
This patch introduces a new set of primitives: - synctask_barrier_init (stub) - synctask_barrier_waitfor (stub, count) - synctask_barrier_wake (stub) Unlike pthread_barrier_t, this barrier has an explicit notion of "waiter" and "waker". The "waiter" waits for @count number of "wakers" to call synctask_barrier_wake() before returning. The wait performed by the waiter via synctask_barrier_waitfor() is co-operative in nature and yields the thread for scheduling other synctasks in the mean time. Intended use case: Eliminate excessive serialization in glusterd and allow for concurrent RPC transactions. Code which are currently in this format: ---old--- list_for_each_entry (peerinfo, peers, op_peers_list) { ... GD_SYNCOP (peerinfo->rpc, stub, rpc_cbk, ...); } ... int rpc_cbk (rpc, stub, ...) { ... __wake (stub); } ---old--- Can be restructred into the format: ---new--- synctask_barrier_init (stub); { list_for_each_entry (peerinfo, peers, op_peers_list) { ... rpc_submit (peerinfo->rpc, stub, rpc_cbk, ...); count++; } } synctask_barrier_wait (stub, count); ... int rpc_cbk (rpc, stub, ...) { ... synctask_barrier_wake (stub); } ---new--- In the above structure, from the synctask's point of view, the region between synctask_barrier_init() and synctask_barrier_wait() are spawning off asynchronous "threads" (or RPC) and keep count of how many such threads have been spawned. Each of those threads are expected to make one call to synctask_barrier_wake(). The call to synctask_barrier_wait() makes the synctask thread co-operatively wait/sleep till @count such threads call their wake function. This way, the synctask thread retains the "synchronous" flow in the code, yet at the same time allows for asynchronous "threads" to acheive parallelism over RPC. Change-Id: Ie037f99b2d306b71e63e3a56353daec06fb0bf41 BUG: 913662 Signed-off-by: Anand Avati <avati@redhat.com> Reviewed-on: http://review.gluster.org/4558 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Krishnan Parthasarathi <kparthas@redhat.com> Tested-by: Krishnan Parthasarathi <kparthas@redhat.com>
Diffstat (limited to 'libglusterfs/src')
-rw-r--r--libglusterfs/src/syncop.c41
-rw-r--r--libglusterfs/src/syncop.h51
2 files changed, 69 insertions, 23 deletions
diff --git a/libglusterfs/src/syncop.c b/libglusterfs/src/syncop.c
index c996b8fdd01..115debbfbf7 100644
--- a/libglusterfs/src/syncop.c
+++ b/libglusterfs/src/syncop.c
@@ -80,15 +80,24 @@ __wait (struct synctask *task)
void
-synctask_yield (struct synctask *task)
+synctask_waitfor (struct synctask *task, int waitfor)
{
+ struct syncenv *env = NULL;
xlator_t *oldTHIS = THIS;
+ env = task->env;
+
#if defined(__NetBSD__) && defined(_UC_TLSBASE)
/* Preserve pthread private pointer through swapcontex() */
task->proc->sched.uc_flags &= ~_UC_TLSBASE;
#endif
+ pthread_mutex_lock (&env->mutex);
+ {
+ task->waitfor = waitfor;
+ }
+ pthread_mutex_unlock (&env->mutex);
+
if (swapcontext (&task->ctx, &task->proc->sched) < 0) {
gf_log ("syncop", GF_LOG_ERROR,
"swapcontext failed (%s)", strerror (errno));
@@ -99,6 +108,29 @@ synctask_yield (struct synctask *task)
void
+synctask_yield (struct synctask *task)
+{
+ synctask_waitfor (task, 1);
+}
+
+
+void
+synctask_yawn (struct synctask *task)
+{
+ struct syncenv *env = NULL;
+
+ env = task->env;
+
+ pthread_mutex_lock (&env->mutex);
+ {
+ task->woken = 0;
+ task->waitfor = 0;
+ }
+ pthread_mutex_unlock (&env->mutex);
+}
+
+
+void
synctask_wake (struct synctask *task)
{
struct syncenv *env = NULL;
@@ -107,9 +139,9 @@ synctask_wake (struct synctask *task)
pthread_mutex_lock (&env->mutex);
{
- task->woken = 1;
+ task->woken++;
- if (task->slept)
+ if (task->slept && task->woken >= task->waitfor)
__run (task);
}
pthread_mutex_unlock (&env->mutex);
@@ -338,6 +370,7 @@ synctask_switchto (struct synctask *task)
task->woken = 0;
task->slept = 0;
+ task->waitfor = 0;
#if defined(__NetBSD__) && defined(_UC_TLSBASE)
/* Preserve pthread private pointer through swapcontex() */
@@ -356,7 +389,7 @@ synctask_switchto (struct synctask *task)
pthread_mutex_lock (&env->mutex);
{
- if (task->woken) {
+ if (task->woken >= task->waitfor) {
__run (task);
} else {
task->slept = 1;
diff --git a/libglusterfs/src/syncop.h b/libglusterfs/src/syncop.h
index 001c68ff5f0..ba0440cd790 100644
--- a/libglusterfs/src/syncop.h
+++ b/libglusterfs/src/syncop.h
@@ -57,6 +57,7 @@ struct synctask {
void *stack;
int woken;
int slept;
+ int waitfor;
int ret;
uid_t uid;
@@ -118,15 +119,18 @@ struct syncargs {
struct synctask *task;
pthread_mutex_t mutex;
pthread_cond_t cond;
- int done;
+ int wakecnt;
};
#define __yawn(args) do { \
- if (!args->task) { \
+ args->task = synctask_get (); \
+ if (args->task) { \
+ synctask_yawn (args->task); \
+ } else { \
pthread_mutex_init (&args->mutex, NULL); \
pthread_cond_init (&args->cond, NULL); \
- args->done = 0; \
+ args->wakecnt = 0; \
} \
} while (0)
@@ -137,7 +141,7 @@ struct syncargs {
} else { \
pthread_mutex_lock (&args->mutex); \
{ \
- args->done = 1; \
+ args->wakecnt++; \
pthread_cond_signal (&args->cond); \
} \
pthread_mutex_unlock (&args->mutex); \
@@ -145,21 +149,24 @@ struct syncargs {
} while (0)
-#define __yield(args) do { \
- if (args->task) { \
- synctask_yield (args->task); \
- } else { \
- pthread_mutex_lock (&args->mutex); \
- { \
- while (!args->done) \
- pthread_cond_wait (&args->cond, \
- &args->mutex); \
- } \
- pthread_mutex_unlock (&args->mutex); \
- pthread_mutex_destroy (&args->mutex); \
- pthread_cond_destroy (&args->cond); \
- } \
- } while (0)
+#define __waitfor(args, cnt) do { \
+ if (args->task) { \
+ synctask_waitfor (args->task, cnt); \
+ } else { \
+ pthread_mutex_lock (&args->mutex); \
+ { \
+ while (args->wakecnt < cnt) \
+ pthread_cond_wait (&args->cond, \
+ &args->mutex); \
+ } \
+ pthread_mutex_unlock (&args->mutex); \
+ pthread_mutex_destroy (&args->mutex); \
+ pthread_cond_destroy (&args->cond); \
+ } \
+ } while (0)
+
+
+#define __yield(args) __waitfor(args, 1)
#define SYNCOP(subvol, stb, cbk, op, params ...) do { \
@@ -202,6 +209,12 @@ void syncenv_scale (struct syncenv *env);
int synctask_new (struct syncenv *, synctask_fn_t, synctask_cbk_t, call_frame_t* frame, void *);
void synctask_wake (struct synctask *task);
void synctask_yield (struct synctask *task);
+void synctask_yawn (struct synctask *task);
+void synctask_waitfor (struct synctask *task, int count);
+
+#define synctask_barrier_init(args) __yawn (args)
+#define synctask_barrier_wait(args, n) __waitfor (args, n)
+#define synctask_barrier_wake(args) __wake (args)
int synctask_setid (struct synctask *task, uid_t uid, gid_t gid);
#define SYNCTASK_SETID(uid, gid) synctask_setid (synctask_get(), uid, gid);
0%;'/> -rw-r--r--argp-standalone/argp-eexst.c36
-rw-r--r--argp-standalone/argp-fmtstream.c475
-rw-r--r--argp-standalone/argp-fmtstream.h319
-rw-r--r--argp-standalone/argp-help.c1849
-rw-r--r--argp-standalone/argp-namefrob.h96
-rw-r--r--argp-standalone/argp-parse.c1305
-rw-r--r--argp-standalone/argp-pv.c25
-rw-r--r--argp-standalone/argp-pvh.c32
-rw-r--r--argp-standalone/argp.h602
-rwxr-xr-xargp-standalone/autogen.sh6
-rw-r--r--argp-standalone/configure.ac102
-rw-r--r--argp-standalone/mempcpy.c21
-rw-r--r--argp-standalone/strcasecmp.c29
-rw-r--r--argp-standalone/strchrnul.c23
-rw-r--r--argp-standalone/strndup.c34
-rw-r--r--argp-standalone/vsnprintf.c839
-rwxr-xr-xautogen.sh96
-rw-r--r--booster/Makefile.am1
-rw-r--r--booster/src/Makefile.am21
-rw-r--r--booster/src/booster-fd.c342
-rw-r--r--booster/src/booster-fd.h83
-rw-r--r--booster/src/booster.c3172
-rw-r--r--booster/src/booster_fstab.c452
-rw-r--r--booster/src/booster_fstab.h83
-rw-r--r--booster/src/booster_stat.c188
-rwxr-xr-xbuild-aux/checkpatch.pl4326
-rwxr-xr-xbuild-aux/config.guess.dist14
-rwxr-xr-xbuild-aux/config.sub.dist14
-rwxr-xr-xbuild-aux/pkg-version64
-rw-r--r--cli/src/Makefile.am37
-rw-r--r--cli/src/cli-cmd-global.c195
-rw-r--r--cli/src/cli-cmd-misc.c152
-rw-r--r--cli/src/cli-cmd-parser.c7076
-rw-r--r--cli/src/cli-cmd-peer.c431
-rw-r--r--cli/src/cli-cmd-snapshot.c135
-rw-r--r--cli/src/cli-cmd-system.c793
-rw-r--r--cli/src/cli-cmd-volume.c4282
-rw-r--r--cli/src/cli-cmd.c580
-rw-r--r--cli/src/cli-cmd.h173
-rw-r--r--cli/src/cli-mem-types.h41
-rw-r--r--cli/src/cli-quotad-client.c146
-rw-r--r--cli/src/cli-quotad-client.h29
-rw-r--r--cli/src/cli-rl.c535
-rw-r--r--cli/src/cli-rpc-ops.c14821
-rw-r--r--cli/src/cli-xml-output.c7441
-rw-r--r--cli/src/cli.c1233
-rw-r--r--cli/src/cli.h564
-rw-r--r--cli/src/input.c134
-rw-r--r--cli/src/registry.c524
-rw-r--r--configure.ac1711
-rw-r--r--contrib/aclocal/mkdirp.m4146
-rw-r--r--contrib/aclocal/python.m4209
-rw-r--r--contrib/fuse-include/fuse-mount.h1
-rw-r--r--contrib/fuse-include/fuse_kernel.h578
-rw-r--r--contrib/fuse-include/fuse_kernel_macfuse.h461
-rw-r--r--contrib/fuse-include/mount_util.h (renamed from contrib/fuse-util/mount_util.h)0
-rw-r--r--contrib/fuse-lib/misc.c3
-rw-r--r--contrib/fuse-lib/mount-common.c282
-rw-r--r--contrib/fuse-lib/mount-gluster-compat.h105
-rw-r--r--contrib/fuse-lib/mount.c638
-rw-r--r--contrib/fuse-util/Makefile.am8
-rw-r--r--contrib/fuse-util/fusermount.c124
-rw-r--r--contrib/fuse-util/mount_util.c64
-rw-r--r--contrib/ipaddr-py/COPYING202
-rw-r--r--contrib/ipaddr-py/MANIFEST.in3
-rw-r--r--contrib/ipaddr-py/OWNERS4
-rw-r--r--contrib/ipaddr-py/README8
-rw-r--r--contrib/ipaddr-py/ipaddr.py1907
-rwxr-xr-xcontrib/ipaddr-py/ipaddr_test.py1099
-rwxr-xr-xcontrib/ipaddr-py/setup.py36
-rwxr-xr-xcontrib/ipaddr-py/test-2to3.sh15
-rw-r--r--contrib/libexecinfo/execinfo.c442
-rw-r--r--contrib/libexecinfo/execinfo_compat.h51
-rw-r--r--contrib/libgen/basename_r.c40
-rw-r--r--contrib/libgen/dirname_r.c243
-rw-r--r--contrib/macfuse/fuse_param.h97
-rw-r--r--contrib/macfuse/mount_darwin.c459
-rw-r--r--contrib/mount/mntent.c260
-rw-r--r--contrib/mount/mntent_compat.h37
-rw-r--r--contrib/timer-wheel/find_last_bit.c61
-rw-r--r--contrib/timer-wheel/timer-wheel.c374
-rw-r--r--contrib/timer-wheel/timer-wheel.h77
-rw-r--r--contrib/umountd/Makefile.am11
-rw-r--r--contrib/umountd/umountd.c255
-rw-r--r--contrib/userspace-rcu/rculist-extra.h42
-rw-r--r--contrib/userspace-rcu/static-wfcqueue.h685
-rw-r--r--contrib/userspace-rcu/static-wfstack.h455
-rw-r--r--contrib/userspace-rcu/wfcqueue.h216
-rw-r--r--contrib/userspace-rcu/wfstack.h178
-rw-r--r--contrib/uuid/clear.c43
-rw-r--r--contrib/uuid/compare.c55
-rw-r--r--contrib/uuid/copy.c45
-rw-r--r--contrib/uuid/gen_uuid.c679
-rw-r--r--contrib/uuid/gen_uuid_nt.c92
-rw-r--r--contrib/uuid/isnull.c48
-rw-r--r--contrib/uuid/pack.c69
-rw-r--r--contrib/uuid/parse.c79
-rw-r--r--contrib/uuid/tst_uuid.c180
-rw-r--r--contrib/uuid/unpack.c63
-rw-r--r--contrib/uuid/unparse.c76
-rw-r--r--contrib/uuid/uuid.h104
-rw-r--r--contrib/uuid/uuidP.h63
-rw-r--r--contrib/uuid/uuid_time.c171
-rw-r--r--contrib/uuid/uuid_types.h.in50
-rw-r--r--contrib/uuid/uuidd.h54
-rw-r--r--contrib/xxhash/xxhash.c1029
-rw-r--r--contrib/xxhash/xxhash.h328
-rw-r--r--contrib/xxhash/xxhsum.c1301
-rw-r--r--doc/Makefile.am13
-rw-r--r--doc/README.md26
-rw-r--r--doc/admin-guide/en-US/Administration_Guide.ent4
-rw-r--r--doc/admin-guide/en-US/Administration_Guide.xml27
-rw-r--r--doc/admin-guide/en-US/Author_Group.xml17
-rw-r--r--doc/admin-guide/en-US/Book_Info.xml28
-rw-r--r--doc/admin-guide/en-US/Chapter.xml33
-rw-r--r--doc/admin-guide/en-US/Preface.xml24
-rw-r--r--doc/admin-guide/en-US/Revision_History.xml27
-rw-r--r--doc/admin-guide/en-US/admin_ACLs.xml206
-rw-r--r--doc/admin-guide/en-US/admin_Hadoop.xml244
-rw-r--r--doc/admin-guide/en-US/admin_UFO.xml1588
-rw-r--r--doc/admin-guide/en-US/admin_commandref.xml334
-rw-r--r--doc/admin-guide/en-US/admin_console.xml28
-rw-r--r--doc/admin-guide/en-US/admin_directory_Quota.xml179
-rw-r--r--doc/admin-guide/en-US/admin_geo-replication.xml732
-rw-r--r--doc/admin-guide/en-US/admin_managing_volumes.xml735
-rw-r--r--doc/admin-guide/en-US/admin_monitoring_workload.xml878
-rw-r--r--doc/admin-guide/en-US/admin_setting_volumes.xml325
-rw-r--r--doc/admin-guide/en-US/admin_settingup_clients.xml511
-rw-r--r--doc/admin-guide/en-US/admin_start_stop_daemon.xml56
-rw-r--r--doc/admin-guide/en-US/admin_storage_pools.xml57
-rw-r--r--doc/admin-guide/en-US/admin_troubleshooting.xml509
-rw-r--r--doc/admin-guide/en-US/gfs_introduction.xml54
-rw-r--r--doc/admin-guide/en-US/glossary.xml126
-rw-r--r--doc/admin-guide/en-US/images/640px-GlusterFS_3.2_Architecture.pngbin97477 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Distributed_Replicated_Volume.pngbin51326 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Distributed_Striped_Replicated_Volume.pngbin57210 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Distributed_Striped_Volume.pngbin53781 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Distributed_Volume.pngbin47211 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Geo-Rep03_Internet.pngbin131824 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Geo-Rep04_Cascading.pngbin187341 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Geo-Rep_LAN.pngbin163417 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Geo-Rep_WAN.pngbin96291 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/GlusterFS_3.2_Architecture.pngbin133597 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Hadoop_Architecture.pngbin43815 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Replicated_Volume.pngbin44077 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Striped_Replicated_Volume.pngbin50193 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/Striped_Volume.pngbin43316 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/UFO_Architecture.pngbin72139 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/VSA_Architecture.pngbin38875 -> 0 bytes-rw-r--r--doc/admin-guide/en-US/images/arhitecture.png13
-rw-r--r--doc/admin-guide/en-US/images/icon.svg19
-rw-r--r--doc/admin-guide/publican.cfg12
-rw-r--r--doc/debugging/analyzing-regression-cores.md54
-rw-r--r--doc/debugging/gfid-to-path.md68
-rw-r--r--doc/debugging/mem-alloc-list.md19
-rw-r--r--doc/debugging/split-brain.md264
-rw-r--r--doc/debugging/statedump.md414
-rw-r--r--doc/developer-guide/Language-Bindings.md45
-rw-r--r--doc/developer-guide/README.md81
-rw-r--r--doc/developer-guide/Using-Gluster-Test-Framework.md271
-rw-r--r--doc/developer-guide/adding-fops.md18
-rw-r--r--doc/developer-guide/afr-locks-evolution.md91
-rw-r--r--doc/developer-guide/afr-self-heal-daemon.md92
-rw-r--r--doc/developer-guide/afr.md191
-rw-r--r--doc/developer-guide/brickmux-thread-reduction.md64
-rw-r--r--doc/developer-guide/coding-standard.md697
-rw-r--r--doc/developer-guide/commit-guidelines.md136
-rw-r--r--doc/developer-guide/daemon-management-framework.md38
-rw-r--r--doc/developer-guide/datastructure-inode.md221
-rw-r--r--doc/developer-guide/datastructure-iobuf.md259
-rw-r--r--doc/developer-guide/datastructure-mem-pool.md124
-rw-r--r--doc/developer-guide/dirops-transactions-in-dht.md273
-rw-r--r--doc/developer-guide/ec-implementation.md588
-rw-r--r--doc/developer-guide/fuse-interrupt.md211
-rw-r--r--doc/developer-guide/gfapi-symbol-versions.md270
-rw-r--r--doc/developer-guide/identifying-resource-leaks.md200
-rw-r--r--doc/developer-guide/logging-guidelines.md132
-rw-r--r--doc/developer-guide/network_compression.md71
-rw-r--r--doc/developer-guide/options-to-contribute.md212
-rw-r--r--doc/developer-guide/posix.md59
-rw-r--r--doc/developer-guide/rpc-for-glusterfs.changes-done.txt (renamed from doc/legacy/rpc-for-glusterfs.changes-done.txt)0
-rw-r--r--doc/developer-guide/rpc-for-glusterfs.new-versions.md32
-rw-r--r--doc/developer-guide/syncop.md72
-rw-r--r--doc/developer-guide/thread-naming.md104
-rw-r--r--doc/developer-guide/translator-development.md683
-rw-r--r--doc/developer-guide/unittest.md228
-rw-r--r--doc/developer-guide/versioning.md44
-rw-r--r--doc/developer-guide/write-behind.md56
-rw-r--r--doc/developer-guide/writing-a-cloudsync-plugin.md164
-rw-r--r--doc/developer-guide/xlator-classification.md221
-rw-r--r--doc/examples/legacy/Makefile.am8
-rw-r--r--doc/examples/legacy/README13
-rw-r--r--doc/examples/legacy/filter.vol23
-rw-r--r--doc/examples/legacy/io-cache.vol31
-rw-r--r--doc/examples/legacy/io-threads.vol22
-rw-r--r--doc/examples/legacy/posix-locks.vol19
-rw-r--r--doc/examples/legacy/protocol-client.vol12
-rw-r--r--doc/examples/legacy/protocol-server.vol21
-rw-r--r--doc/examples/legacy/read-ahead.vol24
-rw-r--r--doc/examples/legacy/replicate.vol118
-rw-r--r--doc/examples/legacy/stripe.vol120
-rw-r--r--doc/examples/legacy/trace.vol21
-rw-r--r--doc/examples/legacy/trash.vol20
-rw-r--r--doc/examples/legacy/write-behind.vol27
-rw-r--r--doc/features/ctime.md68
-rw-r--r--doc/features/ganesha-ha.md43
-rw-r--r--doc/gluster.8280
-rw-r--r--doc/glusterd.824
-rw-r--r--doc/glusterd.vol8
-rw-r--r--doc/glusterfs.8104
-rw-r--r--doc/glusterfs.vol.sample53
-rw-r--r--doc/glusterfsd.834
-rw-r--r--doc/glusterfsd.vol.sample44
-rw-r--r--doc/legacy/authentication.txt112
-rw-r--r--doc/legacy/booster.txt54
-rw-r--r--doc/legacy/coding-standard.pdfbin68627 -> 0 bytes-rw-r--r--doc/legacy/coding-standard.tex385
-rw-r--r--doc/legacy/errno.list.bsd.txt376
-rw-r--r--doc/legacy/errno.list.linux.txt1586
-rw-r--r--doc/legacy/errno.list.macosx.txt1513
-rw-r--r--doc/legacy/errno.list.solaris.txt206
-rw-r--r--doc/legacy/get_put_api_using_xattr.txt22
-rw-r--r--doc/legacy/hacker-guide/Makefile.am8
-rw-r--r--doc/legacy/hacker-guide/adding-fops.txt33
-rw-r--r--doc/legacy/hacker-guide/bdb.txt70
-rw-r--r--doc/legacy/hacker-guide/call-stub.txt1033
-rw-r--r--doc/legacy/hacker-guide/hacker-guide.tex309
-rw-r--r--doc/legacy/hacker-guide/lock-ahead.txt80
-rw-r--r--doc/legacy/hacker-guide/posix.txt59
-rw-r--r--doc/legacy/hacker-guide/replicate.txt206
-rw-r--r--doc/legacy/hacker-guide/write-behind.txt45
-rw-r--r--doc/legacy/handling-options.txt13
-rw-r--r--doc/legacy/mac-related-xattrs.txt21
-rw-r--r--doc/legacy/porting_guide.txt45
-rw-r--r--doc/legacy/replicate.lyx797
-rw-r--r--doc/legacy/replicate.pdfbin109057 -> 0 bytes-rw-r--r--doc/legacy/solaris-related-xattrs.txt44
-rw-r--r--doc/legacy/stat-prefetch-design.txt154
-rw-r--r--doc/legacy/translator-options.txt224
-rw-r--r--doc/mount.glusterfs.8154
-rw-r--r--doc/qa/legacy/qa-client.vol170
-rw-r--r--doc/qa/legacy/qa-high-avail-client.vol17
-rw-r--r--doc/qa/legacy/qa-high-avail-server.vol344
-rw-r--r--doc/qa/legacy/qa-server.vol284
-rw-r--r--doc/user-guide/legacy/Makefile.am3
-rw-r--r--doc/user-guide/legacy/advanced-stripe.odgbin12648 -> 0 bytes-rw-r--r--doc/user-guide/legacy/advanced-stripe.pdfbin13382 -> 0 bytes-rw-r--r--doc/user-guide/legacy/colonO-icon.jpgbin779 -> 0 bytes-rw-r--r--doc/user-guide/legacy/fdl.texi454
-rw-r--r--doc/user-guide/legacy/fuse.odgbin13190 -> 0 bytes-rw-r--r--doc/user-guide/legacy/fuse.pdfbin14948 -> 0 bytes-rw-r--r--doc/user-guide/legacy/ha.odgbin37290 -> 0 bytes-rw-r--r--doc/user-guide/legacy/ha.pdfbin19403 -> 0 bytes-rw-r--r--doc/user-guide/legacy/stripe.odgbin10188 -> 0 bytes-rw-r--r--doc/user-guide/legacy/stripe.pdfbin11941 -> 0 bytes-rw-r--r--doc/user-guide/legacy/unify.odgbin12955 -> 0 bytes-rw-r--r--doc/user-guide/legacy/unify.pdfbin18969 -> 0 bytes-rw-r--r--doc/user-guide/legacy/user-guide.info2697
-rw-r--r--doc/user-guide/legacy/user-guide.pdfbin353986 -> 0 bytes-rw-r--r--doc/user-guide/legacy/user-guide.texi2246
-rw-r--r--doc/user-guide/legacy/xlator.odgbin12169 -> 0 bytes-rw-r--r--doc/user-guide/legacy/xlator.pdfbin14358 -> 0 bytes-rw-r--r--events/Makefile.am8
-rw-r--r--events/eventskeygen.py243
-rw-r--r--events/src/Makefile.am41
-rw-r--r--events/src/__init__.py10
-rw-r--r--events/src/eventsapiconf.py.in59
-rw-r--r--events/src/eventsconfig.json5
-rw-r--r--events/src/gf_event.py60
-rw-r--r--events/src/glustereventsd.py159
-rw-r--r--events/src/handlers.py40
-rw-r--r--events/src/peer_eventsapi.py669
-rw-r--r--events/src/utils.py445
-rw-r--r--events/tools/Makefile.am6
-rw-r--r--events/tools/eventsdash.py75
-rw-r--r--extras/LinuxRPM/Makefile.am55
-rwxr-xr-xextras/LinuxRPM/make_glusterrpms9
-rw-r--r--extras/MacOSX/Portfile26
-rw-r--r--extras/MacOSX/README.MacOSX84
-rw-r--r--extras/Makefile.am80
-rw-r--r--extras/Ubuntu/README.Ubuntu14
-rw-r--r--extras/Ubuntu/glusterfs-server.conf (renamed from extras/Ubuntu/glusterd.conf)0
-rw-r--r--extras/Ubuntu/mounting-glusterfs.conf5
-rw-r--r--extras/backend-cleanup.sh2
-rw-r--r--extras/benchmarking/Makefile.am4
-rw-r--r--extras/benchmarking/glfs-bm.c534
-rw-r--r--extras/benchmarking/rdd.c1025
-rwxr-xr-xextras/check_goto.pl45
-rwxr-xr-xextras/clang-checker.sh301
-rw-r--r--extras/cliutils/Makefile.am4
-rw-r--r--extras/cliutils/README.md233
-rw-r--r--extras/cliutils/__init__.py31
-rw-r--r--extras/cliutils/cliutils.py237
-rwxr-xr-xextras/collect-system-stats.sh52
-rw-r--r--extras/command-completion/Makefile6
-rw-r--r--extras/command-completion/README5
-rw-r--r--extras/command-completion/gluster.bash492
-rwxr-xr-xextras/control-cpu-load.sh116
-rwxr-xr-xextras/control-mem.sh128
-rw-r--r--extras/create_new_xlator/README.md24
-rwxr-xr-xextras/create_new_xlator/generate_xlator.py208
-rw-r--r--extras/create_new_xlator/new-xlator.c.tmpl151
-rw-r--r--extras/devel-tools/devel-vagrant/Vagrantfile165
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/cluster/tasks/main.yml5
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/compile-gluster/tasks/main.yml29
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/install-pkgs/tasks/main.yml72
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/iptables/tasks/main.yml3
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/prepare-brick/tasks/main.yml30
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/selinux/tasks/main.yml3
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/roles/service/tasks/main.yml21
-rw-r--r--extras/devel-tools/devel-vagrant/ansible/setup.yml23
-rw-r--r--extras/devel-tools/devel-vagrant/bootstrap.sh3
-rwxr-xr-xextras/devel-tools/devel-vagrant/up.sh4
-rw-r--r--extras/devel-tools/gdb_macros84
-rwxr-xr-xextras/devel-tools/print-backtrace.sh115
-rwxr-xr-xextras/devel-tools/strace-brick.sh55
-rw-r--r--extras/distributed-testing/README28
-rw-r--r--extras/distributed-testing/distributed-test-build-env20
-rwxr-xr-xextras/distributed-testing/distributed-test-build.sh27
-rw-r--r--extras/distributed-testing/distributed-test-env48
-rwxr-xr-xextras/distributed-testing/distributed-test-runner.py859
-rwxr-xr-xextras/distributed-testing/distributed-test.sh95
-rw-r--r--extras/ec-heal-script/README.md69
-rwxr-xr-xextras/ec-heal-script/correct_pending_heals.sh415
-rwxr-xr-xextras/ec-heal-script/gfid_needing_heal_parallel.sh278
-rwxr-xr-xextras/failed-tests.py180
-rw-r--r--extras/firewalld/Makefile.am8
-rw-r--r--extras/firewalld/glusterfs.xml14
-rw-r--r--extras/ganesha/Makefile.am2
-rw-r--r--extras/ganesha/config/Makefile.am4
-rw-r--r--extras/ganesha/config/ganesha-ha.conf.sample19
-rw-r--r--extras/ganesha/ocf/Makefile.am11
-rw-r--r--extras/ganesha/ocf/ganesha_grace221
-rw-r--r--extras/ganesha/ocf/ganesha_mon234
-rw-r--r--extras/ganesha/ocf/ganesha_nfsd167
-rw-r--r--extras/ganesha/scripts/Makefile.am6
-rwxr-xr-xextras/ganesha/scripts/create-export-ganesha.sh92
-rwxr-xr-xextras/ganesha/scripts/dbus-send.sh70
-rw-r--r--extras/ganesha/scripts/ganesha-ha.sh1199
-rwxr-xr-xextras/ganesha/scripts/generate-epoch.py48
-rwxr-xr-xextras/generate-xdr-files.sh107
-rw-r--r--extras/geo-rep/Makefile.am16
-rw-r--r--extras/geo-rep/generate-gfid-file.sh70
-rwxr-xr-xextras/geo-rep/get-gfid.sh7
-rw-r--r--extras/geo-rep/gsync-sync-gfid.c109
-rw-r--r--extras/geo-rep/gsync-upgrade.sh123
-rw-r--r--extras/geo-rep/schedule_georep.py.in492
-rw-r--r--extras/geo-rep/slave-upgrade.sh102
-rwxr-xr-xextras/gfid-to-dirname.sh46
-rwxr-xr-xextras/git-branch-diff.py285
-rw-r--r--extras/gluster-rsyslog-5.8.conf51
-rw-r--r--extras/gluster-rsyslog-7.2.conf76
-rw-r--r--extras/glusterd-sysconfig6
-rw-r--r--extras/glusterd.vol.in15
-rw-r--r--extras/glusterfs-georep-logrotate61
-rwxr-xr-xextras/glusterfs-georep-upgrade.py77
-rw-r--r--extras/glusterfs-logrotate63
-rw-r--r--extras/glusterfs-mode.el225
-rw-r--r--extras/glusterfs.vim21
-rwxr-xr-x[-rw-r--r--]extras/gnfs-loganalyse.py23
-rw-r--r--extras/group-db-workload12
-rw-r--r--extras/group-distributed-virt10
-rw-r--r--extras/group-gluster-block27
-rw-r--r--extras/group-metadata-cache6
-rw-r--r--extras/group-nl-cache5
-rw-r--r--extras/group-samba11
-rw-r--r--extras/group-virt.example24
-rw-r--r--extras/hook-scripts/Makefile.am8
-rw-r--r--extras/hook-scripts/S29CTDBsetup.sh69
-rwxr-xr-xextras/hook-scripts/S30samba-start.sh62
-rwxr-xr-xextras/hook-scripts/S30samba-stop.sh60
-rwxr-xr-xextras/hook-scripts/S40ufo-stop.py24
-rwxr-xr-xextras/hook-scripts/S56glusterd-geo-rep-create-post.sh104
-rw-r--r--extras/hook-scripts/add-brick/Makefile.am2
-rw-r--r--extras/hook-scripts/add-brick/post/Makefile.am6
-rwxr-xr-xextras/hook-scripts/add-brick/post/S10selinux-label-brick.sh100
-rwxr-xr-xextras/hook-scripts/add-brick/post/S13create-subdir-mounts.sh86
-rwxr-xr-xextras/hook-scripts/add-brick/post/disabled-quota-root-xattr-heal.sh145
-rw-r--r--extras/hook-scripts/add-brick/pre/Makefile.am6
-rwxr-xr-xextras/hook-scripts/add-brick/pre/S28Quota-enable-root-xattr-heal.sh101
-rw-r--r--extras/hook-scripts/create/Makefile.am1
-rw-r--r--extras/hook-scripts/create/post/Makefile.am8
-rwxr-xr-xextras/hook-scripts/create/post/S10selinux-label-brick.sh65
-rw-r--r--extras/hook-scripts/delete/Makefile.am1
-rw-r--r--extras/hook-scripts/delete/pre/Makefile.am8
-rwxr-xr-xextras/hook-scripts/delete/pre/S10selinux-del-fcontext.sh73
-rw-r--r--extras/hook-scripts/reset/Makefile.am2
-rw-r--r--extras/hook-scripts/reset/post/Makefile.am1
-rw-r--r--extras/hook-scripts/reset/pre/Makefile.am1
-rw-r--r--extras/hook-scripts/set/Makefile.am2
-rw-r--r--extras/hook-scripts/set/post/Makefile.am6
-rwxr-xr-xextras/hook-scripts/set/post/S30samba-set.sh161
-rwxr-xr-xextras/hook-scripts/set/post/S32gluster_enable_shared_storage.sh136
-rw-r--r--extras/hook-scripts/start/Makefile.am2
-rw-r--r--extras/hook-scripts/start/post/Makefile.am6
-rwxr-xr-xextras/hook-scripts/start/post/S29CTDBsetup.sh84
-rwxr-xr-xextras/hook-scripts/start/post/S30samba-start.sh145
-rwxr-xr-xextras/hook-scripts/start/post/S31ganesha-start.sh122
-rw-r--r--extras/hook-scripts/stop/Makefile.am2
-rw-r--r--extras/hook-scripts/stop/pre/Makefile.am6
-rwxr-xr-xextras/hook-scripts/stop/pre/S29CTDB-teardown.sh62
-rwxr-xr-xextras/hook-scripts/stop/pre/S30samba-stop.sh77
-rwxr-xr-xextras/identify-hangs.sh53
-rw-r--r--extras/init.d/Makefile.am33
-rw-r--r--extras/init.d/glusterd-FreeBSD.in24
-rwxr-xr-xextras/init.d/glusterd-Redhat.in124
-rwxr-xr-xextras/init.d/glusterd-SuSE.in10
-rw-r--r--extras/init.d/glusterd.plist.in2
-rw-r--r--extras/init.d/glustereventsd-Debian.in91
-rw-r--r--extras/init.d/glustereventsd-FreeBSD.in19
-rw-r--r--extras/init.d/glustereventsd-Redhat.in129
-rw-r--r--extras/logger.conf.example13
-rwxr-xr-xextras/mount-shared-storage.sh39
-rw-r--r--extras/ocf/Makefile.am11
-rwxr-xr-xextras/ocf/glusterd.in212
-rwxr-xr-xextras/ocf/volume.in276
-rw-r--r--extras/peer_add_secret_pub.in70
-rwxr-xr-xextras/post-upgrade-script-for-quota.sh65
-rwxr-xr-xextras/pre-upgrade-script-for-quota.sh18
-rwxr-xr-xextras/profiler/glusterfs-profiler27
-rw-r--r--extras/python/Makefile.am7
-rw-r--r--extras/python/__init__.py2
-rwxr-xr-xextras/quota-metadata-cleanup.sh24
-rwxr-xr-xextras/quota-remove-xattr.sh24
-rwxr-xr-xextras/quota/contri-add.sh (renamed from extras/contri-add.sh)0
-rwxr-xr-xextras/quota/log_accounting.sh26
-rwxr-xr-xextras/quota/quota_fsck.py377
-rwxr-xr-xextras/quota/xattr_analysis.py73
-rwxr-xr-xextras/rebalance.py309
-rw-r--r--extras/run-gluster.tmpfiles.in2
-rw-r--r--extras/snap_scheduler/Makefile.am9
-rw-r--r--extras/snap_scheduler/README.md125
-rw-r--r--extras/snap_scheduler/conf.py.in11
-rwxr-xr-xextras/snap_scheduler/gcron.py190
-rwxr-xr-xextras/snap_scheduler/snap_scheduler.py941
-rwxr-xr-xextras/statedumpparse.rb208
-rwxr-xr-xextras/stop-all-gluster-processes.sh193
-rw-r--r--extras/stripe-merge.c539
-rw-r--r--extras/systemd/Makefile.am17
-rw-r--r--extras/systemd/gluster-ta-volume.service.in13
-rw-r--r--extras/systemd/glusterd.service.in26
-rw-r--r--extras/systemd/glustereventsd.service.in16
-rw-r--r--extras/systemd/glusterfssharedstorage.service.in13
-rwxr-xr-xextras/test/bug-920583.t50
-rwxr-xr-xextras/test/gluster_commands.sh40
-rw-r--r--extras/test/ld-preload-test/README4
-rw-r--r--extras/test/ld-preload-test/ld-preload-lib.c620
-rw-r--r--extras/test/ld-preload-test/ld-preload-test.c527
-rw-r--r--extras/test/open-fd-tests.c85
-rwxr-xr-xextras/test/run.sh23
-rwxr-xr-xextras/test/stop_glusterd.sh23
-rw-r--r--extras/test/test-ffop.c971
-rwxr-xr-xextras/thin-arbiter/setup-thin-arbiter.sh184
-rw-r--r--extras/thin-arbiter/thin-arbiter.vol57
-rw-r--r--extras/volfilter.py168
-rw-r--r--extras/who-wrote-glusterfs/gitdm.aliases58
-rw-r--r--extras/who-wrote-glusterfs/gitdm.config8
-rw-r--r--extras/who-wrote-glusterfs/gitdm.domain-map29
-rwxr-xr-xextras/who-wrote-glusterfs/who-wrote-glusterfs.sh50
-rw-r--r--geo-replication/Makefile.am8
-rw-r--r--geo-replication/gsyncd.conf.in349
-rw-r--r--geo-replication/setup.py32
-rw-r--r--geo-replication/src/Makefile.am48
-rw-r--r--geo-replication/src/gsyncd.c402
-rwxr-xr-xgeo-replication/src/gverify.sh276
-rw-r--r--geo-replication/src/peer_georep-sshkey.py.in116
-rwxr-xr-xgeo-replication/src/peer_gsec_create.in24
-rw-r--r--geo-replication/src/peer_mountbroker.in211
-rw-r--r--geo-replication/src/peer_mountbroker.py.in401
-rw-r--r--geo-replication/src/procdiggy.c136
-rw-r--r--geo-replication/src/procdiggy.h21
-rwxr-xr-xgeo-replication/src/set_geo_rep_pem_keys.sh58
-rw-r--r--geo-replication/syncdaemon/Makefile.am8
-rw-r--r--geo-replication/syncdaemon/README.md (renamed from xlators/features/marker/utils/syncdaemon/README.md)42
-rw-r--r--geo-replication/syncdaemon/__codecheck.py (renamed from xlators/features/marker/utils/syncdaemon/__codecheck.py)20
-rw-r--r--geo-replication/syncdaemon/__init__.py9
-rw-r--r--geo-replication/syncdaemon/argsupgrade.py359
-rw-r--r--geo-replication/syncdaemon/conf.py.in17
-rw-r--r--geo-replication/syncdaemon/gsyncd.py325
-rw-r--r--geo-replication/syncdaemon/gsyncdconfig.py485
-rw-r--r--geo-replication/syncdaemon/gsyncdstatus.py419
-rw-r--r--geo-replication/syncdaemon/libcxattr.py112
-rw-r--r--geo-replication/syncdaemon/libgfchangelog.py143
-rw-r--r--geo-replication/syncdaemon/logutils.py77
-rw-r--r--geo-replication/syncdaemon/master.py2020
-rw-r--r--geo-replication/syncdaemon/monitor.py395
-rw-r--r--geo-replication/syncdaemon/py2py3.py184
-rw-r--r--geo-replication/syncdaemon/rconf.py31
-rw-r--r--geo-replication/syncdaemon/repce.py (renamed from xlators/features/marker/utils/syncdaemon/repce.py)82
-rw-r--r--geo-replication/syncdaemon/resource.py1583
-rw-r--r--geo-replication/syncdaemon/subcmds.py335
-rw-r--r--geo-replication/syncdaemon/syncdutils.py1115
-rw-r--r--geo-replication/test-requirements.txt7
-rw-r--r--geo-replication/tests/__init__.py9
-rw-r--r--geo-replication/tests/unit/__init__.py9
-rwxr-xr-xgeo-replication/tests/unit/test_gsyncdstatus.py193
-rw-r--r--geo-replication/tests/unit/test_syncdutils.py29
-rw-r--r--geo-replication/tox.ini32
-rw-r--r--geo-replication/unittests.sh9
-rw-r--r--glusterfs-api.pc.in12
-rw-r--r--glusterfs-hadoop/0.20.2/conf/core-site.xml38
-rw-r--r--glusterfs-hadoop/0.20.2/pom.xml36
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFSBrickClass.java109
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFSBrickRepl.java52
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFSXattr.java472
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFUSEInputStream.java205
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFUSEOutputStream.java86
-rw-r--r--glusterfs-hadoop/0.20.2/src/main/java/org/apache/hadoop/fs/glusterfs/GlusterFileSystem.java492
-rw-r--r--glusterfs-hadoop/0.20.2/src/test/java/org/apache/hadoop/fs/glusterfs/AppTest.java38
-rwxr-xr-xglusterfs-hadoop/0.20.2/tools/build-deploy-jar.py212
-rw-r--r--glusterfs-hadoop/COPYING202
-rw-r--r--glusterfs-hadoop/README182
-rw-r--r--glusterfs.spec.in2192
-rw-r--r--glusterfsd/src/Makefile.am39
-rw-r--r--glusterfsd/src/gf_attach.c241
-rw-r--r--glusterfsd/src/glusterfsd-mem-types.h36
-rw-r--r--glusterfsd/src/glusterfsd-messages.h93
-rw-r--r--glusterfsd/src/glusterfsd-mgmt.c4517
-rw-r--r--glusterfsd/src/glusterfsd.c3657
-rw-r--r--glusterfsd/src/glusterfsd.h204
-rw-r--r--heal/Makefile.am (renamed from scheduler/nufa/Makefile.am)2
-rw-r--r--heal/src/Makefile.am29
-rw-r--r--heal/src/glfs-heal.c1793
-rw-r--r--libgfchangelog.pc.in12
-rw-r--r--libglusterd/Makefile.am (renamed from mod_glusterfs/apache/2.2/Makefile.am)2
-rw-r--r--libglusterd/src/Makefile.am31
-rw-r--r--libglusterd/src/gd-common-utils.c78
-rw-r--r--libglusterd/src/gd-common-utils.h28
-rw-r--r--libglusterd/src/libglusterd.sym2
-rw-r--r--libglusterfs/src/Makefile.am138
-rw-r--r--libglusterfs/src/async.c720
-rw-r--r--libglusterfs/src/byte-order.h301
-rw-r--r--libglusterfs/src/call-stub.c4909
-rw-r--r--libglusterfs/src/call-stub.h1134
-rw-r--r--libglusterfs/src/changelog.h115
-rw-r--r--libglusterfs/src/checksum.c51
-rw-r--r--libglusterfs/src/circ-buff.c275
-rw-r--r--libglusterfs/src/circ-buff.h63
-rw-r--r--libglusterfs/src/client_t.c825
-rw-r--r--libglusterfs/src/cluster-syncop.c1261
-rw-r--r--libglusterfs/src/common-utils.c6203
-rw-r--r--libglusterfs/src/common-utils.h487
-rw-r--r--libglusterfs/src/compat-errno.c1731
-rw-r--r--libglusterfs/src/compat-errno.h231
-rw-r--r--libglusterfs/src/compat.c906
-rw-r--r--libglusterfs/src/compat.h391
-rw-r--r--libglusterfs/src/ctx.c97
-rw-r--r--libglusterfs/src/daemon.c69
-rw-r--r--libglusterfs/src/default-args.c1651
-rw-r--r--libglusterfs/src/defaults-tmpl.c247
-rw-r--r--libglusterfs/src/defaults.c1354
-rw-r--r--libglusterfs/src/defaults.h673
-rw-r--r--libglusterfs/src/dict.c4349
-rw-r--r--libglusterfs/src/dict.h230
-rw-r--r--libglusterfs/src/event-epoll.c1032
-rw-r--r--libglusterfs/src/event-history.c83
-rw-r--r--libglusterfs/src/event-history.h43
-rw-r--r--libglusterfs/src/event-poll.c513
-rw-r--r--libglusterfs/src/event.c1064
-rw-r--r--libglusterfs/src/event.h81
-rw-r--r--libglusterfs/src/events.c136
-rw-r--r--libglusterfs/src/fd-lk.c663
-rw-r--r--libglusterfs/src/fd-lk.h66
-rw-r--r--libglusterfs/src/fd.c1714
-rw-r--r--libglusterfs/src/fd.h197
-rwxr-xr-xlibglusterfs/src/gen-defaults.py81
-rwxr-xr-xlibglusterfs/src/generator.py777
-rw-r--r--libglusterfs/src/gf-dirent.c315
-rw-r--r--libglusterfs/src/gf-dirent.h57
-rw-r--r--libglusterfs/src/gidcache.c211
-rw-r--r--libglusterfs/src/globals.c567
-rw-r--r--libglusterfs/src/globals.h45
-rw-r--r--libglusterfs/src/glusterfs.h435
-rw-r--r--libglusterfs/src/glusterfs/async.h209
-rw-r--r--libglusterfs/src/glusterfs/atomic.h459
-rw-r--r--libglusterfs/src/glusterfs/byte-order.h279
-rw-r--r--libglusterfs/src/glusterfs/call-stub.h622
-rw-r--r--libglusterfs/src/glusterfs/checksum.h (renamed from libglusterfs/src/checksum.h)6
-rw-r--r--libglusterfs/src/glusterfs/circ-buff.h61
-rw-r--r--libglusterfs/src/glusterfs/client_t.h147
-rw-r--r--libglusterfs/src/glusterfs/cluster-syncop.h227
-rw-r--r--libglusterfs/src/glusterfs/common-utils.h1256
-rw-r--r--libglusterfs/src/glusterfs/compat-errno.h238
-rw-r--r--libglusterfs/src/glusterfs/compat-uuid.h71
-rw-r--r--libglusterfs/src/glusterfs/compat.h544
-rw-r--r--libglusterfs/src/glusterfs/daemon.h (renamed from libglusterfs/src/daemon.h)11
-rw-r--r--libglusterfs/src/glusterfs/default-args.h455
-rw-r--r--libglusterfs/src/glusterfs/defaults.h1275
-rw-r--r--libglusterfs/src/glusterfs/dict.h420
-rw-r--r--libglusterfs/src/glusterfs/event-history.h40
-rw-r--r--libglusterfs/src/glusterfs/events.h34
-rw-r--r--libglusterfs/src/glusterfs/fd-lk.h59
-rw-r--r--libglusterfs/src/glusterfs/fd.h169
-rw-r--r--libglusterfs/src/glusterfs/gf-dirent.h71
-rw-r--r--libglusterfs/src/glusterfs/gf-event.h140
-rw-r--r--libglusterfs/src/glusterfs/gidcache.h60
-rw-r--r--libglusterfs/src/glusterfs/glfs-message-id.h102
-rw-r--r--libglusterfs/src/glusterfs/globals.h188
-rw-r--r--libglusterfs/src/glusterfs/glusterfs-acl.h162
-rw-r--r--libglusterfs/src/glusterfs/glusterfs-fops.h241
-rw-r--r--libglusterfs/src/glusterfs/glusterfs.h838
-rw-r--r--libglusterfs/src/glusterfs/graph-utils.h (renamed from libglusterfs/src/graph-utils.h)12
-rw-r--r--libglusterfs/src/glusterfs/hashfn.h (renamed from libglusterfs/src/hashfn.h)12
-rw-r--r--libglusterfs/src/glusterfs/iatt.h489
-rw-r--r--libglusterfs/src/glusterfs/inode.h306
-rw-r--r--libglusterfs/src/glusterfs/iobuf.h194
-rw-r--r--libglusterfs/src/glusterfs/latency.h33
-rw-r--r--libglusterfs/src/glusterfs/libglusterfs-messages.h245
-rw-r--r--libglusterfs/src/glusterfs/list.h273
-rw-r--r--libglusterfs/src/glusterfs/lkowner.h93
-rw-r--r--libglusterfs/src/glusterfs/locking.h84
-rw-r--r--libglusterfs/src/glusterfs/logging.h383
-rw-r--r--libglusterfs/src/glusterfs/lvm-defaults.h20
-rw-r--r--libglusterfs/src/glusterfs/mem-pool.h336
-rw-r--r--libglusterfs/src/glusterfs/mem-types.h139
-rw-r--r--libglusterfs/src/glusterfs/monitoring.h21
-rw-r--r--libglusterfs/src/glusterfs/options.h327
-rw-r--r--libglusterfs/src/glusterfs/parse-utils.h50
-rw-r--r--libglusterfs/src/glusterfs/quota-common-utils.h68
-rw-r--r--libglusterfs/src/glusterfs/rbthash.h75
-rw-r--r--libglusterfs/src/glusterfs/refcount.h101
-rw-r--r--libglusterfs/src/glusterfs/revision.h1
-rw-r--r--libglusterfs/src/glusterfs/rot-buffs.h125
-rw-r--r--libglusterfs/src/glusterfs/run.h (renamed from libglusterfs/src/run.h)63
-rw-r--r--libglusterfs/src/glusterfs/stack.h555
-rw-r--r--libglusterfs/src/glusterfs/statedump.h132
-rw-r--r--libglusterfs/src/glusterfs/store.h112
-rw-r--r--libglusterfs/src/glusterfs/strfd.h34
-rw-r--r--libglusterfs/src/glusterfs/syncop-utils.h54
-rw-r--r--libglusterfs/src/glusterfs/syncop.h718
-rw-r--r--libglusterfs/src/glusterfs/syscall.h278
-rw-r--r--libglusterfs/src/glusterfs/template-component-messages.h28
-rw-r--r--libglusterfs/src/glusterfs/throttle-tbf.h74
-rw-r--r--libglusterfs/src/glusterfs/timer.h56
-rw-r--r--libglusterfs/src/glusterfs/timespec.h33
-rw-r--r--libglusterfs/src/glusterfs/trie.h52
-rw-r--r--libglusterfs/src/glusterfs/upcall-utils.h110
-rw-r--r--libglusterfs/src/glusterfs/xlator.h1106
-rw-r--r--libglusterfs/src/graph-print.c221
-rw-r--r--libglusterfs/src/graph.c1968
-rw-r--r--libglusterfs/src/graph.l66
-rw-r--r--libglusterfs/src/graph.y273
-rw-r--r--libglusterfs/src/hashfn.c269
-rw-r--r--libglusterfs/src/iatt.h313
-rw-r--r--libglusterfs/src/inode.c3390
-rw-r--r--libglusterfs/src/inode.h202
-rw-r--r--libglusterfs/src/iobuf.c1613
-rw-r--r--libglusterfs/src/iobuf.h161
-rw-r--r--libglusterfs/src/latency.c186
-rw-r--r--libglusterfs/src/latency.h27
-rw-r--r--libglusterfs/src/libglusterfs.sym1193
-rw-r--r--libglusterfs/src/list.h178
-rw-r--r--libglusterfs/src/lkowner.h83
-rw-r--r--libglusterfs/src/locking.c27
-rw-r--r--libglusterfs/src/locking.h40
-rw-r--r--libglusterfs/src/logging.c2760
-rw-r--r--libglusterfs/src/logging.h148
-rw-r--r--libglusterfs/src/mem-pool.c1220
-rw-r--r--libglusterfs/src/mem-pool.h163
-rw-r--r--libglusterfs/src/mem-types.h107
-rw-r--r--libglusterfs/src/monitoring.c282
-rw-r--r--libglusterfs/src/options.c1811
-rw-r--r--libglusterfs/src/options.h242
-rw-r--r--libglusterfs/src/parse-utils.c174
-rw-r--r--libglusterfs/src/quota-common-utils.c241
-rw-r--r--libglusterfs/src/rbthash.c667
-rw-r--r--libglusterfs/src/rbthash.h77
-rw-r--r--libglusterfs/src/refcount.c108
-rw-r--r--libglusterfs/src/revision.h1
-rw-r--r--libglusterfs/src/rot-buffs.c490
-rw-r--r--libglusterfs/src/run.c774
-rw-r--r--libglusterfs/src/scheduler.c82
-rw-r--r--libglusterfs/src/scheduler.h32
-rw-r--r--libglusterfs/src/stack.c646
-rw-r--r--libglusterfs/src/stack.h429
-rw-r--r--libglusterfs/src/statedump.c1333
-rw-r--r--libglusterfs/src/statedump.h85
-rw-r--r--libglusterfs/src/store.c744
-rw-r--r--libglusterfs/src/strfd.c93
-rw-r--r--libglusterfs/src/syncop-utils.c669
-rw-r--r--libglusterfs/src/syncop.c3824
-rw-r--r--libglusterfs/src/syncop.h205
-rw-r--r--libglusterfs/src/syscall.c756
-rw-r--r--libglusterfs/src/syscall.h142
-rw-r--r--libglusterfs/src/throttle-tbf.c290
-rw-r--r--libglusterfs/src/timer.c382
-rw-r--r--libglusterfs/src/timer.h61
-rw-r--r--libglusterfs/src/timespec.c129
-rw-r--r--libglusterfs/src/trie.c491
-rw-r--r--libglusterfs/src/trie.h51
-rw-r--r--libglusterfs/src/unittest/global_mock.c25
-rw-r--r--libglusterfs/src/unittest/log_mock.c52
-rw-r--r--libglusterfs/src/unittest/mem_pool_unittest.c483
-rw-r--r--libglusterfs/src/unittest/unittest.h47
-rw-r--r--libglusterfs/src/xlator.c1879
-rw-r--r--libglusterfs/src/xlator.h877
-rw-r--r--libglusterfsclient/src/Makefile.am16
-rw-r--r--libglusterfsclient/src/libglusterfsclient-dentry.c404
-rwxr-xr-xlibglusterfsclient/src/libglusterfsclient-internals.h289
-rwxr-xr-xlibglusterfsclient/src/libglusterfsclient.c8160
-rwxr-xr-xlibglusterfsclient/src/libglusterfsclient.h1363
-rw-r--r--mod_glusterfs/Makefile.am3
-rw-r--r--mod_glusterfs/apache/1.3/src/Makefile.am30
-rw-r--r--mod_glusterfs/apache/1.3/src/README.txt107
-rw-r--r--mod_glusterfs/apache/1.3/src/mod_glusterfs.c507
-rw-r--r--mod_glusterfs/apache/2.2/src/Makefile.am31
-rw-r--r--mod_glusterfs/apache/2.2/src/README.txt105
-rw-r--r--mod_glusterfs/apache/2.2/src/mod_glusterfs.c3627
-rw-r--r--mod_glusterfs/apache/Makefile.am10
-rw-r--r--mod_glusterfs/lighttpd/1.4/Makefile.am3
-rw-r--r--mod_glusterfs/lighttpd/1.4/Makefile.am.diff29
-rw-r--r--mod_glusterfs/lighttpd/1.4/README.txt57
-rw-r--r--mod_glusterfs/lighttpd/1.4/mod_glusterfs.c1820
-rw-r--r--mod_glusterfs/lighttpd/1.4/mod_glusterfs.h32
-rw-r--r--mod_glusterfs/lighttpd/1.5/Makefile.am3
-rw-r--r--mod_glusterfs/lighttpd/1.5/Makefile.am.diff29
-rw-r--r--mod_glusterfs/lighttpd/1.5/README.txt57
-rw-r--r--mod_glusterfs/lighttpd/1.5/mod_glusterfs.c1476
-rw-r--r--mod_glusterfs/lighttpd/1.5/mod_glusterfs.h29
-rw-r--r--mod_glusterfs/lighttpd/Makefile.am3
-rwxr-xr-xrfc.sh259
-rw-r--r--rpc/Makefile.am2
-rw-r--r--rpc/rpc-lib/src/Makefile.am27
-rw-r--r--rpc/rpc-lib/src/auth-glusterfs.c506
-rw-r--r--rpc/rpc-lib/src/auth-null.c53
-rw-r--r--rpc/rpc-lib/src/auth-unix.c92
-rw-r--r--rpc/rpc-lib/src/autoscale-threads.c22
-rw-r--r--rpc/rpc-lib/src/libgfrpc.sym68
-rw-r--r--rpc/rpc-lib/src/mgmt-pmap.c147
-rw-r--r--rpc/rpc-lib/src/protocol-common.h490
-rw-r--r--rpc/rpc-lib/src/rpc-clnt-ping.c357
-rw-r--r--rpc/rpc-lib/src/rpc-clnt-ping.h16
-rw-r--r--rpc/rpc-lib/src/rpc-clnt.c3078
-rw-r--r--rpc/rpc-lib/src/rpc-clnt.h269
-rw-r--r--rpc/rpc-lib/src/rpc-drc.c855
-rw-r--r--rpc/rpc-lib/src/rpc-drc.h97
-rw-r--r--rpc/rpc-lib/src/rpc-lib-messages.h34
-rw-r--r--rpc/rpc-lib/src/rpc-transport.c944
-rw-r--r--rpc/rpc-lib/src/rpc-transport.h320
-rw-r--r--rpc/rpc-lib/src/rpcsvc-auth.c786
-rw-r--r--rpc/rpc-lib/src/rpcsvc-common.h116
-rw-r--r--rpc/rpc-lib/src/rpcsvc.c4549
-rw-r--r--rpc/rpc-lib/src/rpcsvc.h801
-rw-r--r--rpc/rpc-lib/src/xdr-common.h77
-rw-r--r--rpc/rpc-lib/src/xdr-rpc.c272
-rw-r--r--rpc/rpc-lib/src/xdr-rpc.h82
-rw-r--r--rpc/rpc-lib/src/xdr-rpcclnt.c130
-rw-r--r--rpc/rpc-lib/src/xdr-rpcclnt.h28
-rw-r--r--rpc/rpc-transport/Makefile.am2
-rw-r--r--rpc/rpc-transport/rdma/src/Makefile.am20
-rw-r--r--rpc/rpc-transport/rdma/src/name.c698
-rw-r--r--rpc/rpc-transport/rdma/src/name.h39
-rw-r--r--rpc/rpc-transport/rdma/src/rdma.c4942
-rw-r--r--rpc/rpc-transport/rdma/src/rdma.h403
-rw-r--r--rpc/rpc-transport/socket/src/Makefile.am19
-rw-r--r--rpc/rpc-transport/socket/src/name.c1175
-rw-r--r--rpc/rpc-transport/socket/src/name.h22
-rw-r--r--rpc/rpc-transport/socket/src/socket-mem-types.h22
-rw-r--r--rpc/rpc-transport/socket/src/socket.c6270
-rw-r--r--rpc/rpc-transport/socket/src/socket.h322
-rw-r--r--rpc/xdr/src/.gitignore25
-rw-r--r--rpc/xdr/src/Makefile.am107
-rw-r--r--rpc/xdr/src/acl3-xdr.x52
-rw-r--r--rpc/xdr/src/changelog-xdr.x42
-rw-r--r--rpc/xdr/src/cli1-xdr.c459
-rw-r--r--rpc/xdr/src/cli1-xdr.h369
-rw-r--r--rpc/xdr/src/cli1-xdr.x245
-rw-r--r--rpc/xdr/src/glusterd1-xdr.c502
-rw-r--r--rpc/xdr/src/glusterd1-xdr.h264
-rw-r--r--rpc/xdr/src/glusterd1-xdr.x122
-rw-r--r--rpc/xdr/src/glusterfs3-xdr.c1922
-rw-r--r--rpc/xdr/src/glusterfs3-xdr.h1295
-rw-r--r--rpc/xdr/src/glusterfs3-xdr.x446
-rw-r--r--rpc/xdr/src/glusterfs3.h1113
-rw-r--r--rpc/xdr/src/glusterfs4-xdr.x797
-rw-r--r--rpc/xdr/src/libgfxdr.sym350
-rw-r--r--rpc/xdr/src/mount3udp.x26
-rw-r--r--rpc/xdr/src/msg-nfs3.c467
-rw-r--r--rpc/xdr/src/msg-nfs3.h163
-rw-r--r--rpc/xdr/src/nlm4-xdr.c254
-rw-r--r--rpc/xdr/src/nlm4-xdr.h254
-rw-r--r--rpc/xdr/src/nlm4-xdr.x (renamed from rpc/xdr/src/nlm4.x)78
-rw-r--r--rpc/xdr/src/nlmcbk-xdr.c37
-rw-r--r--rpc/xdr/src/nlmcbk-xdr.h74
-rw-r--r--rpc/xdr/src/nlmcbk.x33
-rw-r--r--rpc/xdr/src/nsm-xdr.c105
-rw-r--r--rpc/xdr/src/nsm-xdr.h95
-rw-r--r--rpc/xdr/src/nsm-xdr.x (renamed from rpc/xdr/src/nsm.x)19
-rw-r--r--rpc/xdr/src/portmap-xdr.c246
-rw-r--r--rpc/xdr/src/portmap-xdr.h139
-rw-r--r--rpc/xdr/src/portmap-xdr.x27
-rw-r--r--rpc/xdr/src/rpc-common-xdr.c232
-rw-r--r--rpc/xdr/src/rpc-common-xdr.h113
-rw-r--r--rpc/xdr/src/rpc-common-xdr.x37
-rw-r--r--rpc/xdr/src/rpc-pragmas.h28
-rw-r--r--rpc/xdr/src/xdr-generic.c148
-rw-r--r--rpc/xdr/src/xdr-generic.h78
-rw-r--r--rpc/xdr/src/xdr-nfs3.c2620
-rw-r--r--rpc/xdr/src/xdr-nfs3.h1447
-rwxr-xr-xrun-tests-in-vagrant.sh311
-rwxr-xr-xrun-tests.sh615
-rw-r--r--scheduler/Makefile.am3
-rw-r--r--scheduler/alu/src/Makefile.am14
-rw-r--r--scheduler/alu/src/alu-mem-types.h35
-rw-r--r--scheduler/alu/src/alu.c1019
-rw-r--r--scheduler/alu/src/alu.h89
-rw-r--r--scheduler/nufa/src/Makefile.am12
-rw-r--r--scheduler/nufa/src/nufa-mem-types.h33
-rw-r--r--scheduler/nufa/src/nufa.c429
-rw-r--r--scheduler/random/src/Makefile.am14
-rw-r--r--scheduler/random/src/random-mem-types.h32
-rw-r--r--scheduler/random/src/random.c305
-rw-r--r--scheduler/random/src/random.h46
-rw-r--r--scheduler/rr/Makefile.am3
-rw-r--r--scheduler/rr/src/Makefile.am13
-rw-r--r--scheduler/rr/src/rr-mem-types.h32
-rw-r--r--scheduler/rr/src/rr-options.c256
-rw-r--r--scheduler/rr/src/rr-options.h34
-rw-r--r--scheduler/rr/src/rr.c567
-rw-r--r--scheduler/rr/src/rr.h70
-rw-r--r--scheduler/switch/Makefile.am3
-rw-r--r--scheduler/switch/src/Makefile.am12
-rw-r--r--scheduler/switch/src/switch-mem-types.h33
-rw-r--r--scheduler/switch/src/switch.c451
-rw-r--r--site.h.in44
-rwxr-xr-xsmoke.sh83
l---------submit-for-review.sh1
-rw-r--r--swift/1.4.8/README22
-rw-r--r--swift/1.4.8/gluster-swift-plugin.spec60
-rw-r--r--swift/1.4.8/gluster-swift.spec396
-rw-r--r--swift/1.4.8/plugins/DiskDir.py484
-rw-r--r--swift/1.4.8/plugins/DiskFile.py316
-rw-r--r--swift/1.4.8/plugins/Glusterfs.py131
-rw-r--r--swift/1.4.8/plugins/__init__.py16
-rw-r--r--swift/1.4.8/plugins/conf/account-server/1.conf22
-rw-r--r--swift/1.4.8/plugins/conf/account.builderbin786843 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/account.ring.gzbin739 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/container-server/1.conf24
-rw-r--r--swift/1.4.8/plugins/conf/container.builderbin786843 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/container.ring.gzbin741 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/fs.conf9
-rw-r--r--swift/1.4.8/plugins/conf/object-server/1.conf22
-rw-r--r--swift/1.4.8/plugins/conf/object.builderbin786843 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/object.ring.gzbin738 -> 0 bytes-rw-r--r--swift/1.4.8/plugins/conf/proxy-server.conf21
-rw-r--r--swift/1.4.8/plugins/conf/swift.conf7
-rw-r--r--swift/1.4.8/plugins/constraints.py97
-rw-r--r--swift/1.4.8/plugins/utils.py679
-rw-r--r--swift/1.4.8/swift.diff797
-rw-r--r--tests/00-geo-rep/00-georep-verify-non-root-setup.t294
-rw-r--r--tests/00-geo-rep/00-georep-verify-setup.t110
-rw-r--r--tests/00-geo-rep/01-georep-glusterd-tests.t213
-rw-r--r--tests/00-geo-rep/bug-1600145.t109
-rw-r--r--tests/00-geo-rep/bug-1708603.t63
-rw-r--r--tests/00-geo-rep/georep-basic-dr-rsync-arbiter.t234
-rw-r--r--tests/00-geo-rep/georep-basic-dr-rsync.t258
-rw-r--r--tests/00-geo-rep/georep-basic-dr-tarssh-arbiter.t227
-rw-r--r--tests/00-geo-rep/georep-basic-dr-tarssh.t227
-rw-r--r--tests/00-geo-rep/georep-basic-rsync-ec.t224
-rw-r--r--tests/00-geo-rep/georep-basic-tarssh-ec.t223
-rw-r--r--tests/00-geo-rep/georep-config-upgrade.t132
-rw-r--r--tests/00-geo-rep/georep-stderr-hang.t128
-rw-r--r--tests/00-geo-rep/georep-upgrade.t79
-rw-r--r--tests/00-geo-rep/gsyncd.conf.old47
-rw-r--r--tests/000-flaky/basic_afr_split-brain-favorite-child-policy.t203
-rw-r--r--tests/000-flaky/basic_changelog_changelog-snapshot.t60
-rw-r--r--tests/000-flaky/basic_distribute_rebal-all-nodes-migrate.t142
-rw-r--r--tests/000-flaky/basic_ec_ec-quorum-count-partial-failure.t50
-rw-r--r--tests/000-flaky/basic_mount-nfs-auth.t342
-rw-r--r--tests/000-flaky/bugs_core_multiplex-limit-issue-151.t56
-rw-r--r--tests/000-flaky/bugs_distribute_bug-1117851.t101
-rw-r--r--tests/000-flaky/bugs_distribute_bug-1122443.t61
-rw-r--r--tests/000-flaky/bugs_glusterd_bug-857330/common.rc57
-rwxr-xr-xtests/000-flaky/bugs_glusterd_bug-857330/normal.t69
-rwxr-xr-xtests/000-flaky/bugs_glusterd_bug-857330/xml.t83
-rw-r--r--tests/000-flaky/bugs_glusterd_quorum-value-check.t37
-rw-r--r--tests/000-flaky/bugs_nfs_bug-1116503.t47
-rw-r--r--tests/000-flaky/features_lock-migration_lkmigration-set-option.t34
-rw-r--r--tests/README.md43
-rw-r--r--tests/afr.rc123
-rwxr-xr-xtests/basic/0symbol-check.t46
-rw-r--r--tests/basic/afr/add-brick-self-heal.t74
-rw-r--r--tests/basic/afr/afr-anon-inode-no-quorum.t63
-rw-r--r--tests/basic/afr/afr-anon-inode.t114
-rw-r--r--tests/basic/afr/afr-no-fsync.t20
-rw-r--r--tests/basic/afr/afr-read-hash-mode.t56
-rw-r--r--tests/basic/afr/afr-seek.t55
-rw-r--r--tests/basic/afr/afr-up.t28
-rw-r--r--tests/basic/afr/arbiter-add-brick.t86
-rw-r--r--tests/basic/afr/arbiter-cli.t30
-rw-r--r--tests/basic/afr/arbiter-mount.t48
-rw-r--r--tests/basic/afr/arbiter-remove-brick.t36
-rw-r--r--tests/basic/afr/arbiter-statfs.t41
-rw-r--r--tests/basic/afr/arbiter.t92
-rwxr-xr-xtests/basic/afr/client-side-heal.t95
-rw-r--r--tests/basic/afr/data-self-heal.t209
-rw-r--r--tests/basic/afr/durability-off.t46
-rw-r--r--tests/basic/afr/entry-self-heal-anon-dir-off.t459
-rw-r--r--tests/basic/afr/entry-self-heal.t447
-rw-r--r--tests/basic/afr/gfid-heal.t33
-rw-r--r--tests/basic/afr/gfid-mismatch-resolution-with-cli.t168
-rw-r--r--tests/basic/afr/gfid-mismatch-resolution-with-fav-child-policy.t229
-rw-r--r--tests/basic/afr/gfid-mismatch.t32
-rw-r--r--tests/basic/afr/gfid-self-heal.t145
-rw-r--r--tests/basic/afr/granular-esh/add-brick.t80
-rw-r--r--tests/basic/afr/granular-esh/cli.t114
-rw-r--r--tests/basic/afr/granular-esh/conservative-merge.t138
-rw-r--r--tests/basic/afr/granular-esh/granular-esh.t168
-rw-r--r--tests/basic/afr/granular-esh/granular-indices-but-non-granular-heal.t76
-rw-r--r--tests/basic/afr/granular-esh/replace-brick.t76
-rw-r--r--tests/basic/afr/halo.t61
-rw-r--r--tests/basic/afr/heal-info.t36
-rw-r--r--tests/basic/afr/heal-quota.t35
-rw-r--r--tests/basic/afr/inodelk.t87
-rw-r--r--tests/basic/afr/lk-quorum.t257
-rw-r--r--tests/basic/afr/metadata-self-heal.t133
-rw-r--r--tests/basic/afr/name-self-heal.t112
-rw-r--r--tests/basic/afr/quorum.t97
-rw-r--r--tests/basic/afr/read-subvol-data.t33
-rw-r--r--tests/basic/afr/read-subvol-entry.t35
-rw-r--r--tests/basic/afr/rename-data-loss.t72
-rw-r--r--tests/basic/afr/replace-brick-self-heal.t64
-rw-r--r--tests/basic/afr/resolve.t55
-rw-r--r--tests/basic/afr/root-squash-self-heal.t27
-rw-r--r--tests/basic/afr/self-heal.t244
-rw-r--r--tests/basic/afr/self-heald.t193
-rw-r--r--tests/basic/afr/sparse-file-self-heal.t181
-rw-r--r--tests/basic/afr/split-brain-favorite-child-policy-client-side-healing.t124
-rw-r--r--tests/basic/afr/split-brain-heal-info.t62
-rw-r--r--tests/basic/afr/split-brain-healing-ctime.t252
-rw-r--r--tests/basic/afr/split-brain-healing.t261
-rw-r--r--tests/basic/afr/split-brain-open.t38
-rw-r--r--tests/basic/afr/split-brain-resolution.t105
-rw-r--r--tests/basic/afr/stale-file-lookup.t30
-rw-r--r--tests/basic/afr/ta-check-locks.t68
-rw-r--r--tests/basic/afr/ta-read.t64
-rw-r--r--tests/basic/afr/ta-shd.t49
-rw-r--r--tests/basic/afr/ta-write-on-bad-brick.t51
-rw-r--r--tests/basic/afr/ta.t54
-rw-r--r--tests/basic/afr/tarissue.t39
-rw-r--r--tests/basic/all_squash.t74
-rwxr-xr-xtests/basic/cdc.t148
-rw-r--r--tests/basic/changelog/changelog-api.t37
-rw-r--r--tests/basic/changelog/changelog-history.t91
-rw-r--r--tests/basic/changelog/changelog-rename.t44
-rw-r--r--tests/basic/changelog/history-api.t42
-rw-r--r--tests/basic/cloudsync-sanity.t29
-rw-r--r--tests/basic/ctime/ctime-ec-heal.t70
-rw-r--r--tests/basic/ctime/ctime-ec-rebalance.t43
-rw-r--r--tests/basic/ctime/ctime-glfs-init.c68
-rw-r--r--tests/basic/ctime/ctime-glfs-init.t23
-rw-r--r--tests/basic/ctime/ctime-heal-symlinks.t65
-rw-r--r--tests/basic/ctime/ctime-mdata-legacy-files.t83
-rw-r--r--tests/basic/ctime/ctime-noatime.t49
-rw-r--r--tests/basic/ctime/ctime-readdir.c29
-rw-r--r--tests/basic/ctime/ctime-readdir.t50
-rw-r--r--tests/basic/ctime/ctime-rep-heal.t70
-rw-r--r--tests/basic/ctime/ctime-rep-rebalance.t41
-rw-r--r--tests/basic/ctime/ctime-utimesat.t28
-rw-r--r--tests/basic/distribute/brick-down.t83
-rw-r--r--tests/basic/distribute/bug-1265677-use-readdirp.t38
-rw-r--r--tests/basic/distribute/debug-xattrs.t54
-rw-r--r--tests/basic/distribute/dir-heal.t145
-rw-r--r--tests/basic/distribute/file-create.t120
-rw-r--r--tests/basic/distribute/file-rename.t1021
-rw-r--r--tests/basic/distribute/force-migration.t50
-rw-r--r--tests/basic/distribute/lookup.t54
-rw-r--r--tests/basic/distribute/non-root-unlink-stale-linkto.t51
-rw-r--r--tests/basic/distribute/spare_file_rebalance.t51
-rw-r--r--tests/basic/distribute/throttle-rebal.t56
-rw-r--r--tests/basic/ec/dht-rename.t19
-rw-r--r--tests/basic/ec/ec-1468261.t95
-rw-r--r--tests/basic/ec/ec-3-1.t14
-rw-r--r--tests/basic/ec/ec-4-1.t14
-rw-r--r--tests/basic/ec/ec-5-2.t14
-rw-r--r--tests/basic/ec/ec-6-2.t14
-rw-r--r--tests/basic/ec/ec-anonymous-fd.t42
-rw-r--r--tests/basic/ec/ec-background-heals.t105
-rw-r--r--tests/basic/ec/ec-badfd.c124
-rwxr-xr-xtests/basic/ec/ec-badfd.t26
-rw-r--r--tests/basic/ec/ec-common145
-rw-r--r--tests/basic/ec/ec-cpu-extensions.t62
-rwxr-xr-xtests/basic/ec/ec-data-heal.t75
-rw-r--r--tests/basic/ec/ec-dirty-flags.t23
-rw-r--r--tests/basic/ec/ec-discard.t205
-rw-r--r--tests/basic/ec/ec-fallocate.t72
-rw-r--r--tests/basic/ec/ec-fast-fgetxattr.c129
-rwxr-xr-xtests/basic/ec/ec-fast-fgetxattr.t40
-rw-r--r--tests/basic/ec/ec-fix-openfd.t111
-rw-r--r--tests/basic/ec/ec-internal-xattrs.t45
-rw-r--r--tests/basic/ec/ec-new-entry.t70
-rw-r--r--tests/basic/ec/ec-notify.t101
-rw-r--r--tests/basic/ec/ec-optimistic-changelog.t153
-rw-r--r--tests/basic/ec/ec-quorum-count.t167
-rw-r--r--tests/basic/ec/ec-read-mask.t114
-rw-r--r--tests/basic/ec/ec-read-policy.t52
-rw-r--r--tests/basic/ec/ec-readdir.t46
-rw-r--r--tests/basic/ec/ec-rebalance.t61
-rw-r--r--tests/basic/ec/ec-reset-brick.t50
-rw-r--r--tests/basic/ec/ec-root-heal.t34
-rw-r--r--tests/basic/ec/ec-seek.t58
-rw-r--r--tests/basic/ec/ec-stripe.t227
-rw-r--r--tests/basic/ec/ec-up.t28
-rw-r--r--tests/basic/ec/ec.t259
-rw-r--r--tests/basic/ec/gfapi-ec-open-truncate.c171
-rw-r--r--tests/basic/ec/gfapi-ec-open-truncate.t48
-rw-r--r--tests/basic/ec/heal-info.t74
-rw-r--r--tests/basic/ec/lock-contention.t62
-rwxr-xr-xtests/basic/ec/nfs.t29
-rwxr-xr-xtests/basic/ec/quota.t45
-rw-r--r--tests/basic/ec/self-heal-read-write-fail.t69
-rw-r--r--tests/basic/ec/self-heal.t235
-rw-r--r--tests/basic/ec/statedump.t28
-rw-r--r--tests/basic/exports_parsing.t57
-rw-r--r--tests/basic/fencing/afr-lock-heal-advanced.c227
-rw-r--r--tests/basic/fencing/afr-lock-heal-advanced.t115
-rw-r--r--tests/basic/fencing/afr-lock-heal-basic.c182
-rw-r--r--tests/basic/fencing/afr-lock-heal-basic.t102
-rw-r--r--tests/basic/fencing/fence-basic.c229
-rwxr-xr-xtests/basic/fencing/fence-basic.t31
-rw-r--r--tests/basic/fencing/fencing-crash-conistency.t62
-rw-r--r--tests/basic/fencing/test-fence-option.t37
-rw-r--r--tests/basic/fop-sampling.t61
-rw-r--r--tests/basic/fops-sanity.c1033
-rwxr-xr-xtests/basic/fops-sanity.t27
-rw-r--r--tests/basic/fuse/Makefile12
-rw-r--r--tests/basic/fuse/active-io-graph-switch.t65
-rw-r--r--tests/basic/fuse/seek.c82
-rwxr-xr-xtests/basic/geo-replication/marker-xattrs.t80
-rw-r--r--tests/basic/gfapi/Makefile22
-rwxr-xr-xtests/basic/gfapi/anonymous_fd.t26
-rw-r--r--tests/basic/gfapi/anonymous_fd_read_write.c106
-rw-r--r--tests/basic/gfapi/bug-1241104.c93
-rwxr-xr-xtests/basic/gfapi/bug-1241104.t30
-rw-r--r--tests/basic/gfapi/bug-1507896.c49
-rw-r--r--tests/basic/gfapi/bug-1507896.t33
-rw-r--r--tests/basic/gfapi/bug1283983.c122
-rwxr-xr-xtests/basic/gfapi/bug1283983.sh33
-rw-r--r--tests/basic/gfapi/bug1291259.c181
-rwxr-xr-xtests/basic/gfapi/bug1291259.t32
-rw-r--r--tests/basic/gfapi/bug1613098.c96
-rwxr-xr-xtests/basic/gfapi/bug1613098.t22
-rw-r--r--tests/basic/gfapi/gfapi-async-calls-test.c494
-rw-r--r--tests/basic/gfapi/gfapi-async-calls-test.t26
-rw-r--r--tests/basic/gfapi/gfapi-copy-file-range.t82
-rw-r--r--tests/basic/gfapi/gfapi-dup.c84
-rwxr-xr-xtests/basic/gfapi/gfapi-dup.t27
-rw-r--r--tests/basic/gfapi/gfapi-graph-switch-open-fd.t44
-rw-r--r--tests/basic/gfapi/gfapi-keep-writing.c129
-rw-r--r--tests/basic/gfapi/gfapi-load-volfile.c65
-rw-r--r--tests/basic/gfapi/gfapi-load-volfile.t28
-rw-r--r--tests/basic/gfapi/gfapi-ssl-load-volfile-test.c127
-rwxr-xr-xtests/basic/gfapi/gfapi-ssl-load-volfile-test.t76
-rw-r--r--tests/basic/gfapi/gfapi-ssl-test.c124
-rwxr-xr-xtests/basic/gfapi/gfapi-ssl-test.t61
-rw-r--r--tests/basic/gfapi/gfapi-statx-basic.c184
-rwxr-xr-xtests/basic/gfapi/gfapi-statx-basic.t30
-rw-r--r--tests/basic/gfapi/gfapi-trunc.c89
-rw-r--r--tests/basic/gfapi/gfapi-trunc.t22
-rw-r--r--tests/basic/gfapi/glfd-lkowner.c214
-rwxr-xr-xtests/basic/gfapi/glfd-lkowner.t27
-rw-r--r--tests/basic/gfapi/glfs-copy-file-range.c180
-rw-r--r--tests/basic/gfapi/glfs_h_creat_open.c118
-rwxr-xr-xtests/basic/gfapi/glfs_h_creat_open.t27
-rw-r--r--tests/basic/gfapi/glfs_sysrq.c60
-rwxr-xr-xtests/basic/gfapi/glfs_sysrq.t39
-rw-r--r--tests/basic/gfapi/glfs_xreaddirplus_r.c242
-rwxr-xr-xtests/basic/gfapi/glfs_xreaddirplus_r.t28
-rw-r--r--tests/basic/gfapi/glfsxmp-coverage.c1900
-rw-r--r--tests/basic/gfapi/glfsxmp.t30
-rw-r--r--tests/basic/gfapi/libgfapi-fini-hang.c62
-rwxr-xr-xtests/basic/gfapi/libgfapi-fini-hang.t42
-rw-r--r--tests/basic/gfapi/mandatory-lock-optimal.c532
-rw-r--r--tests/basic/gfapi/mandatory-lock-optimal.t38
-rw-r--r--tests/basic/gfapi/protocol-client-ssl.vol.in15
-rw-r--r--tests/basic/gfapi/protocol-client.vol.in14
-rw-r--r--tests/basic/gfapi/seek.c99
-rw-r--r--tests/basic/gfapi/sink.t13
-rw-r--r--tests/basic/gfapi/sink.vol24
-rw-r--r--tests/basic/gfapi/upcall-cache-invalidate.c209
-rwxr-xr-xtests/basic/gfapi/upcall-cache-invalidate.t30
-rw-r--r--tests/basic/gfapi/upcall-register-api.c286
-rwxr-xr-xtests/basic/gfapi/upcall-register-api.t30
-rw-r--r--tests/basic/gfid-access.t80
-rwxr-xr-xtests/basic/gfproxy.t71
-rw-r--r--tests/basic/global-threading.t104
-rw-r--r--tests/basic/glusterd-restart-shd-mux.t96
-rw-r--r--tests/basic/glusterd/arbiter-volume-probe.t25
-rw-r--r--tests/basic/glusterd/check-cloudsync-ancestry.t48
-rw-r--r--tests/basic/glusterd/disperse-create.t73
-rw-r--r--tests/basic/glusterd/heald.t92
-rw-r--r--tests/basic/glusterd/thin-arbiter-volume-probe.t25
-rw-r--r--tests/basic/glusterd/thin-arbiter-volume.t45
-rw-r--r--tests/basic/glusterd/volfile_server_switch.t46
-rw-r--r--tests/basic/glusterd/volume-brick-count.t61
-rw-r--r--tests/basic/glusterfsd-args.t5
-rw-r--r--tests/basic/graph-cleanup-brick-down-shd-mux.t64
-rw-r--r--tests/basic/hardlink-limit.t44
-rw-r--r--tests/basic/inode-leak.t31
-rw-r--r--tests/basic/inode-quota-enforcing.t100
-rw-r--r--tests/basic/ios-dump.t43
-rw-r--r--tests/basic/jbr/jbr-volgen.t39
-rwxr-xr-xtests/basic/jbr/jbr.t38
-rw-r--r--tests/basic/logchecks-messages.h105
-rw-r--r--tests/basic/logchecks.c214
-rw-r--r--tests/basic/md-cache/bug-1317785.t34
-rwxr-xr-xtests/basic/md-cache/bug-1418249.t20
-rwxr-xr-xtests/basic/meta.t45
-rw-r--r--tests/basic/metadisp/fsyncdir.c29
-rw-r--r--tests/basic/metadisp/ftruncate.c34
-rw-r--r--tests/basic/metadisp/fxattr.c107
-rw-r--r--tests/basic/metadisp/gfs-fsetxattr.c141
-rw-r--r--tests/basic/metadisp/metadisp.t316
-rw-r--r--tests/basic/metadisp/metadisp.vol14
-rw-r--r--tests/basic/mgmt_v3-locks.t120
-rw-r--r--tests/basic/mount-options.disabled143
-rwxr-xr-xtests/basic/mount.t85
-rw-r--r--tests/basic/mpx-compat.t53
-rw-r--r--tests/basic/multiple-volume-shd-mux.t46
-rw-r--r--tests/basic/multiplex.t78
-rw-r--r--tests/basic/namespace.t131
-rw-r--r--tests/basic/netgroup_parsing.t56
-rwxr-xr-xtests/basic/nl-cache.t98
-rw-r--r--tests/basic/nufa.t41
-rwxr-xr-xtests/basic/op_errnos.t34
-rw-r--r--tests/basic/open-behind/open-behind.t183
-rw-r--r--tests/basic/open-behind/tester-fd.c99
-rw-r--r--tests/basic/open-behind/tester.c444
-rw-r--r--tests/basic/open-behind/tester.h145
-rw-r--r--tests/basic/open-fd-snap-delete.t74
-rw-r--r--tests/basic/peer-parsing.t52
-rw-r--r--tests/basic/pgfid-feat.t35
-rwxr-xr-xtests/basic/playground/template-xlator-sanity.t43
-rw-r--r--tests/basic/posix/shared-statfs.t58
-rw-r--r--tests/basic/posix/zero-fill-enospace.c67
-rw-r--r--tests/basic/posix/zero-fill-enospace.t35
-rwxr-xr-xtests/basic/posixonly.t31
-rw-r--r--tests/basic/quick-read-with-upcall.t72
-rwxr-xr-xtests/basic/quota-ancestry-building.t71
-rwxr-xr-xtests/basic/quota-anon-fd-nfs.t117
-rwxr-xr-xtests/basic/quota-nfs.t66
-rw-r--r--tests/basic/quota-rename.t37
-rw-r--r--tests/basic/quota.c89
-rwxr-xr-xtests/basic/quota.t236
-rwxr-xr-xtests/basic/quota_aux_mount.t53
-rwxr-xr-xtests/basic/rpc-coverage.sh (renamed from extras/rpc-coverage.sh)57
-rwxr-xr-xtests/basic/rpc-coverage.t25
-rw-r--r--tests/basic/sdfs-sanity.t28
-rw-r--r--tests/basic/seek.c182
-rw-r--r--tests/basic/shd-mux-afr.t70
-rw-r--r--tests/basic/shd-mux-ec.t75
-rw-r--r--tests/basic/stats-dump.t55
-rwxr-xr-xtests/basic/symbol-check.sh114
-rwxr-xr-xtests/basic/trace.t55
-rw-r--r--tests/basic/uss.t421
-rw-r--r--tests/basic/volfile-sanity.t29
-rw-r--r--tests/basic/volume-scale-shd-mux.t116
-rw-r--r--tests/basic/volume-snap-scheduler.t49
-rwxr-xr-xtests/basic/volume-snapshot-clone.t129
-rwxr-xr-xtests/basic/volume-snapshot-xml.t72
-rwxr-xr-xtests/basic/volume-snapshot.t172
-rw-r--r--tests/basic/volume-status.t114
-rw-r--r--tests/basic/volume.t60
-rw-r--r--tests/basic/xlator-pass-through-sanity.t22
-rw-r--r--tests/bitrot/br-signer-threads-config-1797869.t73
-rw-r--r--tests/bitrot/br-state-check.t83
-rw-r--r--tests/bitrot/br-stub.c195
-rw-r--r--tests/bitrot/br-stub.t66
-rw-r--r--tests/bitrot/bug-1207627-bitrot-scrub-status.t52
-rw-r--r--tests/bitrot/bug-1221914.t51
-rw-r--r--tests/bitrot/bug-1244613.t95
-rw-r--r--tests/bitrot/bug-1294786.t95
-rw-r--r--tests/bitrot/bug-1373520.t71
-rw-r--r--tests/bitrot/bug-1700078.t87
-rw-r--r--tests/bitrot/bug-internal-xattrs-check-1243391.t42
-rw-r--r--tests/bugs/access-control/bug-1051896.c94
-rw-r--r--tests/bugs/access-control/bug-1051896.t34
-rw-r--r--tests/bugs/access-control/bug-1387241.c18
-rw-r--r--tests/bugs/access-control/bug-1387241.t36
-rw-r--r--tests/bugs/access-control/bug-887098-gmount-crash.t42
-rw-r--r--tests/bugs/access-control/bug-958691.t52
-rwxr-xr-xtests/bugs/bitrot/1207029-bitrot-daemon-should-start-on-valid-node.t57
-rw-r--r--tests/bugs/bitrot/1209751-bitrot-scrub-tunable-reset.t48
-rw-r--r--tests/bugs/bitrot/1209752-volume-status-should-show-bitrot-scrub-info.t70
-rw-r--r--tests/bugs/bitrot/1209818-vol-info-show-scrub-process-properly.t48
-rw-r--r--tests/bugs/bitrot/bug-1210684-scrub-pause-resume-error-handling.t39
-rw-r--r--tests/bugs/bitrot/bug-1227996.t57
-rw-r--r--tests/bugs/bitrot/bug-1228680.t48
-rw-r--r--tests/bugs/bitrot/bug-1229134-bitd-not-support-vol-set.t38
-rw-r--r--tests/bugs/bitrot/bug-1245981.t55
-rw-r--r--tests/bugs/bitrot/bug-1288490.t48
-rwxr-xr-xtests/bugs/bug-1064147.t72
-rw-r--r--tests/bugs/bug-1110262.t72
-rw-r--r--tests/bugs/bug-1138841.t25
-rwxr-xr-xtests/bugs/bug-1258069.t30
-rw-r--r--tests/bugs/bug-1368312.t86
-rw-r--r--tests/bugs/bug-1371806.t81
-rw-r--r--tests/bugs/bug-1371806_1.t48
-rw-r--r--tests/bugs/bug-1371806_2.t52
-rw-r--r--tests/bugs/bug-1371806_3.t63
-rw-r--r--tests/bugs/bug-1371806_acl.t96
-rw-r--r--tests/bugs/bug-1584517.t70
-rw-r--r--tests/bugs/bug-1620580.t67
-rw-r--r--tests/bugs/bug-1694920.t63
-rw-r--r--tests/bugs/bug-1702299.t67
-rwxr-xr-xtests/bugs/changelog/bug-1208470.t40
-rw-r--r--tests/bugs/changelog/bug-1211327.t46
-rw-r--r--tests/bugs/changelog/bug-1225542.t30
-rw-r--r--tests/bugs/changelog/bug-1321955.t60
-rw-r--r--tests/bugs/cli/bug-1004218.t26
-rw-r--r--tests/bugs/cli/bug-1022905.t37
-rw-r--r--tests/bugs/cli/bug-1030580.t53
-rw-r--r--tests/bugs/cli/bug-1047378.t12
-rw-r--r--tests/bugs/cli/bug-1047416.t71
-rw-r--r--tests/bugs/cli/bug-1077682.t24
-rwxr-xr-xtests/bugs/cli/bug-1087487.t23
-rw-r--r--tests/bugs/cli/bug-1113476.t45
-rw-r--r--tests/bugs/cli/bug-1169302.c79
-rwxr-xr-xtests/bugs/cli/bug-1169302.t55
-rwxr-xr-xtests/bugs/cli/bug-1320388.t44
-rw-r--r--tests/bugs/cli/bug-1353156-get-state-cli-validations.t147
-rw-r--r--tests/bugs/cli/bug-1378842-volume-get-all.t23
-rw-r--r--tests/bugs/cli/bug-764638.t13
-rwxr-xr-xtests/bugs/cli/bug-822830.t64
-rw-r--r--tests/bugs/cli/bug-867252.t41
-rwxr-xr-xtests/bugs/cli/bug-921215.t13
-rw-r--r--tests/bugs/cli/bug-949298.t12
-rw-r--r--tests/bugs/cli/bug-961307.t20
-rwxr-xr-xtests/bugs/cli/bug-969193.t13
-rw-r--r--tests/bugs/cli/bug-977246.t21
-rw-r--r--tests/bugs/cli/bug-982174.t36
-rw-r--r--tests/bugs/cli/bug-983317-volume-get.t45
-rw-r--r--tests/bugs/core/949327.t23
-rw-r--r--tests/bugs/core/brick-mux-fd-cleanup.t78
-rw-r--r--tests/bugs/core/bug-1110917.t39
-rw-r--r--tests/bugs/core/bug-1111557.t12
-rw-r--r--tests/bugs/core/bug-1117951.t24
-rw-r--r--tests/bugs/core/bug-1119582.t24
-rw-r--r--tests/bugs/core/bug-1135514-allow-setxattr-with-null-value.t18
-rwxr-xr-xtests/bugs/core/bug-1168803-snapd-option-validation-fix.t30
-rwxr-xr-xtests/bugs/core/bug-1402841.t-mt-dir-scan-race.t42
-rw-r--r--tests/bugs/core/bug-1421721-mpx-toggle.t25
-rw-r--r--tests/bugs/core/bug-1432542-mpx-restart-crash.t116
-rw-r--r--tests/bugs/core/bug-1650403.t113
-rw-r--r--tests/bugs/core/bug-1699025-brick-mux-detach-brick-fd-issue.t33
-rw-r--r--tests/bugs/core/bug-834465.c60
-rwxr-xr-xtests/bugs/core/bug-834465.t51
-rw-r--r--tests/bugs/core/bug-845213.t19
-rw-r--r--tests/bugs/core/bug-903336.t13
-rwxr-xr-xtests/bugs/core/bug-908146.t30
-rw-r--r--tests/bugs/core/bug-913544.t24
-rwxr-xr-xtests/bugs/core/bug-924075.t23
-rwxr-xr-xtests/bugs/core/bug-927616.t65
-rw-r--r--tests/bugs/core/bug-949242.t55
-rw-r--r--tests/bugs/core/bug-986429.t19
-rwxr-xr-xtests/bugs/core/io-stats-1322825.t67
-rwxr-xr-xtests/bugs/core/log-bug-1362520.t43
-rwxr-xr-xtests/bugs/ctime/issue-832.t32
-rw-r--r--tests/bugs/distribute/bug-1042725.t49
-rwxr-xr-xtests/bugs/distribute/bug-1066798.t88
-rwxr-xr-xtests/bugs/distribute/bug-1086228.t34
-rwxr-xr-xtests/bugs/distribute/bug-1088231.t173
-rw-r--r--tests/bugs/distribute/bug-1099890.t130
-rwxr-xr-xtests/bugs/distribute/bug-1125824.t103
-rwxr-xr-xtests/bugs/distribute/bug-1161156.t58
-rwxr-xr-xtests/bugs/distribute/bug-1161311.t164
-rw-r--r--tests/bugs/distribute/bug-1190734.t93
-rw-r--r--tests/bugs/distribute/bug-1193636.c68
-rw-r--r--tests/bugs/distribute/bug-1193636.t74
-rwxr-xr-xtests/bugs/distribute/bug-1204140.t22
-rw-r--r--tests/bugs/distribute/bug-1247563.t62
-rw-r--r--tests/bugs/distribute/bug-1368012.t51
-rw-r--r--tests/bugs/distribute/bug-1389697.t42
-rw-r--r--tests/bugs/distribute/bug-1543279.t67
-rw-r--r--tests/bugs/distribute/bug-1600379.t54
-rw-r--r--tests/bugs/distribute/bug-1667804.t63
-rwxr-xr-xtests/bugs/distribute/bug-1786679.t69
-rwxr-xr-xtests/bugs/distribute/bug-853258.t47
-rw-r--r--tests/bugs/distribute/bug-860663.c41
-rw-r--r--tests/bugs/distribute/bug-860663.t56
-rw-r--r--tests/bugs/distribute/bug-862967.t59
-rwxr-xr-xtests/bugs/distribute/bug-882278.t73
-rwxr-xr-xtests/bugs/distribute/bug-884455.t84
-rwxr-xr-xtests/bugs/distribute/bug-884597.t173
-rwxr-xr-xtests/bugs/distribute/bug-907072.t49
-rwxr-xr-xtests/bugs/distribute/bug-912564.t92
-rwxr-xr-xtests/bugs/distribute/bug-915554.t76
-rwxr-xr-xtests/bugs/distribute/bug-921408.t90
-rwxr-xr-xtests/bugs/distribute/bug-924265.t35
-rw-r--r--tests/bugs/distribute/bug-961615.t34
-rwxr-xr-xtests/bugs/distribute/bug-973073.t48
-rwxr-xr-xtests/bugs/distribute/issue-1327.t33
-rwxr-xr-xtests/bugs/distribute/overlap.py59
-rw-r--r--tests/bugs/ec/bug-1161621.t42
-rw-r--r--tests/bugs/ec/bug-1161886.c53
-rw-r--r--tests/bugs/ec/bug-1161886.t44
-rw-r--r--tests/bugs/ec/bug-1179050.t23
-rw-r--r--tests/bugs/ec/bug-1187474.t43
-rw-r--r--tests/bugs/ec/bug-1188145.t50
-rw-r--r--tests/bugs/ec/bug-1227869.t33
-rw-r--r--tests/bugs/ec/bug-1236065.t95
-rw-r--r--tests/bugs/ec/bug-1251446.t50
-rwxr-xr-xtests/bugs/ec/bug-1304988.t42
-rw-r--r--tests/bugs/ec/bug-1547662.t41
-rw-r--r--tests/bugs/ec/bug-1699866-check-reopen-fd.t34
-rw-r--r--tests/bugs/ec/bug-1708156-honor-inodelk-contention-notify-on-partial-locks.t54
-rwxr-xr-xtests/bugs/error-gen/bug-767095.t51
-rw-r--r--tests/bugs/fuse/bug-1030208.t35
-rw-r--r--tests/bugs/fuse/bug-1126048.c43
-rwxr-xr-xtests/bugs/fuse/bug-1126048.t30
-rw-r--r--tests/bugs/fuse/bug-1283103.t59
-rw-r--r--tests/bugs/fuse/bug-1309462.t50
-rw-r--r--tests/bugs/fuse/bug-1336818.t52
-rwxr-xr-xtests/bugs/fuse/bug-858215.t79
-rw-r--r--tests/bugs/fuse/bug-858488-min-free-disk.t108
-rwxr-xr-xtests/bugs/fuse/bug-924726.t45
-rw-r--r--tests/bugs/fuse/bug-963678.t57
-rwxr-xr-xtests/bugs/fuse/bug-983477.t53
-rw-r--r--tests/bugs/fuse/bug-985074.t54
-rwxr-xr-xtests/bugs/fuse/many-groups-for-acl.t123
-rwxr-xr-xtests/bugs/fuse/setup.sh20
-rwxr-xr-xtests/bugs/fuse/teardown.sh5
-rw-r--r--tests/bugs/geo-replication/bug-1111490.t35
-rw-r--r--tests/bugs/geo-replication/bug-1296496.t44
-rwxr-xr-xtests/bugs/geo-replication/bug-877293.t41
-rw-r--r--tests/bugs/gfapi/bug-1032894.t33
-rw-r--r--tests/bugs/gfapi/bug-1093594.c311
-rwxr-xr-xtests/bugs/gfapi/bug-1093594.t22
-rwxr-xr-xtests/bugs/gfapi/bug-1319374-THIS-crash.t27
-rw-r--r--tests/bugs/gfapi/bug-1319374.c131
-rw-r--r--tests/bugs/gfapi/bug-1447266/1460514.c150
-rw-r--r--tests/bugs/gfapi/bug-1447266/1460514.t26
-rw-r--r--tests/bugs/gfapi/bug-1447266/bug-1447266.c107
-rw-r--r--tests/bugs/gfapi/bug-1447266/bug-1447266.t60
-rw-r--r--tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.c112
-rw-r--r--tests/bugs/gfapi/bug-1630804/gfapi-bz1630804.t25
-rw-r--r--tests/bugs/gfapi/glfs_vol_set_IO_ERR.c163
-rwxr-xr-xtests/bugs/gfapi/glfs_vol_set_IO_ERR.t20
-rwxr-xr-xtests/bugs/glusterd/859927/repl.t59
-rw-r--r--tests/bugs/glusterd/add-brick-and-validate-replicated-volume-options.t110
-rw-r--r--tests/bugs/glusterd/brick-mux-validation-in-cluster.t108
-rw-r--r--tests/bugs/glusterd/brick-mux-validation.t104
-rw-r--r--tests/bugs/glusterd/brick-mux.t81
-rw-r--r--tests/bugs/glusterd/brick-order-check-add-brick.t61
-rwxr-xr-xtests/bugs/glusterd/bug-1070734.t80
-rw-r--r--tests/bugs/glusterd/bug-1085330-and-bug-916549.t93
-rwxr-xr-xtests/bugs/glusterd/bug-1091935-brick-order-check-from-cli-to-glusterd.t93
-rw-r--r--tests/bugs/glusterd/bug-1238706-daemons-stop-on-peer-cleanup.t44
-rw-r--r--tests/bugs/glusterd/bug-1242875-do-not-pass-volinfo-quota.t38
-rw-r--r--tests/bugs/glusterd/bug-1482906-peer-file-blank-line.t29
-rw-r--r--tests/bugs/glusterd/bug-1595320.t93
-rw-r--r--tests/bugs/glusterd/bug-1696046.t113
-rw-r--r--tests/bugs/glusterd/bug-1699339.t73
-rw-r--r--tests/bugs/glusterd/bug-1720566.t50
-rw-r--r--tests/bugs/glusterd/bug-824753-file-locker.c46
-rwxr-xr-xtests/bugs/glusterd/bug-824753.t45
-rw-r--r--tests/bugs/glusterd/bug-948729/bug-948729-force.t103
-rw-r--r--tests/bugs/glusterd/bug-948729/bug-948729-mode-script.t77
-rw-r--r--tests/bugs/glusterd/bug-948729/bug-948729.t80
-rw-r--r--tests/bugs/glusterd/bug-949930.t29
-rw-r--r--tests/bugs/glusterd/check_elastic_server.t63
-rw-r--r--tests/bugs/glusterd/daemon-log-level-option.t93
-rw-r--r--tests/bugs/glusterd/df-results-post-replace-brick-operations.t61
-rw-r--r--tests/bugs/glusterd/mgmt-handshake-and-volume-sync-post-glusterd-restart.t71
-rw-r--r--tests/bugs/glusterd/optimized-basic-testcases-in-cluster.t115
-rw-r--r--tests/bugs/glusterd/optimized-basic-testcases.t305
-rw-r--r--tests/bugs/glusterd/quorum-validation.t122
-rw-r--r--tests/bugs/glusterd/rebalance-in-cluster.t52
-rw-r--r--tests/bugs/glusterd/rebalance-operations-in-single-node.t131
-rw-r--r--tests/bugs/glusterd/remove-brick-in-cluster.t60
-rw-r--r--tests/bugs/glusterd/remove-brick-testcases.t119
-rw-r--r--tests/bugs/glusterd/remove-brick-validation.t68
-rw-r--r--tests/bugs/glusterd/removing-multiple-bricks-in-single-remove-brick-command.t80
-rw-r--r--tests/bugs/glusterd/replace-brick-operations.t48
-rw-r--r--tests/bugs/glusterd/reset-brick-and-daemons-follow-quorum.t63
-rw-r--r--tests/bugs/glusterd/serialize-shd-manager-glusterd-restart.t54
-rw-r--r--tests/bugs/glusterd/snapshot-operations.t50
-rw-r--r--tests/bugs/glusterd/sync-post-glusterd-restart.t54
-rw-r--r--tests/bugs/glusterd/validating-options-for-replicated-volume.t142
-rw-r--r--tests/bugs/glusterd/validating-server-quorum.t125
-rwxr-xr-xtests/bugs/glusterfs-server/bug-852147.t85
-rwxr-xr-xtests/bugs/glusterfs-server/bug-861542.t50
-rwxr-xr-xtests/bugs/glusterfs-server/bug-864222.t30
-rw-r--r--tests/bugs/glusterfs-server/bug-873549.t17
-rwxr-xr-xtests/bugs/glusterfs-server/bug-877992.t63
-rwxr-xr-xtests/bugs/glusterfs-server/bug-887145.t99
-rw-r--r--tests/bugs/glusterfs-server/bug-889996.t19
-rwxr-xr-xtests/bugs/glusterfs-server/bug-904300.t65
-rw-r--r--tests/bugs/glusterfs-server/bug-905864.c83
-rw-r--r--tests/bugs/glusterfs-server/bug-905864.t32
-rwxr-xr-xtests/bugs/glusterfs-server/bug-912297.t44
-rw-r--r--tests/bugs/glusterfs/bug-1482528.t100
-rwxr-xr-xtests/bugs/glusterfs/bug-811493.t18
-rwxr-xr-xtests/bugs/glusterfs/bug-844688.t55
-rw-r--r--tests/bugs/glusterfs/bug-848251.t52
-rwxr-xr-xtests/bugs/glusterfs/bug-853690.t91
-rw-r--r--tests/bugs/glusterfs/bug-856455.t43
-rw-r--r--tests/bugs/glusterfs/bug-860297.t13
-rw-r--r--tests/bugs/glusterfs/bug-861015-index.t36
-rw-r--r--tests/bugs/glusterfs/bug-861015-log.t29
-rw-r--r--tests/bugs/glusterfs/bug-866459.t44
-rw-r--r--tests/bugs/glusterfs/bug-867253.t64
-rw-r--r--tests/bugs/glusterfs/bug-869724.t37
-rwxr-xr-xtests/bugs/glusterfs/bug-872923.t59
-rw-r--r--tests/bugs/glusterfs/bug-873962-spb.t40
-rwxr-xr-xtests/bugs/glusterfs/bug-873962.t107
-rwxr-xr-xtests/bugs/glusterfs/bug-879490.t37
-rwxr-xr-xtests/bugs/glusterfs/bug-879494.t37
-rwxr-xr-xtests/bugs/glusterfs/bug-892730.t77
-rw-r--r--tests/bugs/glusterfs/bug-893338.t34
-rwxr-xr-xtests/bugs/glusterfs/bug-893378.t75
-rw-r--r--tests/bugs/glusterfs/bug-895235.t23
-rwxr-xr-xtests/bugs/glusterfs/bug-896431.t89
-rwxr-xr-xtests/bugs/glusterfs/bug-902610.t66
-rw-r--r--tests/bugs/glusterfs/bug-906646.t97
-rw-r--r--tests/bugs/glusterfs/getlk_owner.c124
-rw-r--r--tests/bugs/heal-symlinks.t65
-rw-r--r--tests/bugs/index/bug-1559004-EMLINK-handling.t91
-rw-r--r--tests/bugs/io-cache/bug-858242.c84
-rwxr-xr-xtests/bugs/io-cache/bug-858242.t28
-rw-r--r--tests/bugs/io-cache/bug-read-hang.c125
-rwxr-xr-xtests/bugs/io-cache/bug-read-hang.t34
-rwxr-xr-xtests/bugs/io-stats/bug-1598548.t41
-rwxr-xr-xtests/bugs/logging/bug-823081.t41
-rwxr-xr-xtests/bugs/md-cache/afr-stale-read.t44
-rwxr-xr-xtests/bugs/md-cache/bug-1211863.t69
-rwxr-xr-xtests/bugs/md-cache/bug-1211863_unlink.t49
-rw-r--r--tests/bugs/md-cache/bug-1476324.t27
-rwxr-xr-xtests/bugs/md-cache/bug-1632503.t24
-rw-r--r--tests/bugs/md-cache/bug-1726205.t22
-rwxr-xr-xtests/bugs/md-cache/setxattr-prepoststat.t38
-rwxr-xr-xtests/bugs/nfs/bug-1053579.t114
-rw-r--r--tests/bugs/nfs/bug-1143880-fix-gNFSd-auth-crash.t24
-rw-r--r--tests/bugs/nfs/bug-1157223-symlink-mounting.t126
-rw-r--r--tests/bugs/nfs/bug-1161092-nfs-acls.t39
-rwxr-xr-xtests/bugs/nfs/bug-1166862.t69
-rw-r--r--tests/bugs/nfs/bug-1210338.c31
-rw-r--r--tests/bugs/nfs/bug-1210338.t30
-rwxr-xr-xtests/bugs/nfs/bug-1302948.t13
-rwxr-xr-xtests/bugs/nfs/bug-847622.t39
-rwxr-xr-xtests/bugs/nfs/bug-877885.t39
-rwxr-xr-xtests/bugs/nfs/bug-904065.t100
-rwxr-xr-xtests/bugs/nfs/bug-915280.t54
-rwxr-xr-xtests/bugs/nfs/bug-970070.t13
-rwxr-xr-xtests/bugs/nfs/bug-974972.t41
-rw-r--r--tests/bugs/nfs/showmount-many-clients.t43
-rwxr-xr-xtests/bugs/nfs/socket-as-fifo.py33
-rw-r--r--tests/bugs/nfs/socket-as-fifo.t25
-rw-r--r--tests/bugs/nfs/subdir-trailing-slash.t32
-rwxr-xr-xtests/bugs/nfs/zero-atime.t33
-rwxr-xr-xtests/bugs/nl-cache/bug-1451588.t25
-rw-r--r--tests/bugs/posix/bug-1034716.t60
-rwxr-xr-xtests/bugs/posix/bug-1040275-brick-uid-reset-on-volume-restart.t60
-rwxr-xr-xtests/bugs/posix/bug-1113960.t98
-rwxr-xr-xtests/bugs/posix/bug-1122028.t51
-rw-r--r--tests/bugs/posix/bug-1175711.c37
-rwxr-xr-xtests/bugs/posix/bug-1175711.t30
-rw-r--r--tests/bugs/posix/bug-1360679.t36
-rwxr-xr-xtests/bugs/posix/bug-1619720.t58
-rw-r--r--tests/bugs/posix/bug-1651445.t54
-rw-r--r--tests/bugs/posix/bug-765380.t39
-rwxr-xr-xtests/bugs/posix/bug-990028.t157
-rw-r--r--tests/bugs/posix/bug-gfid-path.t70
-rw-r--r--tests/bugs/posix/disallow-gfid-volumeid-fremovexattr.c104
-rwxr-xr-xtests/bugs/posix/disallow-gfid-volumeid-fremovexattr.t21
-rw-r--r--tests/bugs/posix/disallow-gfid-volumeid-removexattr.t26
-rw-r--r--tests/bugs/protocol/bug-1321578.t82
-rw-r--r--tests/bugs/protocol/bug-1390914.t36
-rw-r--r--tests/bugs/protocol/bug-1433815-auth-allow.t40
-rwxr-xr-xtests/bugs/protocol/bug-762989.t40
-rwxr-xr-xtests/bugs/protocol/bug-808400-dist.t32
-rw-r--r--tests/bugs/protocol/bug-808400-fcntl.c124
-rw-r--r--tests/bugs/protocol/bug-808400-flock.c100
-rwxr-xr-xtests/bugs/protocol/bug-808400-repl.t31
-rwxr-xr-xtests/bugs/protocol/bug-808400.t35
-rwxr-xr-xtests/bugs/quick-read/bug-846240.t59
-rwxr-xr-xtests/bugs/quick-read/bz1523599/bz1523599.t32
-rw-r--r--tests/bugs/quick-read/bz1523599/test_bz1523599.c198
-rw-r--r--tests/bugs/quota/afr-quota-xattr-mdata-heal.t140
-rw-r--r--tests/bugs/quota/bug-1035576.t53
-rw-r--r--tests/bugs/quota/bug-1038598.t52
-rw-r--r--tests/bugs/quota/bug-1087198.t86
-rwxr-xr-xtests/bugs/quota/bug-1104692.t26
-rw-r--r--tests/bugs/quota/bug-1153964.t81
-rw-r--r--tests/bugs/quota/bug-1178130.t44
-rw-r--r--tests/bugs/quota/bug-1235182.t61
-rw-r--r--tests/bugs/quota/bug-1243798.t46
-rw-r--r--tests/bugs/quota/bug-1250582-volume-reset-should-not-remove-quota-quota-deem-statfs.t53
-rw-r--r--tests/bugs/quota/bug-1260545.t53
-rw-r--r--tests/bugs/quota/bug-1287996.t21
-rw-r--r--tests/bugs/quota/bug-1292020.t28
-rw-r--r--tests/bugs/quota/bug-1293601.t33
-rw-r--r--tests/bugs/read-only/bug-1134822-read-only-default-in-graph.t67
-rw-r--r--tests/bugs/readdir-ahead/bug-1390050.c72
-rw-r--r--tests/bugs/readdir-ahead/bug-1390050.t29
-rwxr-xr-xtests/bugs/readdir-ahead/bug-1436090.t44
-rwxr-xr-xtests/bugs/readdir-ahead/bug-1439640.t31
-rwxr-xr-xtests/bugs/readdir-ahead/bug-1446516.t21
-rwxr-xr-xtests/bugs/readdir-ahead/bug-1512437.t23
-rw-r--r--tests/bugs/readdir-ahead/bug-1670253-consistent-metadata.t23
-rw-r--r--tests/bugs/replicate/886998/strict-readdir.t52
-rwxr-xr-xtests/bugs/replicate/bug-1015990-rep.t61
-rwxr-xr-xtests/bugs/replicate/bug-1015990.t69
-rw-r--r--tests/bugs/replicate/bug-1032927.t32
-rwxr-xr-xtests/bugs/replicate/bug-1037501.t104
-rwxr-xr-xtests/bugs/replicate/bug-1046624.t47
-rw-r--r--tests/bugs/replicate/bug-1058797.t48
-rw-r--r--tests/bugs/replicate/bug-1101647.t31
-rw-r--r--tests/bugs/replicate/bug-1130892.t76
-rw-r--r--tests/bugs/replicate/bug-1132102.t28
-rw-r--r--tests/bugs/replicate/bug-1134691-afr-lookup-metadata-heal.t56
-rw-r--r--tests/bugs/replicate/bug-1139230.t58
-rw-r--r--tests/bugs/replicate/bug-1180545.t77
-rw-r--r--tests/bugs/replicate/bug-1190069-afr-stale-index-entries.t57
-rw-r--r--tests/bugs/replicate/bug-1221481-allow-fops-on-dir-split-brain.t42
-rw-r--r--tests/bugs/replicate/bug-1238398-split-brain-resolution.t51
-rw-r--r--tests/bugs/replicate/bug-1238508-self-heal.t51
-rw-r--r--tests/bugs/replicate/bug-1250170-fsync.c56
-rw-r--r--tests/bugs/replicate/bug-1250170-fsync.t35
-rw-r--r--tests/bugs/replicate/bug-1266876-allow-reset-brick-for-same-path.t54
-rw-r--r--tests/bugs/replicate/bug-1292379.t58
-rw-r--r--tests/bugs/replicate/bug-1297695.t43
-rw-r--r--tests/bugs/replicate/bug-1305031-block-reads-on-metadata-sbrain.t40
-rw-r--r--tests/bugs/replicate/bug-1325792.t25
-rw-r--r--tests/bugs/replicate/bug-1335652.t29
-rw-r--r--tests/bugs/replicate/bug-1340623-mkdir-fails-remove-brick-started.t46
-rw-r--r--tests/bugs/replicate/bug-1341650.t63
-rw-r--r--tests/bugs/replicate/bug-1363721.t118
-rw-r--r--tests/bugs/replicate/bug-1365455.t54
-rw-r--r--tests/bugs/replicate/bug-1386188-sbrain-fav-child.t82
-rw-r--r--tests/bugs/replicate/bug-1402730.t47
-rw-r--r--tests/bugs/replicate/bug-1408712.t101
-rw-r--r--tests/bugs/replicate/bug-1417522-block-split-brain-resolution.t69
-rw-r--r--tests/bugs/replicate/bug-1433571-undo-pending-only-on-up-bricks.t79
-rw-r--r--tests/bugs/replicate/bug-1438255-do-not-mark-self-accusing-xattrs.t46
-rw-r--r--tests/bugs/replicate/bug-1448804-check-quorum-type-values.t47
-rw-r--r--tests/bugs/replicate/bug-1473026.t31
-rw-r--r--tests/bugs/replicate/bug-1477169-entry-selfheal-rename.t52
-rw-r--r--tests/bugs/replicate/bug-1480525.t18
-rw-r--r--tests/bugs/replicate/bug-1493415-gfid-heal.t78
-rw-r--r--tests/bugs/replicate/bug-1498570-client-iot-graph-check.t48
-rwxr-xr-xtests/bugs/replicate/bug-1539358-split-brain-detection.t89
-rw-r--r--tests/bugs/replicate/bug-1561129-enospc.t24
-rw-r--r--tests/bugs/replicate/bug-1586020-mark-dirty-for-entry-txn-on-quorum-failure.t72
-rw-r--r--tests/bugs/replicate/bug-1591193-assign-gfid-and-heal.t128
-rw-r--r--tests/bugs/replicate/bug-1626994-info-split-brain.t62
-rw-r--r--tests/bugs/replicate/bug-1637249-gfid-heal.t149
-rw-r--r--tests/bugs/replicate/bug-1637802-arbiter-stale-data-heal-lock.t45
-rw-r--r--tests/bugs/replicate/bug-1655050-dir-sbrain-size-policy.t55
-rwxr-xr-xtests/bugs/replicate/bug-1655052-sbrain-policy-same-size.t55
-rw-r--r--tests/bugs/replicate/bug-1655854-support-dist-to-rep3-arb-conversion.t95
-rw-r--r--tests/bugs/replicate/bug-1657783-do-not-update-read-subvol-on-rename-link.t40
-rw-r--r--tests/bugs/replicate/bug-1686568-send-truncate-on-arbiter-from-shd.t38
-rwxr-xr-xtests/bugs/replicate/bug-1696599-io-hang.t47
-rw-r--r--tests/bugs/replicate/bug-1717819-metadata-split-brain-detection.t136
-rw-r--r--tests/bugs/replicate/bug-1722507-type-mismatch-error-handling.t116
-rw-r--r--tests/bugs/replicate/bug-1728770-pass-xattrs.t52
-rw-r--r--tests/bugs/replicate/bug-1734370-entry-heal-restore-time.t102
-rw-r--r--tests/bugs/replicate/bug-1744548-heal-timeout.t47
-rw-r--r--tests/bugs/replicate/bug-1749322-entry-heal-not-happening.t89
-rw-r--r--tests/bugs/replicate/bug-1756938-replica-3-sbrain-cli.t111
-rw-r--r--tests/bugs/replicate/bug-1761531-metadata-heal-restore-time.t74
-rw-r--r--tests/bugs/replicate/bug-1801624-entry-heal.t58
-rw-r--r--tests/bugs/replicate/bug-765564.t86
-rwxr-xr-xtests/bugs/replicate/bug-767585-gfid.t42
-rwxr-xr-xtests/bugs/replicate/bug-802417.t120
-rw-r--r--tests/bugs/replicate/bug-821056.t52
-rwxr-xr-xtests/bugs/replicate/bug-830665.t127
-rwxr-xr-xtests/bugs/replicate/bug-859581.t53
-rwxr-xr-xtests/bugs/replicate/bug-865825.t82
-rw-r--r--tests/bugs/replicate/bug-880898.t30
-rw-r--r--tests/bugs/replicate/bug-884328.t12
-rw-r--r--tests/bugs/replicate/bug-886998.t52
-rw-r--r--tests/bugs/replicate/bug-888174.t62
-rw-r--r--tests/bugs/replicate/bug-913051.t56
-rw-r--r--tests/bugs/replicate/bug-916226.t26
-rw-r--r--tests/bugs/replicate/bug-918437-sh-mtime.t71
-rwxr-xr-xtests/bugs/replicate/bug-921231.t31
-rw-r--r--tests/bugs/replicate/bug-957877.t33
-rw-r--r--tests/bugs/replicate/bug-976800.t29
-rwxr-xr-xtests/bugs/replicate/bug-977797.t96
-rw-r--r--tests/bugs/replicate/bug-978794.t29
-rwxr-xr-xtests/bugs/replicate/bug-979365.t47
-rwxr-xr-xtests/bugs/replicate/bug-986905.t27
-rw-r--r--tests/bugs/replicate/issue-1254-prioritize-enospc.t80
-rw-r--r--tests/bugs/replicate/mdata-heal-no-xattrs.t59
-rw-r--r--tests/bugs/replicate/ta-inode-refresh-read.t40
-rwxr-xr-xtests/bugs/rpc/bug-1043886.t58
-rwxr-xr-xtests/bugs/rpc/bug-847624.t29
-rw-r--r--tests/bugs/rpc/bug-884452.t47
-rwxr-xr-xtests/bugs/rpc/bug-921072.t132
-rwxr-xr-xtests/bugs/rpc/bug-954057.t63
-rw-r--r--tests/bugs/shard/bug-1245547.t35
-rw-r--r--tests/bugs/shard/bug-1248887.t39
-rw-r--r--tests/bugs/shard/bug-1250855.t34
-rw-r--r--tests/bugs/shard/bug-1251824.t109
-rw-r--r--tests/bugs/shard/bug-1256580.t34
-rw-r--r--tests/bugs/shard/bug-1258334.t40
-rw-r--r--tests/bugs/shard/bug-1259651.t40
-rw-r--r--tests/bugs/shard/bug-1260637.t42
-rw-r--r--tests/bugs/shard/bug-1261773.t14
-rw-r--r--tests/bugs/shard/bug-1272986.t35
-rw-r--r--tests/bugs/shard/bug-1342298.t23
-rw-r--r--tests/bugs/shard/bug-1468483.t58
-rw-r--r--tests/bugs/shard/bug-1488546.t25
-rw-r--r--tests/bugs/shard/bug-1568521-EEXIST.t91
-rw-r--r--tests/bugs/shard/bug-1568521.t53
-rw-r--r--tests/bugs/shard/bug-1605056-2.t34
-rw-r--r--tests/bugs/shard/bug-1605056.t63
-rw-r--r--tests/bugs/shard/bug-1669077.t29
-rw-r--r--tests/bugs/shard/bug-1696136-lru-limit-equals-deletion-rate.t34
-rw-r--r--tests/bugs/shard/bug-1696136.c122
-rw-r--r--tests/bugs/shard/bug-1696136.t33
-rw-r--r--tests/bugs/shard/bug-1705884.t32
-rw-r--r--tests/bugs/shard/bug-1738419.t29
-rw-r--r--tests/bugs/shard/bug-shard-discard.c70
-rw-r--r--tests/bugs/shard/bug-shard-discard.t65
-rw-r--r--tests/bugs/shard/bug-shard-zerofill.c60
-rw-r--r--tests/bugs/shard/bug-shard-zerofill.t46
-rw-r--r--tests/bugs/shard/configure-lru-limit.t52
-rw-r--r--tests/bugs/shard/issue-1243.t43
-rw-r--r--tests/bugs/shard/issue-1281.t34
-rw-r--r--tests/bugs/shard/issue-1425.t45
-rw-r--r--tests/bugs/shard/parallel-truncate-read.t48
-rw-r--r--tests/bugs/shard/shard-append-test.c183
-rw-r--r--tests/bugs/shard/shard-append-test.t32
-rw-r--r--tests/bugs/shard/shard-fallocate.c113
-rw-r--r--tests/bugs/shard/shard-inode-refcount-test.t30
-rw-r--r--tests/bugs/shard/unlinks-and-renames.t333
-rw-r--r--tests/bugs/shard/zero-flag.t76
-rwxr-xr-xtests/bugs/snapshot/bug-1045333.t44
-rwxr-xr-xtests/bugs/snapshot/bug-1049834.t44
-rw-r--r--tests/bugs/snapshot/bug-1064768.t20
-rw-r--r--tests/bugs/snapshot/bug-1087203.t103
-rwxr-xr-xtests/bugs/snapshot/bug-1090042.t26
-rw-r--r--tests/bugs/snapshot/bug-1109770.t65
-rw-r--r--tests/bugs/snapshot/bug-1109889.t74
-rwxr-xr-xtests/bugs/snapshot/bug-1111041.t40
-rw-r--r--tests/bugs/snapshot/bug-1112613.t49
-rw-r--r--tests/bugs/snapshot/bug-1113975.t38
-rw-r--r--tests/bugs/snapshot/bug-1155042-dont-display-deactivated-snapshots.t36
-rwxr-xr-xtests/bugs/snapshot/bug-1157991.t30
-rwxr-xr-xtests/bugs/snapshot/bug-1162462.t38
-rwxr-xr-xtests/bugs/snapshot/bug-1162498.t56
-rwxr-xr-xtests/bugs/snapshot/bug-1166197.t52
-rw-r--r--tests/bugs/snapshot/bug-1167580-set-proper-uid-and-gid-during-nfs-access.t205
-rw-r--r--tests/bugs/snapshot/bug-1168875.t96
-rw-r--r--tests/bugs/snapshot/bug-1178079.t24
-rw-r--r--tests/bugs/snapshot/bug-1202436-calculate-quota-cksum-during-snap-restore.t37
-rw-r--r--tests/bugs/snapshot/bug-1205592.t30
-rw-r--r--tests/bugs/snapshot/bug-1227646.t31
-rwxr-xr-xtests/bugs/snapshot/bug-1232430.t22
-rwxr-xr-xtests/bugs/snapshot/bug-1250387.t26
-rw-r--r--tests/bugs/snapshot/bug-1260848.t28
-rwxr-xr-xtests/bugs/snapshot/bug-1275616.t50
-rw-r--r--tests/bugs/snapshot/bug-1279327.t29
-rw-r--r--tests/bugs/snapshot/bug-1316437.t29
-rw-r--r--tests/bugs/snapshot/bug-1322772-real-path-fix-for-snapshot.t56
-rwxr-xr-xtests/bugs/snapshot/bug-1399598-uss-with-ssl.t108
-rw-r--r--tests/bugs/snapshot/bug-1482023-snpashot-issue-with-other-processes-accessing-mounted-path.t133
-rw-r--r--tests/bugs/snapshot/bug-1512451-snapshot-creation-failed-after-brick-reset.t39
-rw-r--r--tests/bugs/snapshot/bug-1597662.t58
-rw-r--r--tests/bugs/snapshot/bug-1618004-fix-memory-corruption-in-snap-import.t48
-rw-r--r--tests/bugs/stripe/bug-1002207.t55
-rw-r--r--tests/bugs/stripe/bug-1111454.t20
-rwxr-xr-xtests/bugs/trace/bug-797171.t41
-rwxr-xr-xtests/bugs/transport/bug-873367.t45
-rw-r--r--tests/bugs/unclassified/bug-1034085.t31
-rw-r--r--tests/bugs/unclassified/bug-1357397.t35
-rw-r--r--tests/bugs/unclassified/bug-874498.t64
-rw-r--r--tests/bugs/unclassified/bug-991622.t35
-rwxr-xr-xtests/bugs/upcall/bug-1227204.t29
-rwxr-xr-xtests/bugs/upcall/bug-1369430.t43
-rwxr-xr-xtests/bugs/upcall/bug-1394131.t29
-rwxr-xr-xtests/bugs/upcall/bug-1422776.t30
-rwxr-xr-xtests/bugs/upcall/bug-1458127.t36
-rwxr-xr-xtests/bugs/upcall/bug-upcall-stat.t39
-rw-r--r--tests/bugs/write-behind/bug-1058663.c123
-rw-r--r--tests/bugs/write-behind/bug-1058663.t28
-rw-r--r--tests/bugs/write-behind/bug-1279730.c149
-rwxr-xr-xtests/bugs/write-behind/bug-1279730.t37
-rw-r--r--tests/bugs/write-behind/issue-884.c267
-rwxr-xr-xtests/bugs/write-behind/issue-884.t40
-rw-r--r--tests/changelog.rc9
-rw-r--r--tests/cleanup.sh4
-rw-r--r--tests/cluster.rc218
-rw-r--r--tests/common-utils.rc7
-rw-r--r--tests/configfiles/bad_exports9
-rw-r--r--tests/configfiles/bad_netgroups5
-rw-r--r--tests/configfiles/big_exports10
-rw-r--r--tests/configfiles/exports1
-rw-r--r--tests/configfiles/exports-v61
-rw-r--r--tests/configfiles/exports_bad_opt1
-rw-r--r--tests/configfiles/netgroups4
-rw-r--r--tests/dht.rc174
-rw-r--r--tests/ec.rc18
-rw-r--r--tests/env.rc.in42
-rw-r--r--tests/experimental/.gitignore7
-rw-r--r--tests/fallocate.rc19
-rw-r--r--tests/fdl.rc12
-rwxr-xr-xtests/features/delay-gen.t52
-rw-r--r--tests/features/dh1024.pem5
-rw-r--r--tests/features/fdl-overflow.t72
-rw-r--r--tests/features/fdl.t44
-rw-r--r--tests/features/flock_interrupt.t32
-rw-r--r--tests/features/fuse-lru-limit.t43
-rw-r--r--tests/features/glfs-lease-recall.c372
-rw-r--r--tests/features/glfs-lease.c717
-rwxr-xr-xtests/features/glfs-lease.t31
-rw-r--r--tests/features/interrupt.t71
-rwxr-xr-xtests/features/ipc.t38
-rwxr-xr-xtests/features/ipctest.py28
-rw-r--r--tests/features/lock_revocation.t54
-rw-r--r--tests/features/mandatory-lock-forced.c143
-rw-r--r--tests/features/mandatory-lock-forced.t80
-rwxr-xr-xtests/features/nuke.t41
-rw-r--r--tests/features/open_and_sleep.c27
-rw-r--r--tests/features/openssl.cnf.in41
-rwxr-xr-xtests/features/readdir-ahead.t45
-rw-r--r--tests/features/recon.t59
-rwxr-xr-xtests/features/ssl-authz.t121
-rw-r--r--tests/features/ssl-ciphers.t244
-rw-r--r--tests/features/subdir-mount.t121
-rwxr-xr-xtests/features/trash.t247
-rwxr-xr-xtests/features/unhashed-auto.t125
-rwxr-xr-xtests/features/weighted-rebalance.t78
-rwxr-xr-xtests/features/worm.t117
-rw-r--r--tests/features/worm_sh.t75
-rw-r--r--tests/fileio.rc61
-rw-r--r--tests/geo-rep.rc495
-rw-r--r--tests/gfid2path/block-mount-access.t51
-rw-r--r--tests/gfid2path/get-gfid-to-path.t72
-rw-r--r--tests/gfid2path/gfid2path_fuse.t166
-rw-r--r--tests/gfid2path/gfid2path_nfs.t152
-rw-r--r--tests/glusterfind/glusterfind-basic.t84
-rw-r--r--tests/include.rc1350
-rw-r--r--tests/line-coverage/afr-heal-info.t43
-rwxr-xr-xtests/line-coverage/arbiter-coverage.t32
-rw-r--r--tests/line-coverage/cli-peer-and-volume-operations.t135
-rw-r--r--tests/line-coverage/cli-volume-top-profile-coverage.t62
-rwxr-xr-xtests/line-coverage/errorgen-coverage.t42
-rw-r--r--tests/line-coverage/log-and-brick-ops-negative-case.t82
-rwxr-xr-xtests/line-coverage/meta-max-coverage.t33
-rw-r--r--tests/line-coverage/namespace-linecoverage.t39
-rwxr-xr-xtests/line-coverage/old-protocol.t37
-rwxr-xr-xtests/line-coverage/quiesce-coverage.t44
-rw-r--r--tests/line-coverage/shard-coverage.t33
-rw-r--r--tests/line-coverage/some-features-in-libglusterfs.t67
-rw-r--r--tests/line-coverage/volfile-with-all-graph-syntax.t73
-rw-r--r--tests/nfs.rc70
-rwxr-xr-xtests/performance/open-behind.t75
-rw-r--r--tests/performance/quick-read.t55
-rw-r--r--tests/snapshot.rc484
-rw-r--r--tests/ssl.rc35
-rw-r--r--tests/thin-arbiter.rc613
-rw-r--r--tests/traps.rc22
-rw-r--r--tests/utils/arequal-checksum.c633
-rw-r--r--tests/utils/changelog/changelog.h125
-rw-r--r--tests/utils/changelog/get-history.c71
-rw-r--r--tests/utils/changelog/test-changelog-api.c98
-rw-r--r--tests/utils/changelog/test-history-api.c111
-rw-r--r--tests/utils/changelogparser.py236
-rwxr-xr-xtests/utils/create-files.py593
-rw-r--r--tests/utils/get-mdata-xattr.c152
-rwxr-xr-xtests/utils/getfattr.py133
-rwxr-xr-xtests/utils/gfid-access.py124
-rw-r--r--tests/utils/libcxattr.py108
-rwxr-xr-xtests/utils/pidof.py45
-rw-r--r--tests/utils/py2py3.py186
-rwxr-xr-xtests/utils/setfattr.py77
-rwxr-xr-xtests/utils/testn.sh16
-rw-r--r--tests/vagrant/vagrant-template-centos6/Vagrantfile55
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/daemon-services/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/fix-localhost/tasks/main.yml6
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/install-pkgs/tasks/main.yml92
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/iptables/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/mock-user/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/prepare-brick/tasks/main.yml6
-rw-r--r--tests/vagrant/vagrant-template-centos6/roles/remove-gluster-pkgs/tasks/main.yml4
-rw-r--r--tests/vagrant/vagrant-template-centos6/setup.yml15
-rw-r--r--tests/vagrant/vagrant-template-fedora/Vagrantfile56
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/daemon-services/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/fix-localhost/tasks/main.yml6
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/install-pkgs/tasks/main.yml85
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/iptables/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/mock-user/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/prepare-brick/tasks/main.yml6
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/remove-gluster-pkgs/tasks/main.yml4
-rw-r--r--tests/vagrant/vagrant-template-fedora/roles/selinux/tasks/main.yml3
-rw-r--r--tests/vagrant/vagrant-template-fedora/setup.yml16
-rw-r--r--tests/volume.rc1002
-rw-r--r--tools/Makefile.am3
-rw-r--r--tools/gfind_missing_files/Makefile.am32
-rw-r--r--tools/gfind_missing_files/gcrawler.c581
-rw-r--r--tools/gfind_missing_files/gfid_to_path.py162
-rw-r--r--tools/gfind_missing_files/gfid_to_path.sh43
-rw-r--r--tools/gfind_missing_files/gfind_missing_files.sh119
-rw-r--r--tools/glusterfind/Makefile.am24
-rwxr-xr-xtools/glusterfind/S57glusterfind-delete-post.py69
-rw-r--r--tools/glusterfind/glusterfind.in18
-rw-r--r--tools/glusterfind/src/Makefile.am16
-rw-r--r--tools/glusterfind/src/__init__.py9
-rw-r--r--tools/glusterfind/src/brickfind.py118
-rw-r--r--tools/glusterfind/src/changelog.py469
-rw-r--r--tools/glusterfind/src/changelogdata.py440
-rw-r--r--tools/glusterfind/src/conf.py31
-rw-r--r--tools/glusterfind/src/gfind_py2py3.py88
-rw-r--r--tools/glusterfind/src/libgfchangelog.py92
-rw-r--r--tools/glusterfind/src/main.py921
-rw-r--r--tools/glusterfind/src/nodeagent.py139
-rw-r--r--tools/glusterfind/src/tool.conf.in10
-rw-r--r--tools/glusterfind/src/utils.py267
-rw-r--r--tools/setgfid2path/Makefile.am5
-rw-r--r--tools/setgfid2path/gluster-setgfid2path.854
-rw-r--r--tools/setgfid2path/src/Makefile.am16
-rw-r--r--tools/setgfid2path/src/main.c130
-rw-r--r--xlators/Makefile.am12
-rw-r--r--xlators/bindings/Makefile.am1
-rw-r--r--xlators/bindings/python/src/Makefile.am19
-rw-r--r--xlators/bindings/python/src/gluster.py47
-rw-r--r--xlators/bindings/python/src/glusterstack.py55
-rw-r--r--xlators/bindings/python/src/glustertypes.py167
-rw-r--r--xlators/bindings/python/src/python.c232
-rw-r--r--xlators/bindings/python/src/testxlator.py56
-rw-r--r--xlators/cluster/Makefile.am2
-rw-r--r--xlators/cluster/afr/src/Makefile.am34
-rw-r--r--xlators/cluster/afr/src/afr-common.c10097
-rw-r--r--xlators/cluster/afr/src/afr-dir-read.c899
-rw-r--r--xlators/cluster/afr/src/afr-dir-read.h21
-rw-r--r--xlators/cluster/afr/src/afr-dir-write.c2575
-rw-r--r--xlators/cluster/afr/src/afr-dir-write.h33
-rw-r--r--xlators/cluster/afr/src/afr-inode-read.c2660
-rw-r--r--xlators/cluster/afr/src/afr-inode-read.h33
-rw-r--r--xlators/cluster/afr/src/afr-inode-write.c3659
-rw-r--r--xlators/cluster/afr/src/afr-inode-write.h81
-rw-r--r--xlators/cluster/afr/src/afr-lk-common.c2738
-rw-r--r--xlators/cluster/afr/src/afr-mem-types.h51
-rw-r--r--xlators/cluster/afr/src/afr-messages.h167
-rw-r--r--xlators/cluster/afr/src/afr-open.c666
-rw-r--r--xlators/cluster/afr/src/afr-read-txn.c494
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.c810
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-algorithm.h32
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.c4563
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-common.h128
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-data.c2002
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-entry.c3380
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-metadata.c997
-rw-r--r--xlators/cluster/afr/src/afr-self-heal-name.c616
-rw-r--r--xlators/cluster/afr/src/afr-self-heal.h370
-rw-r--r--xlators/cluster/afr/src/afr-self-heald.c2436
-rw-r--r--xlators/cluster/afr/src/afr-self-heald.h86
-rw-r--r--xlators/cluster/afr/src/afr-transaction.c3536
-rw-r--r--xlators/cluster/afr/src/afr-transaction.h63
-rw-r--r--xlators/cluster/afr/src/afr.c1680
-rw-r--r--xlators/cluster/afr/src/afr.h2033
-rw-r--r--xlators/cluster/afr/src/pump.c2636
-rw-r--r--xlators/cluster/afr/src/pump.h78
-rw-r--r--xlators/cluster/dht/src/Makefile.am33
-rw-r--r--xlators/cluster/dht/src/dht-common.c13963
-rw-r--r--xlators/cluster/dht/src/dht-common.h1839
-rw-r--r--xlators/cluster/dht/src/dht-diskusage.c700
-rw-r--r--xlators/cluster/dht/src/dht-hashfn.c126
-rw-r--r--xlators/cluster/dht/src/dht-helper.c2705
-rw-r--r--xlators/cluster/dht/src/dht-inode-read.c2143
-rw-r--r--xlators/cluster/dht/src/dht-inode-write.c1674
-rw-r--r--xlators/cluster/dht/src/dht-layout.c1187
-rw-r--r--xlators/cluster/dht/src/dht-linkfile.c406
-rw-r--r--xlators/cluster/dht/src/dht-lock.c1392
-rw-r--r--xlators/cluster/dht/src/dht-lock.h91
-rw-r--r--xlators/cluster/dht/src/dht-mem-types.h37
-rw-r--r--xlators/cluster/dht/src/dht-messages.h386
-rw-r--r--xlators/cluster/dht/src/dht-rebalance.c5550
-rw-r--r--xlators/cluster/dht/src/dht-rename.c2441
-rw-r--r--xlators/cluster/dht/src/dht-selfheal.c3055
-rw-r--r--xlators/cluster/dht/src/dht-shared.c1104
-rw-r--r--xlators/cluster/dht/src/dht.c675
-rw-r--r--xlators/cluster/dht/src/nufa.c1142
-rw-r--r--xlators/cluster/dht/src/switch.c1602
-rw-r--r--xlators/cluster/dht/src/unittest/dht_layout_mock.c73
-rw-r--r--xlators/cluster/dht/src/unittest/dht_layout_unittest.c127
-rw-r--r--xlators/cluster/ec/Makefile.am (renamed from libglusterfsclient/Makefile.am)0
-rw-r--r--xlators/cluster/ec/src/Makefile.am83
-rw-r--r--xlators/cluster/ec/src/ec-code-avx.c109
-rw-r--r--xlators/cluster/ec/src/ec-code-avx.h18
-rw-r--r--xlators/cluster/ec/src/ec-code-c.c11679
-rw-r--r--xlators/cluster/ec/src/ec-code-c.h27
-rw-r--r--xlators/cluster/ec/src/ec-code-intel.c594
-rw-r--r--xlators/cluster/ec/src/ec-code-intel.h191
-rw-r--r--xlators/cluster/ec/src/ec-code-sse.c101
-rw-r--r--xlators/cluster/ec/src/ec-code-sse.h18
-rw-r--r--xlators/cluster/ec/src/ec-code-x64.c144
-rw-r--r--xlators/cluster/ec/src/ec-code-x64.h18
-rw-r--r--xlators/cluster/ec/src/ec-code.c1060
-rw-r--r--xlators/cluster/ec/src/ec-code.h44
-rw-r--r--xlators/cluster/ec/src/ec-combine.c995
-rw-r--r--xlators/cluster/ec/src/ec-combine.h44
-rw-r--r--xlators/cluster/ec/src/ec-common.c3042
-rw-r--r--xlators/cluster/ec/src/ec-common.h234
-rw-r--r--xlators/cluster/ec/src/ec-data.c288
-rw-r--r--xlators/cluster/ec/src/ec-data.h35
-rw-r--r--xlators/cluster/ec/src/ec-dir-read.c647
-rw-r--r--xlators/cluster/ec/src/ec-dir-write.c1487
-rw-r--r--xlators/cluster/ec/src/ec-fops.h254
-rw-r--r--xlators/cluster/ec/src/ec-galois.c183
-rw-r--r--xlators/cluster/ec/src/ec-galois.h32
-rw-r--r--xlators/cluster/ec/src/ec-generic.c1591
-rw-r--r--xlators/cluster/ec/src/ec-gf8.c5882
-rw-r--r--xlators/cluster/ec/src/ec-gf8.h18
-rw-r--r--xlators/cluster/ec/src/ec-heal.c3367
-rw-r--r--xlators/cluster/ec/src/ec-heald.c681
-rw-r--r--xlators/cluster/ec/src/ec-heald.h30
-rw-r--r--xlators/cluster/ec/src/ec-helpers.c867
-rw-r--r--xlators/cluster/ec/src/ec-helpers.h200
-rw-r--r--xlators/cluster/ec/src/ec-inode-read.c2046
-rw-r--r--xlators/cluster/ec/src/ec-inode-write.c2369
-rw-r--r--xlators/cluster/ec/src/ec-locks.c1128
-rw-r--r--xlators/cluster/ec/src/ec-mem-types.h30
-rw-r--r--xlators/cluster/ec/src/ec-messages.h61
-rw-r--r--xlators/cluster/ec/src/ec-method.c433
-rw-r--r--xlators/cluster/ec/src/ec-method.h48
-rw-r--r--xlators/cluster/ec/src/ec-types.h690
-rw-r--r--xlators/cluster/ec/src/ec.c1873
-rw-r--r--xlators/cluster/ec/src/ec.h34
-rw-r--r--xlators/cluster/ha/Makefile.am3
-rw-r--r--xlators/cluster/ha/src/Makefile.am15
-rw-r--r--xlators/cluster/ha/src/ha-helpers.c204
-rw-r--r--xlators/cluster/ha/src/ha-mem-types.h37
-rw-r--r--xlators/cluster/ha/src/ha.c4023
-rw-r--r--xlators/cluster/ha/src/ha.h63
-rw-r--r--xlators/cluster/map/Makefile.am3
-rw-r--r--xlators/cluster/map/src/Makefile.am15
-rw-r--r--xlators/cluster/map/src/map-helper.c358
-rw-r--r--xlators/cluster/map/src/map-mem-types.h35
-rw-r--r--xlators/cluster/map/src/map.c2577
-rw-r--r--xlators/cluster/map/src/map.h77
-rw-r--r--xlators/cluster/stripe/Makefile.am3
-rw-r--r--xlators/cluster/stripe/src/Makefile.am19
-rw-r--r--xlators/cluster/stripe/src/stripe-helpers.c503
-rw-r--r--xlators/cluster/stripe/src/stripe-mem-types.h30
-rw-r--r--xlators/cluster/stripe/src/stripe.c4770
-rw-r--r--xlators/cluster/stripe/src/stripe.h233
-rw-r--r--xlators/cluster/unify/Makefile.am3
-rw-r--r--xlators/cluster/unify/src/Makefile.am16
-rw-r--r--xlators/cluster/unify/src/unify-mem-types.h41
-rw-r--r--xlators/cluster/unify/src/unify-self-heal.c1239
-rw-r--r--xlators/cluster/unify/src/unify.c4589
-rw-r--r--xlators/cluster/unify/src/unify.h146
-rw-r--r--xlators/debug/Makefile.am2
-rw-r--r--xlators/debug/delay-gen/Makefile.am (renamed from scheduler/random/Makefile.am)2
-rw-r--r--xlators/debug/delay-gen/src/Makefile.am11
-rw-r--r--xlators/debug/delay-gen/src/delay-gen-mem-types.h21
-rw-r--r--xlators/debug/delay-gen/src/delay-gen-messages.h26
-rw-r--r--xlators/debug/delay-gen/src/delay-gen.c697
-rw-r--r--xlators/debug/delay-gen/src/delay-gen.h27
-rw-r--r--xlators/debug/error-gen/src/Makefile.am8
-rw-r--r--xlators/debug/error-gen/src/error-gen-mem-types.h26
-rw-r--r--xlators/debug/error-gen/src/error-gen.c2973
-rw-r--r--xlators/debug/error-gen/src/error-gen.h61
-rw-r--r--xlators/debug/io-stats/src/Makefile.am10
-rw-r--r--xlators/debug/io-stats/src/io-stats-mem-types.h38
-rw-r--r--xlators/debug/io-stats/src/io-stats.c5876
-rw-r--r--xlators/debug/sink/Makefile.am (renamed from scheduler/alu/Makefile.am)1
-rw-r--r--xlators/debug/sink/src/Makefile.am14
-rw-r--r--xlators/debug/sink/src/sink.c94
-rw-r--r--xlators/debug/trace/src/Makefile.am9
-rw-r--r--xlators/debug/trace/src/trace-mem-types.h20
-rw-r--r--xlators/debug/trace/src/trace.c4929
-rw-r--r--xlators/debug/trace/src/trace.h55
-rw-r--r--xlators/encryption/Makefile.am3
-rw-r--r--xlators/encryption/rot-13/Makefile.am3
-rw-r--r--xlators/encryption/rot-13/src/rot-13.c210
-rw-r--r--xlators/encryption/rot-13/src/rot-13.h33
-rw-r--r--xlators/features/Makefile.am13
-rw-r--r--xlators/features/arbiter/Makefile.am3
-rw-r--r--xlators/features/arbiter/src/Makefile.am19
-rw-r--r--xlators/features/arbiter/src/arbiter-mem-types.h18
-rw-r--r--xlators/features/arbiter/src/arbiter.c380
-rw-r--r--xlators/features/arbiter/src/arbiter.h21
-rw-r--r--xlators/features/barrier/Makefile.am3
-rw-r--r--xlators/features/barrier/src/Makefile.am17
-rw-r--r--xlators/features/barrier/src/barrier-mem-types.h20
-rw-r--r--xlators/features/barrier/src/barrier.c809
-rw-r--r--xlators/features/barrier/src/barrier.h89
-rw-r--r--xlators/features/bit-rot/Makefile.am (renamed from rpc/rpc-transport/rdma/Makefile.am)0
-rw-r--r--xlators/features/bit-rot/src/Makefile.am1
-rw-r--r--xlators/features/bit-rot/src/bitd/Makefile.am23
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-bitd-messages.h101
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.c78
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub-status.h50
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub.c2070
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-scrub.h46
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-ssm.c124
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot-ssm.h38
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.c2232
-rw-r--r--xlators/features/bit-rot/src/bitd/bit-rot.h302
-rw-r--r--xlators/features/bit-rot/src/stub/Makefile.am20
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-common.h178
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-object-version.h30
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub-helpers.c796
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub-mem-types.h36
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub-messages.h117
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub.c3590
-rw-r--r--xlators/features/bit-rot/src/stub/bit-rot-stub.h515
-rw-r--r--xlators/features/changelog/Makefile.am3
-rw-r--r--xlators/features/changelog/lib/Makefile.am3
-rw-r--r--xlators/features/changelog/lib/examples/c/get-changes-multi.c90
-rw-r--r--xlators/features/changelog/lib/examples/c/get-changes.c93
-rw-r--r--xlators/features/changelog/lib/examples/c/get-history.c116
-rwxr-xr-xxlators/features/changelog/lib/examples/python/changes.py34
-rw-r--r--xlators/features/changelog/lib/examples/python/libgfchangelog.py71
-rw-r--r--xlators/features/changelog/lib/src/Makefile.am35
-rw-r--r--xlators/features/changelog/lib/src/changelog-lib-messages.h74
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-api.c224
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-helpers.c170
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-helpers.h255
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-journal-handler.c1029
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-journal.h116
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-reborp.c413
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-rpc.c98
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog-rpc.h28
-rw-r--r--xlators/features/changelog/lib/src/gf-changelog.c652
-rw-r--r--xlators/features/changelog/lib/src/gf-history-changelog.c1020
-rw-r--r--xlators/features/changelog/src/Makefile.am29
-rw-r--r--xlators/features/changelog/src/changelog-barrier.c131
-rw-r--r--xlators/features/changelog/src/changelog-encoders.c232
-rw-r--r--xlators/features/changelog/src/changelog-encoders.h50
-rw-r--r--xlators/features/changelog/src/changelog-ev-handle.c412
-rw-r--r--xlators/features/changelog/src/changelog-ev-handle.h136
-rw-r--r--xlators/features/changelog/src/changelog-helpers.c1977
-rw-r--r--xlators/features/changelog/src/changelog-helpers.h716
-rw-r--r--xlators/features/changelog/src/changelog-mem-types.h34
-rw-r--r--xlators/features/changelog/src/changelog-messages.h172
-rw-r--r--xlators/features/changelog/src/changelog-misc.h131
-rw-r--r--xlators/features/changelog/src/changelog-rpc-common.c359
-rw-r--r--xlators/features/changelog/src/changelog-rpc-common.h85
-rw-r--r--xlators/features/changelog/src/changelog-rpc.c440
-rw-r--r--xlators/features/changelog/src/changelog-rpc.h31
-rw-r--r--xlators/features/changelog/src/changelog-rt.c66
-rw-r--r--xlators/features/changelog/src/changelog-rt.h33
-rw-r--r--xlators/features/changelog/src/changelog.c2989
-rw-r--r--xlators/features/cloudsync/Makefile.am3
-rw-r--r--xlators/features/cloudsync/src/Makefile.am46
-rw-r--r--xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.c30
-rw-r--r--xlators/features/cloudsync/src/cloudsync-autogen-fops-tmpl.h24
-rw-r--r--xlators/features/cloudsync/src/cloudsync-common.c60
-rw-r--r--xlators/features/cloudsync/src/cloudsync-common.h134
-rwxr-xr-xxlators/features/cloudsync/src/cloudsync-fops-c.py324
-rwxr-xr-xxlators/features/cloudsync/src/cloudsync-fops-h.py31
-rw-r--r--xlators/features/cloudsync/src/cloudsync-mem-types.h22
-rw-r--r--xlators/features/cloudsync/src/cloudsync-messages.h16
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/Makefile.am3
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/Makefile.am11
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/Makefile.am3
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/Makefile.am12
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3-mem-types.h19
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.c584
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.h50
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cloudsyncs3/src/libcloudsyncs3.sym1
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/Makefile.am3
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/Makefile.am12
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/archivestore.h203
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/cvlt-messages.h30
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcloudsynccvlt.sym1
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt-mem-types.h19
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.c842
-rw-r--r--xlators/features/cloudsync/src/cloudsync-plugins/src/cvlt/src/libcvlt.h84
-rw-r--r--xlators/features/cloudsync/src/cloudsync.c2076
-rw-r--r--xlators/features/cloudsync/src/cloudsync.h123
-rw-r--r--xlators/features/compress/Makefile.am3
-rw-r--r--xlators/features/compress/src/Makefile.am19
-rw-r--r--xlators/features/compress/src/cdc-helper.c527
-rw-r--r--xlators/features/compress/src/cdc-mem-types.h23
-rw-r--r--xlators/features/compress/src/cdc.c348
-rw-r--r--xlators/features/compress/src/cdc.h99
-rw-r--r--xlators/features/filter/Makefile.am3
-rw-r--r--xlators/features/filter/src/Makefile.am15
-rw-r--r--xlators/features/filter/src/filter-mem-types.h30
-rw-r--r--xlators/features/filter/src/filter.c1744
-rw-r--r--xlators/features/gfid-access/Makefile.am (renamed from xlators/bindings/python/Makefile.am)0
-rw-r--r--xlators/features/gfid-access/src/Makefile.am16
-rw-r--r--xlators/features/gfid-access/src/gfid-access-mem-types.h22
-rw-r--r--xlators/features/gfid-access/src/gfid-access.c1420
-rw-r--r--xlators/features/gfid-access/src/gfid-access.h107
-rw-r--r--xlators/features/index/src/Makefile.am14
-rw-r--r--xlators/features/index/src/index-mem-types.h37
-rw-r--r--xlators/features/index/src/index-messages.h33
-rw-r--r--xlators/features/index/src/index.c3256
-rw-r--r--xlators/features/index/src/index.h110
-rw-r--r--xlators/features/leases/Makefile.am3
-rw-r--r--xlators/features/leases/src/Makefile.am20
-rw-r--r--xlators/features/leases/src/leases-internal.c1412
-rw-r--r--xlators/features/leases/src/leases-mem-types.h27
-rw-r--r--xlators/features/leases/src/leases-messages.h33
-rw-r--r--xlators/features/leases/src/leases.c1168
-rw-r--r--xlators/features/leases/src/leases.h259
-rw-r--r--xlators/features/locks/src/Makefile.am19
-rw-r--r--xlators/features/locks/src/clear.c718
-rw-r--r--xlators/features/locks/src/clear.h93
-rw-r--r--xlators/features/locks/src/common.c1970
-rw-r--r--xlators/features/locks/src/common.h280
-rw-r--r--xlators/features/locks/src/entrylk.c1506
-rw-r--r--xlators/features/locks/src/inodelk.c1514
-rw-r--r--xlators/features/locks/src/locks-mem-types.h43
-rw-r--r--xlators/features/locks/src/locks.h348
-rw-r--r--xlators/features/locks/src/pl-messages.h29
-rw-r--r--xlators/features/locks/src/posix.c6028
-rw-r--r--xlators/features/locks/src/reservelk.c611
-rw-r--r--xlators/features/locks/tests/unit-test.c118
-rw-r--r--xlators/features/mac-compat/Makefile.am3
-rw-r--r--xlators/features/mac-compat/src/Makefile.am13
-rw-r--r--xlators/features/mac-compat/src/mac-compat.c248
-rw-r--r--xlators/features/marker/Makefile.am2
-rw-r--r--xlators/features/marker/src/Makefile.am19
-rw-r--r--xlators/features/marker/src/marker-common.c109
-rw-r--r--xlators/features/marker/src/marker-common.h37
-rw-r--r--xlators/features/marker/src/marker-mem-types.h41
-rw-r--r--xlators/features/marker/src/marker-quota-helper.c599
-rw-r--r--xlators/features/marker/src/marker-quota-helper.h103
-rw-r--r--xlators/features/marker/src/marker-quota.c4039
-rw-r--r--xlators/features/marker/src/marker-quota.h213
-rw-r--r--xlators/features/marker/src/marker.c4487
-rw-r--r--xlators/features/marker/src/marker.h239
-rw-r--r--xlators/features/marker/utils/Makefile.am3
-rw-r--r--xlators/features/marker/utils/src/Makefile.am22
-rw-r--r--xlators/features/marker/utils/src/gsyncd.c342
-rw-r--r--xlators/features/marker/utils/src/procdiggy.c128
-rw-r--r--xlators/features/marker/utils/src/procdiggy.h26
-rw-r--r--xlators/features/marker/utils/syncdaemon/Makefile.am6
-rw-r--r--xlators/features/marker/utils/syncdaemon/__init__.py0
-rw-r--r--xlators/features/marker/utils/syncdaemon/configinterface.py224
-rw-r--r--xlators/features/marker/utils/syncdaemon/gconf.py20
-rw-r--r--xlators/features/marker/utils/syncdaemon/gsyncd.py369
-rw-r--r--xlators/features/marker/utils/syncdaemon/libcxattr.py72
-rw-r--r--xlators/features/marker/utils/syncdaemon/master.py521
-rw-r--r--xlators/features/marker/utils/syncdaemon/monitor.py123
-rw-r--r--xlators/features/marker/utils/syncdaemon/resource.py851
-rw-r--r--xlators/features/marker/utils/syncdaemon/syncdutils.py273
-rw-r--r--xlators/features/metadisp/Makefile.am3
-rw-r--r--xlators/features/metadisp/src/Makefile.am38
-rw-r--r--xlators/features/metadisp/src/backend.c45
-rw-r--r--xlators/features/metadisp/src/fops-tmpl.c10
-rw-r--r--xlators/features/metadisp/src/gen-fops.py160
-rw-r--r--xlators/features/metadisp/src/metadisp-create.c101
-rw-r--r--xlators/features/metadisp/src/metadisp-fops.h51
-rw-r--r--xlators/features/metadisp/src/metadisp-fsync.c54
-rw-r--r--xlators/features/metadisp/src/metadisp-lookup.c90
-rw-r--r--xlators/features/metadisp/src/metadisp-open.c70
-rw-r--r--xlators/features/metadisp/src/metadisp-readdir.c65
-rw-r--r--xlators/features/metadisp/src/metadisp-setattr.c90
-rw-r--r--xlators/features/metadisp/src/metadisp-stat.c124
-rw-r--r--xlators/features/metadisp/src/metadisp-unlink.c160
-rw-r--r--xlators/features/metadisp/src/metadisp.c46
-rw-r--r--xlators/features/metadisp/src/metadisp.h45
-rw-r--r--xlators/features/namespace/Makefile.am3
-rw-r--r--xlators/features/namespace/src/Makefile.am17
-rw-r--r--xlators/features/namespace/src/namespace.c1344
-rw-r--r--xlators/features/namespace/src/namespace.h23
-rw-r--r--xlators/features/path-convertor/Makefile.am3
-rw-r--r--xlators/features/path-convertor/src/Makefile.am14
-rw-r--r--xlators/features/path-convertor/src/path-mem-types.h32
-rw-r--r--xlators/features/path-convertor/src/path.c1239
-rw-r--r--xlators/features/quiesce/src/Makefile.am10
-rw-r--r--xlators/features/quiesce/src/quiesce-mem-types.h27
-rw-r--r--xlators/features/quiesce/src/quiesce-messages.h28
-rw-r--r--xlators/features/quiesce/src/quiesce.c3401
-rw-r--r--xlators/features/quiesce/src/quiesce.h88
-rw-r--r--xlators/features/quota/src/Makefile.am29
-rw-r--r--xlators/features/quota/src/quota-enforcer-client.c503
-rw-r--r--xlators/features/quota/src/quota-mem-types.h45
-rw-r--r--xlators/features/quota/src/quota-messages.h39
-rw-r--r--xlators/features/quota/src/quota.c6961
-rw-r--r--xlators/features/quota/src/quota.h389
-rw-r--r--xlators/features/quota/src/quotad-aggregator.c494
-rw-r--r--xlators/features/quota/src/quotad-aggregator.h38
-rw-r--r--xlators/features/quota/src/quotad-helpers.c107
-rw-r--r--xlators/features/quota/src/quotad-helpers.h24
-rw-r--r--xlators/features/quota/src/quotad.c245
-rw-r--r--xlators/features/read-only/src/Makefile.am14
-rw-r--r--xlators/features/read-only/src/read-only-common.c435
-rw-r--r--xlators/features/read-only/src/read-only-common.h140
-rw-r--r--xlators/features/read-only/src/read-only-mem-types.h20
-rw-r--r--xlators/features/read-only/src/read-only.c191
-rw-r--r--xlators/features/read-only/src/read-only.h37
-rw-r--r--xlators/features/read-only/src/worm-helper.c395
-rw-r--r--xlators/features/read-only/src/worm-helper.h44
-rw-r--r--xlators/features/read-only/src/worm.c750
-rw-r--r--xlators/features/sdfs/Makefile.am3
-rw-r--r--xlators/features/sdfs/src/Makefile.am19
-rw-r--r--xlators/features/sdfs/src/sdfs-messages.h67
-rw-r--r--xlators/features/sdfs/src/sdfs.c1479
-rw-r--r--xlators/features/sdfs/src/sdfs.h49
-rw-r--r--xlators/features/selinux/Makefile.am3
-rw-r--r--xlators/features/selinux/src/Makefile.am20
-rw-r--r--xlators/features/selinux/src/selinux-mem-types.h19
-rw-r--r--xlators/features/selinux/src/selinux-messages.h30
-rw-r--r--xlators/features/selinux/src/selinux.c323
-rw-r--r--xlators/features/selinux/src/selinux.h24
-rw-r--r--xlators/features/shard/Makefile.am3
-rw-r--r--xlators/features/shard/src/Makefile.am17
-rw-r--r--xlators/features/shard/src/shard-mem-types.h24
-rw-r--r--xlators/features/shard/src/shard-messages.h39
-rw-r--r--xlators/features/shard/src/shard.c7382
-rw-r--r--xlators/features/shard/src/shard.h348
-rw-r--r--xlators/features/snapview-client/Makefile.am1
-rw-r--r--xlators/features/snapview-client/src/Makefile.am16
-rw-r--r--xlators/features/snapview-client/src/snapview-client-mem-types.h24
-rw-r--r--xlators/features/snapview-client/src/snapview-client-messages.h71
-rw-r--r--xlators/features/snapview-client/src/snapview-client.c2791
-rw-r--r--xlators/features/snapview-client/src/snapview-client.h101
-rw-r--r--xlators/features/snapview-server/Makefile.am1
-rw-r--r--xlators/features/snapview-server/src/Makefile.am25
-rw-r--r--xlators/features/snapview-server/src/snapview-server-helpers.c715
-rw-r--r--xlators/features/snapview-server/src/snapview-server-mem-types.h25
-rw-r--r--xlators/features/snapview-server/src/snapview-server-messages.h54
-rw-r--r--xlators/features/snapview-server/src/snapview-server-mgmt.c524
-rw-r--r--xlators/features/snapview-server/src/snapview-server.c2720
-rw-r--r--xlators/features/snapview-server/src/snapview-server.h255
-rw-r--r--xlators/features/thin-arbiter/Makefile.am3
-rw-r--r--xlators/features/thin-arbiter/src/Makefile.am22
-rw-r--r--xlators/features/thin-arbiter/src/thin-arbiter-mem-types.h19
-rw-r--r--xlators/features/thin-arbiter/src/thin-arbiter-messages.h28
-rw-r--r--xlators/features/thin-arbiter/src/thin-arbiter.c661
-rw-r--r--xlators/features/thin-arbiter/src/thin-arbiter.h59
-rw-r--r--xlators/features/trash/src/Makefile.am12
-rw-r--r--xlators/features/trash/src/trash-mem-types.h32
-rw-r--r--xlators/features/trash/src/trash.c3763
-rw-r--r--xlators/features/trash/src/trash.h128
-rw-r--r--xlators/features/upcall/Makefile.am3
-rw-r--r--xlators/features/upcall/src/Makefile.am23
-rw-r--r--xlators/features/upcall/src/upcall-cache-invalidation.h18
-rw-r--r--xlators/features/upcall/src/upcall-internal.c689
-rw-r--r--xlators/features/upcall/src/upcall-mem-types.h23
-rw-r--r--xlators/features/upcall/src/upcall-messages.h29
-rw-r--r--xlators/features/upcall/src/upcall.c2505
-rw-r--r--xlators/features/upcall/src/upcall.h131
-rw-r--r--xlators/features/utime/Makefile.am3
-rw-r--r--xlators/features/utime/src/Makefile.am41
-rw-r--r--xlators/features/utime/src/utime-autogen-fops-tmpl.c28
-rw-r--r--xlators/features/utime/src/utime-autogen-fops-tmpl.h22
-rwxr-xr-xxlators/features/utime/src/utime-gen-fops-c.py147
-rwxr-xr-xxlators/features/utime/src/utime-gen-fops-h.py35
-rw-r--r--xlators/features/utime/src/utime-helpers.c110
-rw-r--r--xlators/features/utime/src/utime-helpers.h25
-rw-r--r--xlators/features/utime/src/utime-mem-types.h21
-rw-r--r--xlators/features/utime/src/utime-messages.h29
-rw-r--r--xlators/features/utime/src/utime.c392
-rw-r--r--xlators/features/utime/src/utime.h23
-rw-r--r--xlators/lib/src/libxlator.c745
-rw-r--r--xlators/lib/src/libxlator.h204
-rw-r--r--xlators/meta/Makefile.am2
-rw-r--r--xlators/meta/src/Makefile.am48
-rw-r--r--xlators/meta/src/active-link.c34
-rw-r--r--xlators/meta/src/cmdline-file.c39
-rw-r--r--xlators/meta/src/frames-file.c107
-rw-r--r--xlators/meta/src/graph-dir.c98
-rw-r--r--xlators/meta/src/graphs-dir.c67
-rw-r--r--xlators/meta/src/history-file.c44
-rw-r--r--xlators/meta/src/logfile-link.c34
-rw-r--r--xlators/meta/src/logging-dir.c44
-rw-r--r--xlators/meta/src/loglevel-file.c50
-rw-r--r--xlators/meta/src/mallinfo-file.c36
-rw-r--r--xlators/meta/src/measure-file.c49
-rw-r--r--xlators/meta/src/meminfo-file.c44
-rw-r--r--xlators/meta/src/meta-defaults.c655
-rw-r--r--xlators/meta/src/meta-helpers.c332
-rw-r--r--xlators/meta/src/meta-hooks.h48
-rw-r--r--xlators/meta/src/meta-mem-types.h36
-rw-r--r--xlators/meta/src/meta.c1355
-rw-r--r--xlators/meta/src/meta.h162
-rw-r--r--xlators/meta/src/misc.c67
-rw-r--r--xlators/meta/src/misc.h31
-rw-r--r--xlators/meta/src/name-file.c44
-rw-r--r--xlators/meta/src/option-file.c45
-rw-r--r--xlators/meta/src/options-dir.c65
-rw-r--r--xlators/meta/src/private-file.c44
-rw-r--r--xlators/meta/src/process_uuid-file.c37
-rw-r--r--xlators/meta/src/profile-file.c44
-rw-r--r--xlators/meta/src/root-dir.c77
-rw-r--r--xlators/meta/src/subvolume-link.c56
-rw-r--r--xlators/meta/src/subvolumes-dir.c62
-rw-r--r--xlators/meta/src/top-link.c40
-rw-r--r--xlators/meta/src/tree.c179
-rw-r--r--xlators/meta/src/tree.h35
-rw-r--r--xlators/meta/src/type-file.c44
-rw-r--r--xlators/meta/src/version-file.c37
-rw-r--r--xlators/meta/src/view-dir.c33
-rw-r--r--xlators/meta/src/view.c258
-rw-r--r--xlators/meta/src/view.h32
-rw-r--r--xlators/meta/src/volfile-file.c79
-rw-r--r--xlators/meta/src/xlator-dir.c97
-rw-r--r--xlators/mgmt/glusterd/src/Makefile.am79
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-bitd-svc.c206
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-bitd-svc.h40
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-bitrot.c822
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-brick-ops.c3812
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-conn-helper.c21
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-conn-helper.h21
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-conn-mgmt.c191
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-conn-mgmt.h53
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-errno.h33
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-ganesha.c927
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-geo-rep.c7732
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-geo-rep.h52
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-gfproxyd-svc-helper.c235
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-gfproxyd-svc-helper.h51
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-gfproxyd-svc.c478
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-gfproxyd-svc.h47
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handler.c8292
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-handshake.c2848
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-hooks.c971
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-hooks.h105
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-locks.c870
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-locks.h57
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-log-ops.c480
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mem-types.h115
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-messages.h451
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt-handler.c1144
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt.c3114
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mgmt.h97
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mountbroker.c1212
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-mountbroker.h57
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-nfs-svc.c228
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-nfs-svc.h27
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.c10975
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-op-sm.h373
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-peer-utils.c1058
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-peer-utils.h82
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-pmap.c886
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-pmap.h83
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-proc-mgmt.c152
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-proc-mgmt.h44
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.c2736
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quota.h17
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quotad-svc.c217
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-quotad-svc.h31
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rcu.h36
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rebalance.c1819
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-replace-brick.c2412
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-reset-brick.c376
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-rpc-ops.c3863
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-scrub-svc.c207
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-scrub-svc.h45
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-server-quorum.c486
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-server-quorum.h46
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-shd-svc-helper.c153
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-shd-svc-helper.h42
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-shd-svc.c796
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-shd-svc.h45
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-sm.c2237
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-sm.h271
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapd-svc-helper.c75
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapd-svc-helper.h32
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapd-svc.c478
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapd-svc.h42
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot-utils.c4290
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot-utils.h169
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-snapshot.c10087
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-statedump.c243
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-statedump.h18
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.c6489
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-store.h264
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-svc-helper.c1047
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-svc-helper.h72
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-svc-mgmt.c536
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-svc-mgmt.h112
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.c2285
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-syncop.h131
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-tierd-svc-helper.c207
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.c17919
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-utils.h927
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.c8572
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volgen.h371
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-ops.c4453
-rw-r--r--xlators/mgmt/glusterd/src/glusterd-volume-set.c3146
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.c2982
-rw-r--r--xlators/mgmt/glusterd/src/glusterd.h1563
-rw-r--r--xlators/mount/fuse/src/Makefile.am29
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.c9695
-rw-r--r--xlators/mount/fuse/src/fuse-bridge.h758
-rw-r--r--xlators/mount/fuse/src/fuse-helpers.c970
-rw-r--r--xlators/mount/fuse/src/fuse-mem-types.h44
-rw-r--r--xlators/mount/fuse/src/fuse-resolve.c888
-rw-r--r--xlators/mount/fuse/utils/Makefile.am9
-rwxr-xr-xxlators/mount/fuse/utils/mount.glusterfs.in923
-rwxr-xr-xxlators/mount/fuse/utils/mount_glusterfs.in618
-rw-r--r--xlators/nfs/server/src/Makefile.am35
-rw-r--r--xlators/nfs/server/src/acl3.c933
-rw-r--r--xlators/nfs/server/src/acl3.h42
-rw-r--r--xlators/nfs/server/src/auth-cache.c496
-rw-r--r--xlators/nfs/server/src/auth-cache.h52
-rw-r--r--xlators/nfs/server/src/exports.c1484
-rw-r--r--xlators/nfs/server/src/exports.h93
-rw-r--r--xlators/nfs/server/src/mount3-auth.c642
-rw-r--r--xlators/nfs/server/src/mount3-auth.h59
-rw-r--r--xlators/nfs/server/src/mount3.c5270
-rw-r--r--xlators/nfs/server/src/mount3.h210
-rw-r--r--xlators/nfs/server/src/mount3udp_svc.c329
-rw-r--r--xlators/nfs/server/src/netgroups.c1161
-rw-r--r--xlators/nfs/server/src/netgroups.h53
-rw-r--r--xlators/nfs/server/src/nfs-common.c648
-rw-r--r--xlators/nfs/server/src/nfs-common.h74
-rw-r--r--xlators/nfs/server/src/nfs-fops.c2249
-rw-r--r--xlators/nfs/server/src/nfs-fops.h322
-rw-r--r--xlators/nfs/server/src/nfs-generics.c354
-rw-r--r--xlators/nfs/server/src/nfs-generics.h168
-rw-r--r--xlators/nfs/server/src/nfs-inodes.c790
-rw-r--r--xlators/nfs/server/src/nfs-inodes.h82
-rw-r--r--xlators/nfs/server/src/nfs-mem-types.h80
-rw-r--r--xlators/nfs/server/src/nfs-messages.h102
-rw-r--r--xlators/nfs/server/src/nfs.c2819
-rw-r--r--xlators/nfs/server/src/nfs.h177
-rw-r--r--xlators/nfs/server/src/nfs3-fh.c357
-rw-r--r--xlators/nfs/server/src/nfs3-fh.h135
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.c4999
-rw-r--r--xlators/nfs/server/src/nfs3-helpers.h297
-rw-r--r--xlators/nfs/server/src/nfs3.c9033
-rw-r--r--xlators/nfs/server/src/nfs3.h399
-rw-r--r--xlators/nfs/server/src/nfsserver.sym12
-rw-r--r--xlators/nfs/server/src/nlm4.c4173
-rw-r--r--xlators/nfs/server/src/nlm4.h126
-rw-r--r--xlators/nfs/server/src/nlmcbk_svc.c182
-rw-r--r--xlators/performance/Makefile.am3
-rw-r--r--xlators/performance/io-cache/src/Makefile.am11
-rw-r--r--xlators/performance/io-cache/src/io-cache-messages.h69
-rw-r--r--xlators/performance/io-cache/src/io-cache.c3005
-rw-r--r--xlators/performance/io-cache/src/io-cache.h408
-rw-r--r--xlators/performance/io-cache/src/ioc-inode.c287
-rw-r--r--xlators/performance/io-cache/src/ioc-mem-types.h24
-rw-r--r--xlators/performance/io-cache/src/page.c1443
-rw-r--r--xlators/performance/io-threads/src/Makefile.am10
-rw-r--r--xlators/performance/io-threads/src/io-threads-messages.h41
-rw-r--r--xlators/performance/io-threads/src/io-threads.c3316
-rw-r--r--xlators/performance/io-threads/src/io-threads.h107
-rw-r--r--xlators/performance/io-threads/src/iot-mem-types.h9
-rw-r--r--xlators/performance/md-cache/src/Makefile.am14
-rw-r--r--xlators/performance/md-cache/src/md-cache-mem-types.h13
-rw-r--r--xlators/performance/md-cache/src/md-cache-messages.h29
-rw-r--r--xlators/performance/md-cache/src/md-cache.c4509
-rw-r--r--xlators/performance/nl-cache/Makefile.am3
-rw-r--r--xlators/performance/nl-cache/src/Makefile.am12
-rw-r--r--xlators/performance/nl-cache/src/nl-cache-helper.c1201
-rw-r--r--xlators/performance/nl-cache/src/nl-cache-mem-types.h27
-rw-r--r--xlators/performance/nl-cache/src/nl-cache-messages.h29
-rw-r--r--xlators/performance/nl-cache/src/nl-cache.c840
-rw-r--r--xlators/performance/nl-cache/src/nl-cache.h175
-rw-r--r--xlators/performance/open-behind/Makefile.am1
-rw-r--r--xlators/performance/open-behind/src/Makefile.am16
-rw-r--r--xlators/performance/open-behind/src/open-behind-mem-types.h22
-rw-r--r--xlators/performance/open-behind/src/open-behind-messages.h32
-rw-r--r--xlators/performance/open-behind/src/open-behind.c1101
-rw-r--r--xlators/performance/quick-read/src/Makefile.am10
-rw-r--r--xlators/performance/quick-read/src/quick-read-mem-types.h15
-rw-r--r--xlators/performance/quick-read/src/quick-read-messages.h31
-rw-r--r--xlators/performance/quick-read/src/quick-read.c4786
-rw-r--r--xlators/performance/quick-read/src/quick-read.h131
-rw-r--r--xlators/performance/read-ahead/src/Makefile.am10
-rw-r--r--xlators/performance/read-ahead/src/page.c846
-rw-r--r--xlators/performance/read-ahead/src/read-ahead-mem-types.h17
-rw-r--r--xlators/performance/read-ahead/src/read-ahead-messages.h31
-rw-r--r--xlators/performance/read-ahead/src/read-ahead.c1775
-rw-r--r--xlators/performance/read-ahead/src/read-ahead.h183
-rw-r--r--xlators/performance/readdir-ahead/Makefile.am3
-rw-r--r--xlators/performance/readdir-ahead/src/Makefile.am18
-rw-r--r--xlators/performance/readdir-ahead/src/readdir-ahead-mem-types.h24
-rw-r--r--xlators/performance/readdir-ahead/src/readdir-ahead-messages.h30
-rw-r--r--xlators/performance/readdir-ahead/src/readdir-ahead.c1382
-rw-r--r--xlators/performance/readdir-ahead/src/readdir-ahead.h98
-rw-r--r--xlators/performance/symlink-cache/Makefile.am3
-rw-r--r--xlators/performance/symlink-cache/src/Makefile.am12
-rw-r--r--xlators/performance/symlink-cache/src/symlink-cache.c400
-rw-r--r--xlators/performance/write-behind/src/Makefile.am10
-rw-r--r--xlators/performance/write-behind/src/write-behind-mem-types.h15
-rw-r--r--xlators/performance/write-behind/src/write-behind-messages.h31
-rw-r--r--xlators/performance/write-behind/src/write-behind.c5075
-rw-r--r--xlators/playground/Makefile.am2
-rw-r--r--xlators/playground/rot-13/Makefile.am (renamed from mod_glusterfs/apache/1.3/Makefile.am)0
-rw-r--r--xlators/playground/rot-13/src/Makefile.am (renamed from xlators/encryption/rot-13/src/Makefile.am)8
-rw-r--r--xlators/playground/rot-13/src/rot-13.c166
-rw-r--r--xlators/playground/rot-13/src/rot-13.h18
-rw-r--r--xlators/playground/template/Makefile.am2
-rw-r--r--xlators/playground/template/src/Makefile.am17
-rw-r--r--xlators/playground/template/src/template.c186
-rw-r--r--xlators/playground/template/src/template.h43
-rw-r--r--xlators/protocol/auth/addr/src/Makefile.am8
-rw-r--r--xlators/protocol/auth/addr/src/addr.c492
-rw-r--r--xlators/protocol/auth/login/src/Makefile.am10
-rw-r--r--xlators/protocol/auth/login/src/login.c300
-rw-r--r--xlators/protocol/client/src/Makefile.am18
-rw-r--r--xlators/protocol/client/src/client-callback.c316
-rw-r--r--xlators/protocol/client/src/client-common.c3589
-rw-r--r--xlators/protocol/client/src/client-common.h630
-rw-r--r--xlators/protocol/client/src/client-handshake.c2863
-rw-r--r--xlators/protocol/client/src/client-helpers.c1003
-rw-r--r--xlators/protocol/client/src/client-lk.c1106
-rw-r--r--xlators/protocol/client/src/client-mem-types.h17
-rw-r--r--xlators/protocol/client/src/client-messages.h174
-rw-r--r--xlators/protocol/client/src/client-rpc-fops.c6079
-rw-r--r--xlators/protocol/client/src/client-rpc-fops_v2.c6177
-rw-r--r--xlators/protocol/client/src/client.c4365
-rw-r--r--xlators/protocol/client/src/client.h549
-rw-r--r--xlators/protocol/client/src/client3_1-fops.c5920
-rw-r--r--xlators/protocol/legacy/Makefile.am3
-rw-r--r--xlators/protocol/legacy/client/Makefile.am3
-rw-r--r--xlators/protocol/legacy/client/src/Makefile.am21
-rw-r--r--xlators/protocol/legacy/client/src/client-mem-types.h43
-rw-r--r--xlators/protocol/legacy/client/src/client-protocol.c6683
-rw-r--r--xlators/protocol/legacy/client/src/client-protocol.h178
-rw-r--r--xlators/protocol/legacy/client/src/saved-frames.c196
-rw-r--r--xlators/protocol/legacy/client/src/saved-frames.h79
-rw-r--r--xlators/protocol/legacy/lib/Makefile.am3
-rw-r--r--xlators/protocol/legacy/lib/src/Makefile.am14
-rw-r--r--xlators/protocol/legacy/lib/src/protocol.c108
-rw-r--r--xlators/protocol/legacy/lib/src/protocol.h1118
-rw-r--r--xlators/protocol/legacy/lib/src/transport.c422
-rw-r--r--xlators/protocol/legacy/lib/src/transport.h106
-rw-r--r--xlators/protocol/legacy/server/Makefile.am3
-rw-r--r--xlators/protocol/legacy/server/src/Makefile.am26
-rw-r--r--xlators/protocol/legacy/server/src/authenticate.c249
-rw-r--r--xlators/protocol/legacy/server/src/authenticate.h60
-rw-r--r--xlators/protocol/legacy/server/src/server-helpers.c622
-rw-r--r--xlators/protocol/legacy/server/src/server-helpers.h48
-rw-r--r--xlators/protocol/legacy/server/src/server-mem-types.h39
-rw-r--r--xlators/protocol/legacy/server/src/server-protocol.c6587
-rw-r--r--xlators/protocol/legacy/server/src/server-protocol.h191
-rw-r--r--xlators/protocol/legacy/server/src/server-resolve.c658
-rw-r--r--xlators/protocol/legacy/transport/Makefile.am3
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/Makefile.am1
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/Makefile.am19
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/ib-verbs-mem-types.h39
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/ib-verbs.c2625
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/ib-verbs.h220
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/name.c712
-rw-r--r--xlators/protocol/legacy/transport/ib-verbs/src/name.h47
-rw-r--r--xlators/protocol/legacy/transport/socket/Makefile.am1
-rw-r--r--xlators/protocol/legacy/transport/socket/src/Makefile.am19
-rw-r--r--xlators/protocol/legacy/transport/socket/src/name.c740
-rw-r--r--xlators/protocol/legacy/transport/socket/src/name.h44
-rw-r--r--xlators/protocol/legacy/transport/socket/src/socket-mem-types.h36
-rw-r--r--xlators/protocol/legacy/transport/socket/src/socket.c1625
-rw-r--r--xlators/protocol/legacy/transport/socket/src/socket.h129
-rw-r--r--xlators/protocol/server/src/Makefile.am30
-rw-r--r--xlators/protocol/server/src/authenticate.c386
-rw-r--r--xlators/protocol/server/src/authenticate.h58
-rw-r--r--xlators/protocol/server/src/server-common.c842
-rw-r--r--xlators/protocol/server/src/server-common.h199
-rw-r--r--xlators/protocol/server/src/server-handshake.c1407
-rw-r--r--xlators/protocol/server/src/server-helpers.c2416
-rw-r--r--xlators/protocol/server/src/server-helpers.h133
-rw-r--r--xlators/protocol/server/src/server-mem-types.h42
-rw-r--r--xlators/protocol/server/src/server-messages.h168
-rw-r--r--xlators/protocol/server/src/server-resolve.c925
-rw-r--r--xlators/protocol/server/src/server-rpc-fops.c6084
-rw-r--r--xlators/protocol/server/src/server-rpc-fops_v2.c6031
-rw-r--r--xlators/protocol/server/src/server.c2704
-rw-r--r--xlators/protocol/server/src/server.h335
-rw-r--r--xlators/protocol/server/src/server3_1-fops.c5688
-rw-r--r--xlators/storage/Makefile.am2
-rw-r--r--xlators/storage/bdb/Makefile.am3
-rw-r--r--xlators/storage/bdb/src/Makefile.am18
-rw-r--r--xlators/storage/bdb/src/bctx.c341
-rw-r--r--xlators/storage/bdb/src/bdb-ll.c1464
-rw-r--r--xlators/storage/bdb/src/bdb-mem-types.h42
-rw-r--r--xlators/storage/bdb/src/bdb.c3603
-rw-r--r--xlators/storage/bdb/src/bdb.h530
-rw-r--r--xlators/storage/posix/src/Makefile.am25
-rw-r--r--xlators/storage/posix/src/posix-aio.c556
-rw-r--r--xlators/storage/posix/src/posix-aio.h34
-rw-r--r--xlators/storage/posix/src/posix-common.c1524
-rw-r--r--xlators/storage/posix/src/posix-entry-ops.c2496
-rw-r--r--xlators/storage/posix/src/posix-gfid-path.c243
-rw-r--r--xlators/storage/posix/src/posix-gfid-path.h28
-rw-r--r--xlators/storage/posix/src/posix-handle.c1362
-rw-r--r--xlators/storage/posix/src/posix-handle.h334
-rw-r--r--xlators/storage/posix/src/posix-helpers.c4142
-rw-r--r--xlators/storage/posix/src/posix-inode-fd-ops.c6004
-rw-r--r--xlators/storage/posix/src/posix-inode-handle.h118
-rw-r--r--xlators/storage/posix/src/posix-mem-types.h39
-rw-r--r--xlators/storage/posix/src/posix-messages.h74
-rw-r--r--xlators/storage/posix/src/posix-metadata-disk.h31
-rw-r--r--xlators/storage/posix/src/posix-metadata.c916
-rw-r--r--xlators/storage/posix/src/posix-metadata.h71
-rw-r--r--xlators/storage/posix/src/posix.c4360
-rw-r--r--xlators/storage/posix/src/posix.h733
-rw-r--r--xlators/system/posix-acl/src/Makefile.am17
-rw-r--r--xlators/system/posix-acl/src/posix-acl-mem-types.h23
-rw-r--r--xlators/system/posix-acl/src/posix-acl-messages.h28
-rw-r--r--xlators/system/posix-acl/src/posix-acl-xattr.c253
-rw-r--r--xlators/system/posix-acl/src/posix-acl-xattr.h53
-rw-r--r--xlators/system/posix-acl/src/posix-acl.c3186
-rw-r--r--xlators/system/posix-acl/src/posix-acl.h104
-rw-r--r--xlators/xlator.sym1
2633 files changed, 675220 insertions, 343589 deletions
diff --git a/.clang-format b/.clang-format
new file mode 100644
index 00000000000..84c2efe3fad
--- /dev/null
+++ b/.clang-format
@@ -0,0 +1,107 @@
+---
+Language: Cpp
+# BasedOnStyle: Chromium
+AccessModifierOffset: -1
+AlignAfterOpenBracket: Align
+AlignConsecutiveAssignments: false
+AlignConsecutiveDeclarations: false
+AlignEscapedNewlines: Right
+AlignOperands: true
+AlignTrailingComments: true
+AllowAllParametersOfDeclarationOnNextLine: false
+AllowShortBlocksOnASingleLine: false
+AllowShortCaseLabelsOnASingleLine: false
+AllowShortFunctionsOnASingleLine: Inline
+AllowShortIfStatementsOnASingleLine: false
+AllowShortLoopsOnASingleLine: false
+AlwaysBreakAfterDefinitionReturnType: All
+AlwaysBreakAfterReturnType: All
+AlwaysBreakBeforeMultilineStrings: true
+AlwaysBreakTemplateDeclarations: true
+BinPackArguments: true
+BinPackParameters: true
+BraceWrapping:
+ AfterClass: false
+ AfterControlStatement: false
+ AfterEnum: false
+ AfterFunction: true
+ AfterNamespace: false
+ AfterObjCDeclaration: false
+ AfterStruct: false
+ AfterUnion: false
+ BeforeCatch: false
+ BeforeElse: false
+ IndentBraces: false
+ SplitEmptyFunction: true
+ SplitEmptyRecord: true
+ SplitEmptyNamespace: true
+BreakBeforeBinaryOperators: None
+BreakBeforeBraces: Linux
+BreakBeforeInheritanceComma: false
+BreakBeforeTernaryOperators: true
+BreakConstructorInitializersBeforeComma: false
+BreakConstructorInitializers: BeforeColon
+BreakAfterJavaFieldAnnotations: false
+BreakStringLiterals: true
+ColumnLimit: 80
+CommentPragmas: '^ IWYU pragma:'
+CompactNamespaces: false
+ConstructorInitializerAllOnOneLineOrOnePerLine: true
+ConstructorInitializerIndentWidth: 4
+ContinuationIndentWidth: 4
+Cpp11BracedListStyle: true
+DerivePointerAlignment: false
+DisableFormat: false
+ExperimentalAutoDetectBinPacking: false
+FixNamespaceComments: true
+ForEachMacros:
+ - foreach
+ - Q_FOREACH
+ - BOOST_FOREACH
+IncludeCategories:
+ - Regex: '^<.*\.h>'
+ Priority: 1
+ - Regex: '^<.*'
+ Priority: 2
+ - Regex: '.*'
+ Priority: 3
+IncludeIsMainRegex: '([-_](test|unittest))?$'
+IndentCaseLabels: true
+IndentWidth: 4
+IndentWrappedFunctionNames: false
+JavaScriptQuotes: Leave
+JavaScriptWrapImports: true
+KeepEmptyLinesAtTheStartOfBlocks: false
+MacroBlockBegin: ''
+MacroBlockEnd: ''
+MaxEmptyLinesToKeep: 1
+NamespaceIndentation: None
+ObjCBlockIndentWidth: 2
+ObjCSpaceAfterProperty: false
+ObjCSpaceBeforeProtocolList: false
+PenaltyBreakAssignment: 200
+PenaltyBreakBeforeFirstCallParameter: 1
+PenaltyBreakComment: 300
+PenaltyBreakFirstLessLess: 120
+PenaltyBreakString: 1000
+PenaltyExcessCharacter: 1000000
+PenaltyReturnTypeOnItsOwnLine: 200
+PointerAlignment: Right
+ReflowComments: true
+SortIncludes: false
+SortUsingDeclarations: true
+SpaceAfterCStyleCast: false
+SpaceAfterTemplateKeyword: true
+SpaceBeforeAssignmentOperators: true
+SpaceBeforeParens: ControlStatements
+SpaceInEmptyParentheses: false
+SpacesBeforeTrailingComments: 2
+SpacesInAngles: false
+SpacesInContainerLiterals: true
+SpacesInCStyleCastParentheses: false
+SpacesInParentheses: false
+SpacesInSquareBrackets: false
+Standard: Auto
+TabWidth: 8
+UseTab: Never
+...
diff --git a/.github/ISSUE_TEMPLATE b/.github/ISSUE_TEMPLATE
new file mode 100644
index 00000000000..386ed2d8dd5
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE
@@ -0,0 +1,30 @@
+<!-- Please use this template while reporting an issue, providing as much information as possible. Failure to do so may result in a delayed response. Thank you! -->
+
+**Description of problem:**
+
+
+**The exact command to reproduce the issue**:
+
+
+**The full output of the command that failed**:
+<details>
+
+
+
+</details>
+
+**Expected results:**
+
+
+**Additional info:**
+
+
+**- The output of the `gluster volume info` command**:
+<details>
+
+
+
+</details>
+
+**- The operating system / glusterfs version**:
+
diff --git a/swift/1.4.8/plugins/conf/db_file.db b/.github/PULL_REQUEST_TEMPLATE
index e69de29bb2d..e69de29bb2d 100644
--- a/swift/1.4.8/plugins/conf/db_file.db
+++ b/.github/PULL_REQUEST_TEMPLATE
diff --git a/.github/RELEASE_TRACKER_TEMPLATE b/.github/RELEASE_TRACKER_TEMPLATE
new file mode 100644
index 00000000000..502bbd5556c
--- /dev/null
+++ b/.github/RELEASE_TRACKER_TEMPLATE
@@ -0,0 +1,12 @@
+<!-- Please use this template while creating a tracker issue -->
+
+**Description of problem:**
+A tracker issue to track the issues that will be fixed as a part of this release
+
+
+**Major or minor release**:
+
+
+**Release version**:
+
+
diff --git a/.github/stale.yml b/.github/stale.yml
new file mode 100644
index 00000000000..460e327c6ea
--- /dev/null
+++ b/.github/stale.yml
@@ -0,0 +1,25 @@
+# Number of days of inactivity before an issue becomes stale
+daysUntilStale: 210
+# Number of days of inactivity before a stale issue is closed
+daysUntilClose: 15
+# Issues with these labels will never be considered stale
+exemptLabels:
+ - pinned
+ - security
+# Label to use when marking an issue as stale
+staleLabel: wontfix
+
+# Comment to post when marking an issue as stale. Set to `false` to disable
+markComment: >
+ Thank you for your contributions.
+
+ Noticed that this issue is not having any activity in last ~6 months! We
+ are marking this issue as stale because it has not had recent activity.
+
+ It will be closed in 2 weeks if no one responds with a comment here.
+
+
+# Comment to post when closing a stale issue. Set to `false` to disable
+closeComment: >
+ Closing this issue as there was no update since my last update on issue.
+ If this is an issue which is still valid, feel free to open it.
diff --git a/.gitignore b/.gitignore
index c5371b26436..fc5ba586f8e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,31 +3,123 @@ autom4te.cache
build
config.*
configure
+cscope.*
+tags
depcomp
+INSTALL
install-sh
ltmain.sh
+Makefile
Makefile.in
missing
+stamp-h1
+stamp-h2
+test-driver
+*compile
+*.gcda
+*.gcno
*.sw?
*~
-*lo
-*la
-*o
+*.lo
+*.la
+*.o
+*.tar.gz
+*.rpm
+*.diff
+*.patch
.libs
-Makefile
-stamp-h1
+.deps
+.dirstamp
+
+# Softlinks to test and log
+log
+*.vol
+.clang-format
+
+# cmocka unit tests
+*.log
+*.trs
+*_unittest
# Generated files
-extras/init.d/glusterfs-server.plist
-extras/init.d/glusterfsd-Debian
-extras/init.d/glusterfsd-Redhat
-extras/init.d/glusterfsd-SuSE
+site.h
+*.py[co]
+api/examples/__init__.py
+api/examples/setup.py
+api/src/gfapi.map
+cli/src/gluster
+contrib/fuse-util/fusermount-glusterfs
+extras/geo-rep/gsync-sync-gfid
+extras/geo-rep/schedule_georep.py
+extras/snap_scheduler/conf.py
+extras/init.d/glusterd-Debian
+extras/init.d/glusterd-FreeBSD
+extras/init.d/glusterd-Redhat
+extras/init.d/glusterd-SuSE
+extras/init.d/glusterd.plist
+extras/ocf/glusterd
+extras/ocf/volume
+extras/run-gluster.tmpfiles
+extras/systemd/glusterd.service
+extras/systemd/gluster-ta-volume.service
+extras/systemd/glusterfssharedstorage.service
+extras/who-wrote-glusterfs/gitdm
+geo-replication/.tox
+geo-replication/gsyncd.conf
+geo-replication/src/gsyncd
+geo-replication/src/peer_gsec_create
+geo-replication/src/peer_mountbroker
+geo-replication/src/peer_mountbroker.py
+geo-replication/src/set_geo_rep_pem_keys.sh
+geo-replication/src/peer_georep-sshkey.py
+geo-replication/syncdaemon.egg-info
+geo-replication/syncdaemon/conf.py
+geo-replication/tests/unit/.coverage
+geo-replication/tests/unit/cover
+geo-replication/tests/unit/coverage.xml
+geo-replication/tests/unit/nosetests.xml
+geo-replication/tests/unit/results.html
+glusterfs-api.pc
glusterfs.spec
-libtool
-xlators/mount/fuse/utils/mount.glusterfs
-xlators/mount/fuse/utils/mount_glusterfs
-argp-standalone/libargp.a
+glusterfsd/src/glusterd
+glusterfsd/src/glusterfs
glusterfsd/src/glusterfsd
-libglusterfs/src/spec.lex.c
+glusterfsd/src/gf_attach
+heal/src/glfsheal
+libgfchangelog.pc
+libglusterfs/src/graph.lex.c
libglusterfs/src/y.tab.c
libglusterfs/src/y.tab.h
+libglusterfs/src/defaults.c
+libglusterfs/src/cli1-xdr.h
+libglusterfs/src/protocol-common.h
+libtool
+# copied XDR for cyclic libglusterfs <-> rpc-header dependency
+run-tests.sh
+!tests/basic/fuse/Makefile
+!tests/basic/gfapi/Makefile
+tests/env.rc
+tests/utils/arequal-checksum
+xlators/features/glupy/src/__init__.py
+xlators/features/glupy/src/setup.py
+xlators/mount/fuse/utils/mount.glusterfs
+xlators/mount/fuse/utils/mount_glusterfs
+extras/peer_add_secret_pub
+tools/gfind_missing_files/gcrawler
+tools/glusterfind/glusterfind
+tools/glusterfind/src/tool.conf
+# Eventing
+events/src/eventsapiconf.py
+extras/systemd/glustereventsd.service
+events/src/eventtypes.py
+libglusterfs/src/eventtypes.h
+extras/init.d/glustereventsd-Debian
+extras/init.d/glustereventsd-FreeBSD
+extras/init.d/glustereventsd-Redhat
+tools/setgfid2path/src/gluster-setgfid2path
+xlators/features/cloudsync/src/cloudsync-autogen-fops.c
+xlators/features/cloudsync/src/cloudsync-autogen-fops.h
+xlators/features/utime/src/utime-autogen-fops.c
+xlators/features/utime/src/utime-autogen-fops.h
+tests/basic/metadisp/ftruncate
+xlators/features/metadisp/src/fops.c
diff --git a/.mailmap b/.mailmap
new file mode 100644
index 00000000000..141a1667ffa
--- /dev/null
+++ b/.mailmap
@@ -0,0 +1,43 @@
+# .mailmap, see 'git short-log --help' for details
+#
+# This file needs to match extras/who-wrote-glusterfs/gitdm.aliases.
+#
+# Listing of contributors that filed patches with different email addresses.
+# Format: <name> <main-email> <alias> [<alias> ...]
+#
+
+Amar Tumballi <amarts@redhat.com> <amar@gluster.com> <amar@del.gluster.com>
+Anand Avati <avati@redhat.com> <avati@gluster.com> <avati@dev.gluster.com> <avati@amp.gluster.com> <avati@blackhole.gluster.com>
+Anush Shetty <ashetty@redhat.com> <anush@gluster.com>
+Csaba Henk <csaba@redhat.com> <csaba@gluster.com> <csaba@lowlife.hu> <csaba@zresearch.com>
+Günther Deschner <gd@redhat.com> <gd@samba.org>
+Harshavardhana <fharshav@redhat.com> <harsha@gluster.com> <harsha@zresearch.com> <harsha@dev.gluster.com> <harsha@harshavardhana.net>
+Ji-Hyeon Gim <potatogim@gluesys.com> <potatogim@potatogim.net>
+Justin Clift <justin@gluster.org> <jclift@redhat.com>
+Kaleb S. KEITHLEY <kkeithle@redhat.com> <kkeithle@f16node1.kkeithle.usersys.redhat.com> <kkeithle@linux.keithley.org>
+Kaushal M <kaushal@redhat.com> <kaushal@gluster.com>
+Kaushik BV <kbudiger@redhat.com> <kaushikbv@gluster.com>
+Krishna Srinivas <ksriniva@redhat.com> <krishna@gluster.com> <krishna@zresearch.com> <krishna@guest-laptop>
+Krishnan Parthasarathi <kparthas@redhat.com> <kp@gluster.com>
+Louis Zuckerman <louiszuckerman@gmail.com> <me@louiszuckerman.com>
+M S Vishwanath Bhat <vbhat@redhat.com> <msvbhat@gmail.com> <vishwanath@gluster.com>
+Michael Adam <madam@redhat.com> <obnox@samba.org>
+Oleksandr Natalenko <oleksandr@natalenko.name> <o.natalenko@lanet.ua>
+Patrick Uiterwijk <puiterwijk@fedoraproject.org> <patrick@puiterwijk.org>
+Pavan Sondur <pavan@gluster.com> <pavan@dev.gluster.com>
+Pete Zaitcev <zaitcev@kotori.zaitcev.us> <zaitcev@yahoo.com>
+Pranith Kumar K <pkarampu@redhat.com> <pranithk@gluster.com>
+Prashanth Pai <ppai@redhat.com> <nullpai@gmail.com>
+Raghavendra Bhat <raghavendra@redhat.com> <raghavendrabhat@gluster.com>
+Raghavendra G <rgowdapp@redhat.com> <raghavendra@gluster.com> <raghavendra@zresearch.com>
+Rahul C S <rahulcs@redhat.com> <rahulcssjce@gmail.com>
+Rajesh Amaravathi <rajesh@redhat.com> <rajesh@gluster.com> <rajesh.amaravathi@gmail.com>
+Ravishankar N <ravishankar@redhat.com> <root@ravi2.(none)>
+Sakshi Bansal <sabansal@redhat.com> <sabansal@localhost.localdomain>
+Shehjar Tikoo <shehjart@gluster.com> <shehjart@zresearch.com>
+Venky Shankar <vshankar@redhat.com> <venky@gluster.com>
+Vijay Bellur <vbellur@redhat.com> <vijay@gluster.com> <vijay@dev.gluster.com>
+Vijaykumar Koppad <vkoppad@redhat.com> <vijaykumar.koppad@gmail.com>
+Vijaikumar Mallikarjuna <vmallika@redhat.com>
+Vikas Gorur <vikas@gluster.com> <vikas@zresearch.com>
+shishir gowda <sgowda@redhat.com> <shishirng@gluster.com>
diff --git a/.testignore b/.testignore
new file mode 100644
index 00000000000..fe8f838bf2b
--- /dev/null
+++ b/.testignore
@@ -0,0 +1,64 @@
+.github/ISSUE_TEMPLATE
+.github/PULL_REQUEST_TEMPLATE
+.github/stale.yml
+.gitignore
+.mailmap
+.testignore
+.clang-format
+rfc.sh
+submit-for-review.sh
+AUTHORS
+CONTRIBUTING.md
+COPYING-GPLV2
+COPYING-LGPLV3
+ChangeLog
+INSTALL
+MAINTAINERS
+NEWS
+README.md
+THANKS
+COMMITMENT
+api/examples/README
+api/examples/getvolfile.py
+api/src/README.Symbol_Versions
+build-aux/checkpatch.pl
+contrib/fuse-lib/COPYING.LIB
+contrib/fuse-util/COPYING
+contrib/macfuse/COPYING.txt
+doc/*
+extras/FreeBSD/README.FreeBSD
+extras/Solaris/README.solaris
+extras/Ubuntu/README.Ubuntu
+extras/benchmarking/README
+extras/cliutils/README.md
+extras/command-completion/README
+extras/create_new_xlator/README.md
+extras/glusterfs.vim
+extras/glusterfs-logrotate
+extras/glusterfs-georep-logrotate
+extras/init.d/glusterd-Debian.in
+extras/init.d/glusterd-FreeBSD.in
+extras/init.d/glusterd-Redhat.in
+extras/init.d/glusterd-SuSE.in
+extras/init.d/glusterd.plist.in
+extras/init.d/glustereventsd-Debian.in
+extras/init.d/glustereventsd-FreeBSD.in
+extras/init.d/glustereventsd-Redhat.in
+extras/init.d/rhel5-load-fuse.modules
+extras/logger.conf.example
+extras/snap_scheduler/README.md
+extras/test/ld-preload-test/README
+extras/who-wrote-glusterfs/*
+extras/distributed-testing/*
+geo-replication/syncdaemon/README.md
+geo-replication/test-requirements.txt
+rpc/xdr/src/.gitignore
+tests/README.md
+xlators/experimental/README.md
+xlators/experimental/dht2/README.md
+xlators/experimental/dht2/TODO.md
+xlators/experimental/posix2/README.md
+xlators/experimental/posix2/TODO.md
+xlators/features/glupy/doc/README.md
+xlators/features/glupy/doc/TESTING
+xlators/features/glupy/doc/test.vol
diff --git a/COMMITMENT b/COMMITMENT
new file mode 100644
index 00000000000..16b75efcf29
--- /dev/null
+++ b/COMMITMENT
@@ -0,0 +1,46 @@
+Common Cure Rights Commitment
+Version 1.0
+
+Before filing or continuing to prosecute any legal proceeding or claim
+(other than a Defensive Action) arising from termination of a Covered
+License, we commit to extend to the person or entity ('you') accused
+of violating the Covered License the following provisions regarding
+cure and reinstatement, taken from GPL version 3. As used here, the
+term 'this License' refers to the specific Covered License being
+enforced.
+
+ However, if you cease all violation of this License, then your
+ license from a particular copyright holder is reinstated (a)
+ provisionally, unless and until the copyright holder explicitly
+ and finally terminates your license, and (b) permanently, if the
+ copyright holder fails to notify you of the violation by some
+ reasonable means prior to 60 days after the cessation.
+
+ Moreover, your license from a particular copyright holder is
+ reinstated permanently if the copyright holder notifies you of the
+ violation by some reasonable means, this is the first time you
+ have received notice of violation of this License (for any work)
+ from that copyright holder, and you cure the violation prior to 30
+ days after your receipt of the notice.
+
+We intend this Commitment to be irrevocable, and binding and
+enforceable against us and assignees of or successors to our
+copyrights.
+
+Definitions
+
+'Covered License' means the GNU General Public License, version 2
+(GPLv2), the GNU Lesser General Public License, version 2.1
+(LGPLv2.1), or the GNU Library General Public License, version 2
+(LGPLv2), all as published by the Free Software Foundation.
+
+'Defensive Action' means a legal proceeding or claim that We bring
+against you in response to a prior proceeding or claim initiated by
+you or your affiliate.
+
+'We' means each contributor to this repository as of the date of
+inclusion of this file, including subsidiaries of a corporate
+contributor.
+
+This work is available under a Creative Commons Attribution-ShareAlike
+4.0 International license (https://creativecommons.org/licenses/by-sa/4.0/).
diff --git a/CONTRIBUTING b/CONTRIBUTING
deleted file mode 100644
index 8b3baa7e5f6..00000000000
--- a/CONTRIBUTING
+++ /dev/null
@@ -1,25 +0,0 @@
- Developer's Certificate of Origin 1.1
-
- By making a contribution to this project, I certify that:
-
- (a) The contribution was created in whole or in part by me and I
- have the right to submit it under the open source license
- indicated in the file; or
-
- (b) The contribution is based upon previous work that, to the best
- of my knowledge, is covered under an appropriate open source
- license and I have the right under that license to submit that
- work with modifications, whether created in whole or in part
- by me, under the same open source license (unless I am
- permitted to submit under a different license), as indicated
- in the file; or
-
- (c) The contribution was provided directly to me by some other
- person who certified (a), (b) or (c) and I have not modified
- it.
-
- (d) I understand and agree that this project and the contribution
- are public and that a record of the contribution (including all
- personal information I submit with it, including my sign-off) is
- maintained indefinitely and may be redistributed consistent with
- this project or the open source license(s) involved. \ No newline at end of file
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 00000000000..65fc3497104
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,114 @@
+# GlusterFS project Contribution guidelines
+
+## Development Workflow
+
+We follow most of the details as per the [document here](https://help.github.com/en/github/collaborating-with-issues-and-pull-requests). If you are not aware of the github workflow, it is recommended to go through them before continuing here.
+
+
+#### Get the Repository setup
+
+0. Fork Repository
+ - Fork [GlusterFS repository](https://github.com/gluster/glusterfs/fork).
+
+1. Clone Repository
+ - Clone the glusterfs repo freshly from github using below steps.
+
+```
+ git clone git@github.com:${username}/glusterfs.git
+ cd glusterfs/
+ git remote add upstream git@github.com:gluster/glusterfs.git
+```
+
+About two tasks are one time for the life time. You can continue to use the same repository for all the work in future.
+
+#### Development & Other flows
+
+0. Issue:
+ - Make sure there is an issue filed for the task you are working on.
+ - If it is not filed, open the issue with all the description.
+ - If it is a bug fix, add label "Type:Bug".
+ - If it is an RFC, provide all the documentation, and request for "DocApproved", and "SpecApproved" label.
+
+1. Code:
+ - Start coding
+ - Build and test locally
+ - Make sure clang-format is installed and is run on the patch.
+
+2. Keep up-to-date
+ - GlusterFS is a large project with many developers, so there would be one or the other patch everyday.
+ - It is critical for developer to be up-to-date with `devel` repo to be Conflict-Free when PR is opened.
+ - Git provides many options to keep up-to-date, below is one of them
+```
+ git fetch upstream
+ git rebase upstream/devel
+```
+ - It is recommended you keep pushing to your repo every day, so you don't loose any work.
+ - It can be done by `./rfc.sh` (or `git push origin HEAD:issueNNN`)
+
+2. Commit Message / PR description:
+ - The name of the branch on your personal fork can start with issueNNNN, followed by anything of your choice.
+ - PRs continue to have the title of format "component: \<title\>", like it is practiced now.
+ - When you open a PR, having a reference Issue for the commit is mandatory in GlusterFS.
+ - Commit message can have, either `Fixes: #NNNN` or `Updates: #NNNN` in a separate line in the commit message.
+ - Here, NNNN is the Issue ID in glusterfs repository.
+ - Each commit needs the author to have the "Signed-off-by: Name \<email\>" line.
+ - Can do this by `-s` option for `git commit`.
+ - If the PR is not ready for review, apply the label `work-in-progress`.
+ - Check the availability of "Draft PR" is present for you, if yes, use that instead.
+
+3. Tests:
+ - All the required smoke tests would be auto-triggered.
+ - Developers get a chance to retrigger the smoke tests using **"/recheck smoke"** as comment.
+ - The "regression" tests would be triggered by a comment **"/run regression"** from developers in the [@gluster-maintainers](https://github.com/orgs/gluster/teams/gluster-maintainers) group.
+ - Ask for help as comment in PR if you have any questions about the process!
+
+4. Review Process:
+ - `+2` : is equivalent to "Approve" from the people in the maintainer's group.
+ - `+1` : can be given by a maintainer/reviewer by explicitly stating that in the comment.
+ - `-1` : provide details on required changes and pick "Request Changes" while submitting your review.
+ - `-2` : done by adding the `DO-NOT-MERGE` label.
+
+ - Any further discussions can happen as comments in the PR.
+
+5. Making changes:
+ - There are 2 approaches to submit changes done after addressing review comments.
+ - Commit changes as a new commit on top of the original commits in the branch, and push the changes to same branch (issueNNNN)
+ - Commit changes into the same commit with `--amend` option, and do a push to the same branch with `--force` option.
+
+6. Merging:
+ - GlusterFS project follows 'Squash and Merge' method
+ - This is mainly to preserve the historic Gerrit method of one patch in `git log` for one URL link.
+ - This also makes every merge a complete patch, which has passed all tests.
+ - The merging of the patch is expected to be done by the maintainers.
+ - It can be done when all the tests (smoke and regression) pass.
+ - When the PR has 'Approved' flag from corresponding maintainer.
+ - If you feel there is delay, feel free to add a comment, discuss the same in Slack channel, or send email.
+
+## By contributing to this project, the contributor would need to agree to below.
+
+### Developer's Certificate of Origin 1.1
+
+By making a contribution to this project, I certify that:
+
+(a) The contribution was created in whole or in part by me and I
+ have the right to submit it under the open source license
+ indicated in the file; or
+
+(b) The contribution is based upon previous work that, to the best
+ of my knowledge, is covered under an appropriate open source
+ license and I have the right under that license to submit that
+ work with modifications, whether created in whole or in part
+ by me, under the same open source license (unless I am
+ permitted to submit under a different license), as indicated
+ in the file; or
+
+(c) The contribution was provided directly to me by some other
+ person who certified (a), (b) or (c) and I have not modified
+ it.
+
+(d) I understand and agree that this project and the contribution
+ are public and that a record of the contribution (including all
+ personal information I submit with it, including my sign-off) is
+ maintained indefinitely and may be redistributed consistent with
+ this project or the open source license(s) involved.
+
diff --git a/INSTALL b/INSTALL
index 88e28999df9..a56390e54fb 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,32 +1,47 @@
Installation Instructions
*************************
-Run ./configure after untaring the package.
+0. If you have cloned from git, run ./autogen.sh.
+
+1. Run ./configure.
bash# ./configure
GlusterFS configure summary
===========================
- FUSE client : yes
- Infiniband verbs : yes
- epoll IO multiplex : yes
- Berkeley-DB : yes
- libglusterfsclient : yes
- mod_glusterfs : yes
- argp-standalone : no
+ GlusterFS configure summary
+ ===========================
+ FUSE client : yes
+ Infiniband verbs : yes
+ epoll IO multiplex : yes
+ argp-standalone : no
+ fusermount : yes
+ readline : yes
+ georeplication : yes
+ Linux-AIO : yes
+ Enable Debug : no
+ Block Device xlator : yes
+ glupy : yes
+ Use syslog : yes
+ XML output : yes
+ QEMU Block formats : yes
+ Encryption xlator : yes
+
The configure summary will tell you what all components will be built with
GlusterFS. Other than 'argp-standalone' if something else says 'no', that
feature in GlusterFS will not be built. 'argp-standalone' package will only
be used if the system doesn't have a proper argp package installed.
-Now just run 'make' and later run 'make install' to install the package.
+2. Now just run 'make' and later run 'make install' to install the package.
bash# make
bash# make install
-Installation complete :-)
+Installation completed :-)
bash# glusterfs --version
Make sure your version is the latest from the release, and the one you
just installed :-)
+
+For more information on GlusterFS installation refer# http://docs.gluster.org/en/latest/Developer-guide/Building-GlusterFS/
diff --git a/MAINTAINERS b/MAINTAINERS
new file mode 100644
index 00000000000..953e8755fd9
--- /dev/null
+++ b/MAINTAINERS
@@ -0,0 +1,510 @@
+GlusterFS Maintainers
+=====================
+
+The intention of this file is not to establish who owns what portions of the
+code base, but to provide a set of names that developers can consult when they
+have a question about a particular subset and also to provide a set of names
+to be CC'd when submitting a patch to obtain appropriate review.
+
+In general, if you have a question about inclusion of a patch, you should
+consult gluster-devel@gluster.org and not any specific individual privately.
+
+Descriptions of section entries:
+
+ M: Main contact that knows and takes care of this area
+ L: Mailing list that is relevant to this area
+ W: Web-page with status/info
+ Q: Patchwork web based patch tracking system site
+ T: SCM tree type and location. Type is one of: git, hg, quilt, stgit.
+ S: Status, one of the following:
+ Supported: Someone is actually paid to look after this.
+ Maintained: Someone actually looks after it.
+ Odd Fixes: It has a maintainer but they don't have time to do
+ much other than throw the odd patch in. See below.
+ Orphan: No current maintainer [but maybe you could take the
+ role as you write your new code].
+ Obsolete: Old code. Something tagged obsolete generally means
+ it has been replaced by a better system and you
+ should be using that.
+ F: Files and directories with wildcard patterns.
+ A trailing slash includes all files and subdirectory files.
+ F: drivers/net/ all files in and below drivers/net
+ F: drivers/net/* all files in drivers/net, but not below
+ F: */net/* all files in "any top level directory"/net
+ One pattern per line. Multiple F: lines acceptable.
+ X: Files and directories that are NOT maintained, same rules as F:
+ Files exclusions are tested before file matches.
+ Can be useful for excluding a specific subdirectory, for instance:
+ F: net/
+ X: net/ipv6/
+ matches all files in and below net excluding net/ipv6/
+ K: Keyword perl extended regex pattern to match content in a
+ patch or file. For instance:
+ K: of_get_profile
+ matches patches or files that contain "of_get_profile"
+ K: \b(printk|pr_(info|err))\b
+ matches patches or files that contain one or more of the words
+ printk, pr_info or pr_err
+ One regex pattern per line. Multiple K: lines acceptable.
+ P: Peer for a component
+
+
+General Project Architects
+--------------------------
+M: Amar Tumballi <amarts@gmail.com>
+M: Xavier Hernandez <xhernandez@redhat.com>
+P: Pranith Karampuri <pranith.karampuri@phonepe.com>
+P: Atin Mukherjee <amukherj@redhat.com>
+
+xlators:
+--------
+Access Control List (ACL)
+M: Raghavendra Talur <rtalur@redhat.com>
+P: Jiffin Tony Thottan <jthottan@redhat.com>
+S: Maintained
+F: xlators/system/posix-acl/
+
+Arbiter
+M: Ravishankar N <ravishankar@redhat.com>
+P: Pranith Karampuri <pranith.karampuri@phonepe.com>
+S: Maintained
+F: xlators/features/arbiter/
+
+Automatic File Replication (AFR)
+M: Pranith Karampuri <pranith.karampuri@phonepe.com>
+M: Ravishankar N <ravishankar@redhat.com>
+P: Karthik US <ksubrahm@redhat.com>
+S: Maintained
+F: xlators/cluster/afr/
+
+Barrier
+M: Raghavendra Bhat <rabhat@redhat.com>
+P: Atin Mukherjee <amukherj@redhat.com>
+S: Maintained
+F: xlators/features/barrier
+
+BitRot
+M: Kotresh HR <khiremat@redhat.com>
+P: Raghavendra Bhat <rabhat@redhat.com>
+S: Maintained
+F: xlators/features/bit-rot/
+
+Changelog
+M: Aravinda V K <avishwan@redhat.com>
+P: Kotresh HR <khiremat@redhat.com>
+S: Maintained
+F: xlators/features/changelog/
+
+Distributed Hashing Table (DHT)
+P: Susant Palai <spalai@redhat.com>
+S: Maintained
+F: xlators/cluster/dht/
+
+Erasure Coding
+M: Pranith Karampuri <pranith.karampuri@phonepe.com>
+M: Xavier Hernandez <xhernandez@redhat.com>
+P: Ashish Pandey <aspandey@redhat.com>
+S: Maintained
+F: xlators/cluster/ec/
+
+Error-gen
+M: Raghavendra Talur <rtalur@redhat.com>
+S: Maintained
+F: xlators/debug/error-gen/
+
+FUSE Bridge
+M: Csaba Henk <chenk@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+S: Maintained
+F: xlators/mount/
+
+Index
+M: Pranith Karampuri <pranith.karampuri@phonepe.com>
+P: Ravishankar N <ravishankar@redhat.com>
+S: Maintained
+F: xlators/features/index/
+
+IO Cache
+P: Mohammed Rafi KC <rafi.kavungal@iternity.com>
+S: Maintained
+F: xlators/performance/io-cache/
+
+IO Statistics
+M: Krutika Dhananjay <kdhananj@redhat.com>
+M: Shyam Ranganathan <srangana@redhat.com>
+S: Maintained
+F: xlators/debug/io-stats/
+
+IO threads
+M: Pranith Karampuri <pranith.karampuri@phonepe.com>
+P: Ravishankar N <ravishankar@redhat.com>
+S: Maintained
+F: xlators/performance/io-threads/
+
+Leases
+M: Poornima G <pgurusid@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+P: Soumya Koduri <skoduri@redhat.com>
+S: Maintained
+F: xlators/features/leases/
+
+Locks
+M: Krutika Dhananjay <kdhananj@redhat.com>
+P: Xavier Hernandez <xhernandez@redhat.com>
+S: Maintained
+F: xlators/features/locks/
+
+Marker
+M: Kotresh HR <khiremat@redhat.com>
+S: Maintained
+F: xlators/features/marker/
+
+Meta
+M: Mohammed Rafi KC <rafi.kavungal@iternity.com>
+S: Maintained
+F: xlators/features/meta/
+
+Metadata-cache
+M: Poornima G <pgurusid@redhat.com>
+P: Soumya Koduri <skoduri@redhat.com>
+S: Maintained
+F: xlators/performance/md-cache/
+
+Negative-lookup Cache
+M: Poornima G <pgurusid@redhat.com>
+P: Pranith Karampuri <pranith.karampuri@phonepe.com>
+S: Maintained
+F: xlators/performance/nl-cache/
+
+gNFS
+M: Jiffin Tony Thottan <jthottan@redhat.com>
+P: Xie Changlong <xiechanglong@cmss.chinamobile.com>
+P: Amar Tumballi <amarts@gmail.com>
+S: Odd Fixes
+F: xlators/nfs/server/
+
+Open-behind
+S: Maintained
+F: xlators/performance/open-behind/
+
+Posix:
+M: Raghavendra Bhat <raghavendra@redhat.com>
+P: Kotresh HR <khiremat@redhat.com>
+P: Krutika Dhananjay <kdhananj@redhat.com>
+S: Maintained
+F: xlators/storage/posix/
+
+Quick-read
+S: Maintained
+F: xlators/performance/quick-read/
+
+Quota
+M: Shyamsundar Ranganathan <srangana@redhat.com>
+P: Hari Gowtham <hgowtham@redhat.com>
+S: Maintained
+F: xlators/features/quota/
+
+Read-ahead
+P: Csaba Henk <chenk@redhat.com>
+S: Maintained
+F: xlators/performance/read-ahead/
+
+Readdir-ahead
+S: Maintained
+F: xlators/performance/readdir-ahead/
+
+Sharding
+M: Krutika Dhananjay <kdhananj@redhat.com>
+P: Xavier Hernandez <xhernandez@redhat.com>
+S: Maintained
+F: xlators/features/shard/
+
+Trash
+M: Anoop C S <anoopcs@redhat.com>
+M: Jiffin Tony Thottan <jthottan@redhat.com>
+S: Maintained
+F: xlators/features/trash/
+
+Upcall
+M: Poornima G <pgurusid@redhat.com>
+M: Soumya Koduri <skoduri@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+S: Maintained
+F: xlators/features/upcall/
+
+Write-behind
+P: Csaba Henk <chenk@redhat.com>
+S: Maintained
+F: xlators/performance/write-behind/
+
+Write Once Read Many
+P: Karthik US <ksubrahm@redhat.com>
+S: Maintained
+F: xlators/features/read-only/
+
+Cloudsync
+M: Susant Kumar Palai <spalai@redhat.com>
+S: Maintained
+F: xlators/features/cloudsync/
+
+Other bits of code:
+-------------------
+
+Doc
+M: Humble Chirammal <hchiramm@redhat.com>
+M: Raghavendra Talur <rtalur@redhat.com>
+S: Maintained
+F: doc/
+
+Geo Replication
+M: Aravinda V K <avishwan@redhat.com>
+M: Kotresh HR <khiremat@redhat.com>
+M: Sunny Kumar <sunkumar@redhat.com>
+S: Maintained
+F: geo-replication/
+
+Glusterfind
+M: Aravinda VK <avishwan@redhat.com>
+S: Maintained
+F: tools/glusterfind/
+
+libgfapi
+M: Niels de Vos <ndevos@redhat.com>
+P: Poornima G <pgurusid@redhat.com>
+P: Shyamsundar Ranganathan <srangana@redhat.com>
+P: Soumya Koduri <skoduri@redhat.com>
+S: Maintained
+F: api/
+
+libglusterfs
+M: Amar Tumballi <amarts@gmail.com>
+M: Xavier Hernandez <xhernandez@redhat.com>
+M: Jeff Darcy <jeff@pl.atyp.us>
+P: Kaleb Keithley <kkeithle@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+P: Pranith Karampuri <pranith.karampuri@phonepe.com>
+P: Shyamsundar Ranganathan <srangana@redhat.com>
+S: Maintained
+F: libglusterfs/
+
+xxhash
+M: Aravinda VK <avishwan@redhat.com>
+M: Kotresh HR <khiremat@redhat.com>
+P: Yaniv Kaul <ykaul@redhat.com>
+S: Maintained
+F: contrib/xxhash/
+T: https://github.com/Cyan4973/xxHash.git
+
+Management Daemon - glusterd
+M: Atin Mukherjee <amukherj@redhat.com>
+M: Mohit Agrawal <moagrawa@redhat.com>
+M: Sanju Rakonde <srakonde@redhat.com>
+S: Maintained
+F: cli/
+F: xlators/mgmt/glusterd/
+
+Protocol
+M: Niels de Vos <ndevos@redhat.com>
+P: Mohammed Rafi KC <rafi.kavungal@iternity.com>
+S: Maintained
+F: xlators/protocol/
+
+Remote Procedure Call subsystem
+P: Mohit Agrawal <moagrawa@redhat.com>
+S: Maintained
+F: rpc/rpc-lib/
+F: rpc/xdr/
+
+Snapshot
+M: Raghavendra Bhat <raghavendra@redhat.com>
+P: Mohammed Rafi KC <rafi.kavungal@iternity.com>
+P: Sunny Kumar <sunkumar@redhat.com>
+S: Maintained
+F: xlators/mgmt/glusterd/src/glusterd-snap*
+F: extras/snap-scheduler.py
+
+Socket subsystem
+P: Krutika Dhananjay <kdhananj@redhat.com>
+P: Milind Changire <mchangir@redhat.com>
+P: Mohammed Rafi KC <rafi.kavungal@iternity.com>
+P: Mohit Agrawal <moagrawa@redhat.com>
+S: Maintained
+F: rpc/rpc-transport/socket/
+
+Testing - .t framework
+M: Raghavendra Talur <rtalur@redhat.com>
+S: Maintained
+F: tests/
+
+Utilities
+M: Aravinda VK <avishwan@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+P: Raghavendra Talur <rtalur@redhat.com>
+P: Sachidanda Urs <surs@redhat.com>
+S: Maintained
+F: extras/
+
+Events APIs
+M: Aravinda VK <avishwan@redhat.com>
+S: Maintained
+F: events/
+F: libglusterfs/src/events*
+F: libglusterfs/src/eventtypes*
+F: extras/systemd/glustereventsd*
+
+Distribution Specific:
+----------------------
+Build:
+M: Niels de Vos <ndevos@redhat.com>
+M: Hari Gowtham <hgowtham@redhat.com>
+P: Anoop C S <anoopcs@redhat.com>
+P: Raghavendra Talur <rtalur@redhat.com>
+P: Rinku Kothiya <rkothiya@redhat.com>
+S: Maintained
+
+Debian packages on download.gluster.org
+M: packaging@gluster.org
+M: Kaleb Keithley <kkeithle@redhat.com>
+P: Sheetal Pamecha <spamecha@redhat.com>
+P: Shwetha Acharya <sacharya@redhat.com>
+S: Maintained
+W: http://download.gluster.org/pub/gluster/glusterfs/LATEST/Debian/Debian.README
+T: https://github.com/gluster/glusterfs-debian.git
+
+OpenSuSE
+M: packaging@gluster.org
+M: Kaleb Keithley <kkeithle@redhat.com>
+P: Sheetal Pamecha <spamecha@redhat.com>
+P: Shwetha Acharya <sacharya@redhat.com>
+S: Maintained
+W: https://build.opensuse.org/repositories/home:glusterfs
+W: https://download.gluster.org/pub/gluster/glusterfs/LATEST/SuSE/SuSE.README
+T: https://github.com/gluster/glusterfs-suse.git
+
+Packages for the CentOS Storage SIG
+M: centos-devel@centos.org
+M: Niels de Vos <ndevos@redhat.com>
+P: Kaleb Keithley <kkeithle@redhat.com>
+S: Maintained
+W: https://wiki.centos.org/SpecialInterestGroup/Storage/Gluster
+T: https://github.com/CentOS-Storage-SIG/glusterfs.git
+
+Ubuntu PPA
+M: packaging@gluster.org
+M: Kaleb Keithley <kkeithle@redhat.com>
+P: Sheetal Pamecha <spamecha@redhat.com>
+P: Shwetha Acharya <sacharya@redhat.com>
+S: Maintained
+W: https://launchpad.net/~gluster
+W: http://download.gluster.org/pub/gluster/glusterfs/LATEST/Ubuntu/Ubuntu.README
+T: https://github.com/gluster/glusterfs-debian.git
+
+Related projects
+----------------
+Gluster Block
+M: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
+M: Xiubo Li <xiubli@redhat.com>
+S: Maintained
+T: https://github.com/gluster/gluster-block.git
+
+GlusterFS core-utils
+M: Anoop C S <anoopcs@redhat.com>
+S: Maintained
+T: https://github.com/gluster/glusterfs-coreutils.git
+
+NFS-Ganesha FSAL plugin
+M: Jiffin Tony Thottan <jthottan@redhat.com>
+M: Kaleb Keithley <kkeithle@redhat.com>
+M: Soumya Koduri <skoduri@redhat.com>
+S: Maintained
+T: git://github.com/nfs-ganesha/nfs-ganesha.git
+F: src/nfs-ganesha~/src/FSAL/FSAL_GLUSTER/
+
+QEMU integration
+M: Niels de Vos <ndevos@redhat.com>
+M: Prasanna Kumar Kalever <prasanna.kalever@redhat.com>
+S: Maintained
+T: git://git.qemu.org/qemu.git
+F: block/gluster.c
+
+Samba VFS plugin
+M: Anoop C S <anoopcs@redhat.com>
+M: Raghavendra Talur <rtalur@redhat.com>
+M: Michael Adam <madam@redhat.com>
+M: Poornima G <pgurusid@redhat.com>
+S: Maintained
+T: git://git.samba.org/samba.git
+F: source3/modules/vfs_glusterfs.c
+
+Storhaug
+M: Jose A. Rivera <jarrpa@redhat.com>
+P: Kaleb Keithley <kkeithle@redhat.com>
+S: Maintained
+T: https://github.com/linux-ha-storage/storhaug.git
+
+Testing - Glusto-Tests
+M: Jonathan Holloway <jholloway@redhat.com>
+M: Vijay Bhaskar Reddy Avuthu <vavuthu@redhat.com>
+M: Akarsha Rai <akrai@redhat.com>
+S: Maintained
+T: https://github.com/gluster/glusto-tests.git
+
+Wireshark dissectors
+M: Niels de Vos <ndevos@redhat.com>
+S: Maintained
+W: https://forge.gluster.org/wireshark
+T: http://code.wireshark.org/git/wireshark
+F: epan/dissectors/packet-gluster*
+
+Infrastructure
+--------------
+
+Platform
+M: Michael Scherer <misc@redhat.com>
+P: Shyamsundar Ranganathan <srangana@redhat.com>
+P: Amar Tumballi <amarts@gmail.com>
+
+Continuous Integration
+M: Michael Scherer <misc@redhat.com>
+M: Deepshikha Khandelwal <dkhandel@redhat.com>
+P: Niels de Vos <ndevos@redhat.com>
+
+Special Thanks
+--------------
+
+GlusterFS would not be possible without the contributions of:
+
+
+M: Vijay Bellur <vbellur@redhat.com>
+M: Jeff Darcy <jeff@pl.atyp.us>
+M: Shreyas Siravara <sshreyas@fb.com>
+M: Kaushal M <kaushal@redhat.com>
+M: Nigel Babu
+M: Prashanth Pai
+P: Sanoj Unnikrishnan
+P: Milind Changire <mchangir@redhat.com>
+P: Sunil Kumar Acharya <sheggodu@redhat.com>
+M: Samikshan Bairagya <samikshan@gmail.com>
+M: Chris Hertel
+M: M. Mohan Kumar <mohan@in.ibm.com>
+M: Shishir Gowda <gowda.shishir@gmail.com>
+M: Brian Foster <bfoster@redhat.com>
+M: Anand Avati <avati@cs.stanford.edu>
+M: Dennis Schafroth <dennis@schafroth.com>
+M: Harshavardhana <harsha@harshavardhana.net>
+M: Krishnan Parthasarathi
+M: Justin Clift <justin@gluster.org>
+M: Venky Shankar <vshankar@redhat.com>
+M: Shravan Chandrashekar <shravantc99@gmail.com>
+M: Joseph Fernandes
+M: Vijaikumar Mallikarjuna
+M: Anand Subramanian
+M: Bharata B Rao <bharata@linux.vnet.ibm.com>
+M: Rajesh Joseph
+M: Dan Lambright
+M: Jay Vyas
+M: Luis Pabon
+M: Ira Cooper
+M: Shwetha Panduranga
+M: Nithya Balachandran
+M: Raghavendra Gowdappa
diff --git a/Makefile.am b/Makefile.am
index 6693bb8767a..98ea5c1038d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,14 +1,55 @@
-EXTRA_DIST = autogen.sh COPYING-GPLV2 COPYING-LGPLV3 INSTALL README AUTHORS THANKS NEWS glusterfs.spec
+SOURCES = site.h
-SUBDIRS = argp-standalone libglusterfs rpc xlators glusterfsd $(FUSERMOUNT_SUBDIR) doc extras cli
+EXTRA_DIST = autogen.sh \
+ COPYING-GPLV2 COPYING-LGPLV3 COMMITMENT \
+ INSTALL README.md AUTHORS THANKS NEWS \
+ glusterfs.spec glusterfs-api.pc.in libgfchangelog.pc.in \
+ run-tests.sh \
+ build-aux/pkg-version \
+ contrib/umountd \
+ $(shell find $(top_srcdir)/tests -type f -print)
-CLEANFILES =
+
+SUBDIRS = $(ARGP_STANDALONE_DIR) libglusterfs rpc libglusterd api \
+ glusterfsd xlators $(FUSERMOUNT_SUBDIR) doc extras cli heal \
+ @SYNCDAEMON_SUBDIR@ @UMOUNTD_SUBDIR@ tools events
+
+pkgconfigdir = @pkgconfigdir@
+pkgconfig_DATA = glusterfs-api.pc libgfchangelog.pc
+
+CLEANFILES = glusterfs-api.pc libgfchangelog.pc contrib/umountd/Makefile
+
+clean-local:
+ find . -name '*.o' -o -name '*.lo' -o -name '.Po' | xargs rm -f
gitclean: distclean
find . -name Makefile.in -exec rm -f {} \;
- find . -name Makefile -exec rm -f {} \;
find . -name mount.glusterfs -exec rm -f {} \;
+ find . -name .deps -o -name .libs | xargs rm -rf
rm -fr autom4te.cache
rm -f missing aclocal.m4 config.h.in config.guess config.sub ltmain.sh install-sh configure depcomp
- rm -fr argp-standalone/autom4te.cache
- rm -f argp-standalone/aclocal.m4 argp-standalone/config.h.in argp-standalone/configure argp-standalone/depcomp argp-standalone/install-sh argp-standalone/missing
+
+# dist-hook gets executed with 'make dist', this is the only target getting
+# executed, a dist-hook in other Makefile.am files seem to get ignored.
+dist-hook: gen-VERSION gen-ChangeLog
+ -rm -fr $(distdir)/contrib/umountd/.deps
+ -rm -f $(distdir)/events/src/eventtypes.py
+ -rm -f $(distdir)/tests/env.rc
+ -cp -f $(top_srcdir)/build-aux/config.sub.dist $(distdir)/config.sub
+ -cp -f $(top_srcdir)/build-aux/config.guess.dist $(distdir)/config.guess
+
+.PHONY: gen-VERSION gen-ChangeLog clang-check
+
+clang-check:
+ @$(top_srcdir)/extras/clang-checker.sh
+
+gen-ChangeLog:
+ (cd $(srcdir) && git diff && echo ===== git log ==== && git log) > $(distdir)/ChangeLog
+
+.PHONY : gen-VERSION
+gen-VERSION:
+ if test -d $(top_srcdir)/.git; then \
+ cd $(top_srcdir); \
+ ./build-aux/pkg-version --full \
+ > $(abs_top_builddir)/$(distdir)/VERSION; \
+ fi
diff --git a/README b/README
deleted file mode 100644
index ce648743ee9..00000000000
--- a/README
+++ /dev/null
@@ -1 +0,0 @@
-For more info, please visit http://www.gluster.org/.
diff --git a/README.md b/README.md
new file mode 100644
index 00000000000..9d68e033782
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+# Gluster
+ Gluster is a software defined distributed storage that can scale to several
+ petabytes. It provides interfaces for object, block and file storage.
+
+## Development
+ The development workflow is documented in [Contributors guide](CONTRIBUTING.md)
+
+## Documentation
+ The Gluster documentation can be found at [Gluster Docs](http://docs.gluster.org).
+
+## Deployment
+ Quick instructions to build and install can be found in [INSTALL](INSTALL) file.
+
+## Testing
+
+ GlusterFS source contains some functional tests under `tests/` directory. All
+ these tests are run against every patch submitted for review. If you want your
+ patch to be tested, please add a `.t` test file as part of your patch submission.
+ You can also submit a patch to only add a `.t` file for the test case you are
+ aware of.
+
+ To run these tests, on your test-machine, just run `./run-tests.sh`. Don't run
+ this on a machine where you have 'production' glusterfs is running, as it would
+ blindly kill all gluster processes in each runs.
+
+ If you are sending a patch, and want to validate one or few specific tests, then
+ run a single test by running the below command.
+
+```
+ bash# /bin/bash ${path_to_gluster}/tests/basic/rpc-coverage.t
+```
+
+ You can also use `prove` tool if available in your machine, as follows.
+
+```
+ bash# prove -vmfe '/bin/bash' ${path_to_gluster}/tests/basic/rpc-coverage.t
+```
+
+
+## Maintainers
+ The list of Gluster maintainers is available in [MAINTAINERS](MAINTAINERS) file.
+
+## License
+ Gluster is dual licensed under [GPLV2](COPYING-GPLV2) and [LGPLV3+](COPYING-LGPLV3).
+
+ Please visit the [Gluster Home Page](http://www.gluster.org/) to find out more about Gluster.
diff --git a/THANKS b/THANKS
index e1ce5105d79..d056d00bb72 100644
--- a/THANKS
+++ b/THANKS
@@ -1 +1 @@
-For all of you, who use the product and help us making it more robust, useful, popular..
+For all of you, who use the product and help us make it more robust, useful, and popular.
diff --git a/api/Makefile.am b/api/Makefile.am
new file mode 100644
index 00000000000..f0ad1ee971c
--- /dev/null
+++ b/api/Makefile.am
@@ -0,0 +1 @@
+SUBDIRS = src examples
diff --git a/api/examples/Makefile.am b/api/examples/Makefile.am
new file mode 100644
index 00000000000..7112c81d6a7
--- /dev/null
+++ b/api/examples/Makefile.am
@@ -0,0 +1,6 @@
+# The bits needed for glfsxmp
+EXTRA_PROGRAMS = glfsxmp
+glfsxmp_SOURCES = glfsxmp.c
+glfsxmp_CFLAGS = $(GLFS_CFLAGS) -Wall
+glfsxmp_LDADD = $(GLFS_LIBS) -lrt
+
diff --git a/api/examples/README b/api/examples/README
new file mode 100644
index 00000000000..4d2b521f779
--- /dev/null
+++ b/api/examples/README
@@ -0,0 +1,36 @@
+This is an example application which uses libgfapi. It is
+a complete autotools based build system which demonstrates the
+required changes in configure.ac, Makefile.am etc to successfuly
+detect for and build an application against libgfapi.
+
+There are two approaches to building a libgfapi based application:
+
+1. In the presence of pkg-config in your build system.
+This is the recommended approach which is also used in this example.
+For this approach to work, you need to build glusterfs by passing
+--pkgconfigdir=/usr/lib64/pkgconfig (or the appropriate directory)
+in your distro. This already happens if you build RPMs with the
+glusterfs.spec provided in glusterfs.git. You will also need to
+install glusterfs-api RPM.
+
+2. In the absence of pkg-config in your build system.
+Make sure your LDFLAGS includes -L/path/to/lib where libgfapi.so is
+installed and -I/path/to/include/glusterfs where the 'api' directory
+containing the headers are available.
+
+glfsxmp.c
+=========
+
+glfsxmp.c is an example application which uses libgfapi
+
+Compilation Steps For glfsxmp.c
+===============================
+
+1. $./autogen.sh
+2. $./configure
+
+Note: Before running ./configure , as mentioned above, you need to
+ take care of #1 or #2 i.e. pkg-config path or LDFLAGS and
+ -I/<path> with correct values.
+
+3. $make glfsxmp
diff --git a/api/examples/autogen.sh b/api/examples/autogen.sh
new file mode 100755
index 00000000000..1fee6be11bb
--- /dev/null
+++ b/api/examples/autogen.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+aclocal
+autoconf
+automake --foreign
diff --git a/api/examples/configure.ac b/api/examples/configure.ac
new file mode 100644
index 00000000000..b80177a4e87
--- /dev/null
+++ b/api/examples/configure.ac
@@ -0,0 +1,12 @@
+
+AC_INIT([glfs-test],[0.1],[gluster-devel@nongu.org])
+
+AM_INIT_AUTOMAKE
+
+AC_CONFIG_FILES([Makefile])
+
+AC_PROG_CC
+
+PKG_CHECK_MODULES([GLFS], [glusterfs-api >= 3])
+
+AC_OUTPUT
diff --git a/api/examples/getvolfile.py b/api/examples/getvolfile.py
new file mode 100755
index 00000000000..3b2c8ab5a15
--- /dev/null
+++ b/api/examples/getvolfile.py
@@ -0,0 +1,45 @@
+#!/usr/bin/python3
+
+from __future__ import print_function
+import ctypes
+import ctypes.util
+
+api = ctypes.CDLL("libgfapi.so")
+api.glfs_get_volfile.argtypes = [ctypes.c_void_p,
+ ctypes.c_void_p,
+ ctypes.c_ulong]
+api.glfs_get_volfile.restype = ctypes.c_long
+
+
+def get_volfile(host, volume):
+ # This is set to a large value to exercise the "buffer not big enough"
+ # path. More realistically, you'd just start with a huge buffer.
+ BUF_LEN = 0
+ fs = api.glfs_new(volume)
+ # api.glfs_set_logging(fs,"/dev/stderr",7)
+ api.glfs_set_volfile_server(fs, "tcp", host, 24007)
+ api.glfs_init(fs)
+ vbuf = ctypes.create_string_buffer(BUF_LEN)
+ vlen = api.glfs_get_volfile(fs, vbuf, BUF_LEN)
+ if vlen < 0:
+ vlen = BUF_LEN - vlen
+ vbuf = ctypes.create_string_buffer(vlen)
+ vlen = api.glfs_get_volfile(fs, vbuf, vlen)
+ api.glfs_fini(fs)
+ if vlen <= 0:
+ return vlen
+ return vbuf.value[:vlen]
+
+if __name__ == "__main__":
+ import sys
+
+ try:
+ res = get_volfile(*sys.argv[1:3])
+ except:
+ print("fetching volfile failed (volume not started?)")
+
+ try:
+ for line in res.split('\n'):
+ print(line)
+ except:
+ print("bad return value %s" % res)
diff --git a/api/examples/glfsxmp.c b/api/examples/glfsxmp.c
new file mode 100644
index 00000000000..a55616ef739
--- /dev/null
+++ b/api/examples/glfsxmp.c
@@ -0,0 +1,1811 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <glusterfs/api/glfs.h>
+#include <glusterfs/api/glfs-handles.h>
+#include <string.h>
+#include <time.h>
+
+#define TEST_STR_LEN 2048
+
+int
+test_dirops(glfs_t *fs)
+{
+ glfs_fd_t *fd = NULL;
+ char buf[512];
+ struct dirent *entry = NULL;
+
+ fd = glfs_opendir(fs, "/");
+ if (!fd) {
+ fprintf(stderr, "/: %s\n", strerror(errno));
+ return -1;
+ }
+
+ fprintf(stderr, "Entries:\n");
+ while (glfs_readdir_r(fd, (struct dirent *)buf, &entry), entry) {
+ fprintf(stderr, "%s: %lu\n", entry->d_name, glfs_telldir(fd));
+ }
+
+ glfs_closedir(fd);
+ return 0;
+}
+
+int
+test_xattr(glfs_t *fs)
+{
+ char *filename = "/filename2";
+ char *linkfile = "/linkfile";
+ glfs_fd_t *fd = NULL;
+ char buf[512];
+ char *ptr;
+ int ret;
+
+ ret = glfs_setxattr(fs, filename, "user.testkey", "testval", 8, 0);
+ fprintf(stderr, "setxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+
+ ret = glfs_setxattr(fs, filename, "user.testkey2", "testval", 8, 0);
+ fprintf(stderr, "setxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+
+ ret = glfs_getxattr(fs, filename, "user.testkey", buf, 512);
+ fprintf(stderr, "getxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_listxattr(fs, filename, buf, 512);
+ fprintf(stderr, "listxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_symlink(fs, "filename", linkfile);
+ fprintf(stderr, "symlink(%s %s): %s\n", filename, linkfile,
+ strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_readlink(fs, linkfile, buf, 512);
+ fprintf(stderr, "readlink(%s) : %d (%s)\n", filename, ret, strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_lsetxattr(fs, filename, "user.testkey3", "testval", 8, 0);
+ fprintf(stderr, "lsetxattr(%s) : %d (%s)\n", linkfile, ret,
+ strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_llistxattr(fs, linkfile, buf, 512);
+ fprintf(stderr, "llistxattr(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ ret = glfs_lgetxattr(fs, filename, "user.testkey3", buf, 512);
+ fprintf(stderr, "lgetxattr(%s): %d (%s)\n", linkfile, ret, strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ for (ptr = buf; ptr < buf + ret; ptr++) {
+ printf("key=%s\n", ptr);
+ ptr += strlen(ptr);
+ }
+
+ ret = glfs_removexattr(fs, filename, "user.testkey2");
+ fprintf(stderr, "removexattr(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+
+ fd = glfs_open(fs, filename, O_RDWR);
+ fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno));
+
+ ret = glfs_fsetxattr(fd, "user.testkey2", "testval", 8, 0);
+ fprintf(stderr, "fsetxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+
+ ret = glfs_fgetxattr(fd, "user.testkey2", buf, 512);
+ fprintf(stderr, "fgetxattr(%s): %d (%s)\n", filename, ret, strerror(errno));
+
+ ret = glfs_flistxattr(fd, buf, 512);
+ fprintf(stderr, "flistxattr(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+ if (ret < 0)
+ return -1;
+
+ for (ptr = buf; ptr < buf + ret; ptr++) {
+ printf("key=%s\n", ptr);
+ ptr += strlen(ptr);
+ }
+
+ ret = glfs_fremovexattr(fd, "user.testkey2");
+ fprintf(stderr, "fremovexattr(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+
+ glfs_close(fd);
+
+ return 0;
+}
+
+int
+test_chdir(glfs_t *fs)
+{
+ int ret = -1;
+ char *dir = "/dir";
+ char *topdir = "/topdir";
+ char *linkdir = "/linkdir";
+ char *linkdir2 = "/linkdir2";
+ char *subdir = "./subdir";
+ char *respath = NULL;
+ char pathbuf[4096];
+
+ ret = glfs_mkdir(fs, topdir, 0755);
+ fprintf(stderr, "mkdir(%s): %s\n", topdir, strerror(errno));
+ if (ret)
+ return -1;
+
+ ret = glfs_mkdir(fs, dir, 0755);
+ fprintf(stderr, "mkdir(%s): %s\n", dir, strerror(errno));
+ if (ret)
+ return -1;
+
+ respath = glfs_getcwd(fs, pathbuf, 4096);
+ fprintf(stdout, "getcwd() = %s\n", respath);
+
+ ret = glfs_symlink(fs, "topdir", linkdir);
+ if (ret) {
+ fprintf(stderr, "symlink(%s, %s): %s\n", topdir, linkdir,
+ strerror(errno));
+ return -1;
+ }
+
+ ret = glfs_chdir(fs, linkdir);
+ if (ret) {
+ fprintf(stderr, "chdir(%s): %s\n", linkdir, strerror(errno));
+ return -1;
+ }
+
+ respath = glfs_getcwd(fs, pathbuf, 4096);
+ fprintf(stdout, "getcwd() = %s\n", respath);
+
+ respath = glfs_realpath(fs, subdir, pathbuf);
+ if (respath) {
+ fprintf(stderr, "realpath(%s) worked unexpectedly: %s\n", subdir,
+ respath);
+ return -1;
+ }
+
+ ret = glfs_mkdir(fs, subdir, 0755);
+ if (ret) {
+ fprintf(stderr, "mkdir(%s): %s\n", subdir, strerror(errno));
+ return -1;
+ }
+
+ respath = glfs_realpath(fs, subdir, pathbuf);
+ if (!respath) {
+ fprintf(stderr, "realpath(%s): %s\n", subdir, strerror(errno));
+ } else {
+ fprintf(stdout, "realpath(%s) = %s\n", subdir, respath);
+ }
+
+ ret = glfs_chdir(fs, subdir);
+ if (ret) {
+ fprintf(stderr, "chdir(%s): %s\n", subdir, strerror(errno));
+ return -1;
+ }
+
+ respath = glfs_getcwd(fs, pathbuf, 4096);
+ fprintf(stdout, "getcwd() = %s\n", respath);
+
+ respath = glfs_realpath(fs, "/linkdir/subdir", pathbuf);
+ if (!respath) {
+ fprintf(stderr, "realpath(/linkdir/subdir): %s\n", strerror(errno));
+ } else {
+ fprintf(stdout, "realpath(/linkdir/subdir) = %s\n", respath);
+ }
+
+ return 0;
+}
+
+#ifdef DEBUG
+static void
+peek_stat(struct stat *sb)
+{
+ printf("Dumping stat information:\n");
+ printf("File type: ");
+
+ switch (sb->st_mode & S_IFMT) {
+ case S_IFBLK:
+ printf("block device\n");
+ break;
+ case S_IFCHR:
+ printf("character device\n");
+ break;
+ case S_IFDIR:
+ printf("directory\n");
+ break;
+ case S_IFIFO:
+ printf("FIFO/pipe\n");
+ break;
+ case S_IFLNK:
+ printf("symlink\n");
+ break;
+ case S_IFREG:
+ printf("regular file\n");
+ break;
+ case S_IFSOCK:
+ printf("socket\n");
+ break;
+ default:
+ printf("unknown?\n");
+ break;
+ }
+
+ printf("I-node number: %ld\n", (long)sb->st_ino);
+
+ printf("Mode: %lo (octal)\n",
+ (unsigned long)sb->st_mode);
+
+ printf("Link count: %ld\n", (long)sb->st_nlink);
+ printf("Ownership: UID=%ld GID=%ld\n", (long)sb->st_uid,
+ (long)sb->st_gid);
+
+ printf("Preferred I/O block size: %ld bytes\n", (long)sb->st_blksize);
+ printf("File size: %lld bytes\n", (long long)sb->st_size);
+ printf("Blocks allocated: %lld\n", (long long)sb->st_blocks);
+
+ printf("Last status change: %s", ctime(&sb->st_ctime));
+ printf("Last file access: %s", ctime(&sb->st_atime));
+ printf("Last file modification: %s", ctime(&sb->st_mtime));
+
+ return;
+}
+
+static void
+peek_handle(unsigned char *glid)
+{
+ int i;
+
+ for (i = 0; i < GFAPI_HANDLE_LENGTH; i++) {
+ printf(":%02x:", glid[i]);
+ }
+ printf("\n");
+}
+#else /* DEBUG */
+static void
+peek_stat(struct stat *sb)
+{
+ return;
+}
+
+static void
+peek_handle(unsigned char *id)
+{
+ return;
+}
+#endif /* DEBUG */
+
+glfs_t *fs = NULL;
+char *full_parent_name = "/testdir", *parent_name = "testdir";
+
+void
+test_h_unlink(void)
+{
+ char *my_dir = "unlinkdir";
+ char *my_file = "file.txt";
+ char *my_subdir = "dir1";
+ struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL,
+ *subdir = NULL, *subleaf = NULL;
+ struct stat sb;
+ int ret;
+
+ printf("glfs_h_unlink tests: In Progress\n");
+
+ /* Prepare tests */
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb);
+ if (dir == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, parent, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ leaf = glfs_h_creat(fs, dir, my_file, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ subdir = glfs_h_mkdir(fs, dir, my_subdir, 0755, &sb);
+ if (subdir == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_subdir, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ subleaf = glfs_h_creat(fs, subdir, my_file, O_CREAT, 0644, &sb);
+ if (subleaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, subdir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink non empty directory */
+ ret = glfs_h_unlink(fs, dir, my_subdir);
+ if ((ret && errno != ENOTEMPTY) || (ret == 0)) {
+ fprintf(stderr,
+ "glfs_h_unlink: error unlinking %s: it is non empty: %s\n",
+ my_subdir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink regular file */
+ ret = glfs_h_unlink(fs, subdir, my_file);
+ if (ret) {
+ fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n",
+ my_file, subdir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink directory */
+ ret = glfs_h_unlink(fs, dir, my_subdir);
+ if (ret) {
+ fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n",
+ my_subdir, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink regular file */
+ ret = glfs_h_unlink(fs, dir, my_file);
+ if (ret) {
+ fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n",
+ my_file, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink non-existent regular file */
+ ret = glfs_h_unlink(fs, dir, my_file);
+ if ((ret && errno != ENOENT) || (ret == 0)) {
+ fprintf(stderr,
+ "glfs_h_unlink: error unlinking non-existent %s: invalid errno "
+ ",%d, %s\n",
+ my_file, ret, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink non-existent directory */
+ ret = glfs_h_unlink(fs, dir, my_subdir);
+ if ((ret && errno != ENOENT) || (ret == 0)) {
+ fprintf(stderr,
+ "glfs_h_unlink: error unlinking non-existent %s: invalid "
+ "errno ,%d, %s\n",
+ my_subdir, ret, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ /* unlink directory */
+ ret = glfs_h_unlink(fs, parent, my_dir);
+ if (ret) {
+ fprintf(stderr, "glfs_h_unlink: error unlinking %s: from (%p),%s\n",
+ my_dir, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+
+ printf("glfs_h_unlink tests: PASSED\n");
+
+out:
+ if (dir)
+ glfs_h_close(dir);
+ if (leaf)
+ glfs_h_close(leaf);
+ if (subdir)
+ glfs_h_close(subdir);
+ if (subleaf)
+ glfs_h_close(subleaf);
+ if (parent)
+ glfs_h_close(parent);
+
+ return;
+}
+
+void
+test_h_getsetattrs(void)
+{
+ char *my_dir = "attrdir";
+ char *my_file = "attrfile.txt";
+ struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL;
+ struct stat sb, retsb;
+ int ret, valid;
+ struct timespec timestamp;
+
+ printf("glfs_h_getattrs and setattrs tests: In Progress\n");
+
+ /* Prepare tests */
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb);
+ if (dir == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, parent, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_creat(fs, dir, my_file, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, dir, strerror(errno));
+ printf("glfs_h_unlink tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ ret = glfs_h_getattrs(fs, dir, &retsb);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_getattrs: error %s: from (%p),%s\n", my_dir,
+ dir, strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&retsb);
+ /* TODO: Compare stat information */
+
+ retsb.st_mode = 00666;
+ retsb.st_uid = 1000;
+ retsb.st_gid = 1001;
+ ret = clock_gettime(CLOCK_REALTIME, &timestamp);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+ retsb.st_atim = timestamp;
+ retsb.st_mtim = timestamp;
+ valid = GFAPI_SET_ATTR_MODE | GFAPI_SET_ATTR_UID | GFAPI_SET_ATTR_GID |
+ GFAPI_SET_ATTR_ATIME | GFAPI_SET_ATTR_MTIME;
+ peek_stat(&retsb);
+
+ ret = glfs_h_setattrs(fs, dir, &retsb, valid);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_setattrs: error %s: from (%p),%s\n", my_dir,
+ dir, strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ memset(&retsb, 0, sizeof(struct stat));
+ ret = glfs_h_stat(fs, dir, &retsb);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_stat: error %s: from (%p),%s\n", my_dir, dir,
+ strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&retsb);
+
+ printf("glfs_h_getattrs and setattrs tests: PASSED\n");
+out:
+ if (parent)
+ glfs_h_close(parent);
+ if (leaf)
+ glfs_h_close(leaf);
+ if (dir)
+ glfs_h_close(dir);
+
+ return;
+}
+
+void
+test_h_truncate(void)
+{
+ char *my_dir = "truncatedir";
+ char *my_file = "file.txt";
+ struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL;
+ struct stat sb;
+ glfs_fd_t *fd = NULL;
+ char buf[32];
+ off_t offset = 0;
+ int ret = 0;
+
+ printf("glfs_h_truncate tests: In Progress\n");
+
+ /* Prepare tests */
+ root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (root == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb);
+ if (parent == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, root, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ fd = glfs_h_open(fs, leaf, O_RDWR);
+ if (fd == NULL) {
+ fprintf(stderr, "glfs_h_open: error on open of %s: %s\n", my_file,
+ strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+
+ memcpy(buf, "abcdefghijklmnopqrstuvwxyz012345", 32);
+ ret = glfs_write(fd, buf, 32, 0);
+
+ /* run tests */
+ /* truncate lower */
+ offset = 30;
+ ret = glfs_h_truncate(fs, leaf, offset);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ ret = glfs_h_getattrs(fs, leaf, &sb);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file,
+ leaf, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ if (sb.st_size != offset) {
+ fprintf(stderr, "glfs_h_truncate: post size mismatch\n");
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+
+ /* truncate higher */
+ offset = 32;
+ ret = glfs_h_truncate(fs, leaf, offset);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ ret = glfs_h_getattrs(fs, leaf, &sb);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file,
+ leaf, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ if (sb.st_size != offset) {
+ fprintf(stderr, "glfs_h_truncate: post size mismatch\n");
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+
+ /* truncate equal */
+ offset = 30;
+ ret = glfs_h_truncate(fs, leaf, offset);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_truncate: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ ret = glfs_h_getattrs(fs, leaf, &sb);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_getattrs: error for %s (%p),%s\n", my_file,
+ leaf, strerror(errno));
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+ if (sb.st_size != offset) {
+ fprintf(stderr, "glfs_h_truncate: post size mismatch\n");
+ printf("glfs_h_truncate tests: FAILED\n");
+ goto out;
+ }
+
+ printf("glfs_h_truncate tests: PASSED\n");
+out:
+ if (fd)
+ glfs_close(fd);
+ if (root)
+ glfs_h_close(root);
+ if (parent)
+ glfs_h_close(parent);
+ if (leaf)
+ glfs_h_close(leaf);
+
+ return;
+}
+
+void
+test_h_links(void)
+{
+ char *my_dir = "linkdir";
+ char *my_file = "file.txt";
+ char *my_symlnk = "slnk.txt";
+ char *my_lnk = "lnk.txt";
+ char *linksrc_dir = "dir1";
+ char *linktgt_dir = "dir2";
+ struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL,
+ *dirsrc = NULL, *dirtgt = NULL, *dleaf = NULL;
+ struct glfs_object *ln1 = NULL;
+ struct stat sb;
+ int ret;
+ char *buf = NULL;
+
+ printf("glfs_h_link(s) tests: In Progress\n");
+
+ /* Prepare tests */
+ root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (root == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb);
+ if (parent == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, root, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dirsrc = glfs_h_mkdir(fs, parent, linksrc_dir, 0755, &sb);
+ if (dirsrc == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ linksrc_dir, parent, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dirtgt = glfs_h_mkdir(fs, parent, linktgt_dir, 0755, &sb);
+ if (dirtgt == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ linktgt_dir, parent, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dleaf = glfs_h_creat(fs, dirsrc, my_file, O_CREAT, 0644, &sb);
+ if (dleaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, dirsrc, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* run tests */
+ /* sym link: /testdir/linkdir/file.txt to ./slnk.txt */
+ ln1 = glfs_h_symlink(fs, parent, my_symlnk, "./file.txt", &sb);
+ if (ln1 == NULL) {
+ fprintf(stderr, "glfs_h_symlink: error creating %s: from (%p),%s\n",
+ my_symlnk, parent, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ buf = calloc(1024, sizeof(char));
+ if (buf == NULL) {
+ fprintf(stderr, "Error allocating memory\n");
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+
+ ret = glfs_h_readlink(fs, ln1, buf, 1024);
+ if (ret <= 0) {
+ fprintf(stderr, "glfs_h_readlink: error reading %s: from (%p),%s\n",
+ my_symlnk, ln1, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ if (!(strncmp(buf, my_symlnk, strlen(my_symlnk)))) {
+ fprintf(stderr,
+ "glfs_h_readlink: error mismatch in link name: actual %s: "
+ "retrieved %s\n",
+ my_symlnk, buf);
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+
+ /* link: /testdir/linkdir/file.txt to ./lnk.txt */
+ ret = glfs_h_link(fs, leaf, parent, my_lnk);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_link: error creating %s: from (%p),%s\n",
+ my_lnk, parent, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ /* TODO: Should write content to a file and read from the link */
+
+ /* link: /testdir/linkdir/dir1/file.txt to ../dir2/slnk.txt */
+ ret = glfs_h_link(fs, dleaf, dirtgt, my_lnk);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_link: error creating %s: from (%p),%s\n",
+ my_lnk, dirtgt, strerror(errno));
+ printf("glfs_h_link(s) tests: FAILED\n");
+ goto out;
+ }
+ /* TODO: Should write content to a file and read from the link */
+
+ printf("glfs_h_link(s) tests: PASSED\n");
+
+out:
+ if (root)
+ glfs_h_close(root);
+ if (parent)
+ glfs_h_close(parent);
+ if (leaf)
+ glfs_h_close(leaf);
+ if (dirsrc)
+ glfs_h_close(dirsrc);
+ if (dirtgt)
+ glfs_h_close(dirtgt);
+ if (dleaf)
+ glfs_h_close(dleaf);
+ if (ln1)
+ glfs_h_close(ln1);
+ if (buf)
+ free(buf);
+
+ return;
+}
+
+void
+test_h_rename(void)
+{
+ char *my_dir = "renamedir";
+ char *my_file = "file.txt";
+ char *src_dir = "dir1";
+ char *tgt_dir = "dir2";
+ struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL,
+ *dirsrc = NULL, *dirtgt = NULL, *dleaf = NULL;
+ struct stat sb;
+ int ret;
+
+ printf("glfs_h_rename tests: In Progress\n");
+
+ /* Prepare tests */
+ root = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (root == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ parent = glfs_h_mkdir(fs, root, my_dir, 0755, &sb);
+ if (parent == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, root, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_creat(fs, parent, my_file, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, parent, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dirsrc = glfs_h_mkdir(fs, parent, src_dir, 0755, &sb);
+ if (dirsrc == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ src_dir, parent, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dirtgt = glfs_h_mkdir(fs, parent, tgt_dir, 0755, &sb);
+ if (dirtgt == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ tgt_dir, parent, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ dleaf = glfs_h_creat(fs, dirsrc, my_file, O_CREAT, 0644, &sb);
+ if (dleaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, dirsrc, strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* run tests */
+ /* Rename file.txt -> file1.txt */
+ ret = glfs_h_rename(fs, parent, "file.txt", parent, "file1.txt");
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n",
+ "file.txt", "file1.txt", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename dir1/file.txt -> file.txt */
+ ret = glfs_h_rename(fs, dirsrc, "file.txt", parent, "file.txt");
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_rename: error renaming %s/%s to %s (%s)\n",
+ src_dir, "file.txt", "file.txt", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename file1.txt -> file.txt (exists) */
+ ret = glfs_h_rename(fs, parent, "file1.txt", parent, "file.txt");
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n",
+ "file.txt", "file.txt", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename dir1 -> dir3 */
+ ret = glfs_h_rename(fs, parent, "dir1", parent, "dir3");
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", "dir1",
+ "dir3", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename dir2 ->dir3 (exists) */
+ ret = glfs_h_rename(fs, parent, "dir2", parent, "dir3");
+ if (ret != 0) {
+ fprintf(stderr, "glfs_h_rename: error renaming %s to %s (%s)\n", "dir2",
+ "dir3", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename file.txt -> dir3 (fail) */
+ ret = glfs_h_rename(fs, parent, "file.txt", parent, "dir3");
+ if (ret == 0) {
+ fprintf(stderr, "glfs_h_rename: NO error renaming %s to %s (%s)\n",
+ "file.txt", "dir3", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ /* rename dir3 -> file.txt (fail) */
+ ret = glfs_h_rename(fs, parent, "dir3", parent, "file.txt");
+ if (ret == 0) {
+ fprintf(stderr, "glfs_h_rename: NO error renaming %s to %s (%s)\n",
+ "dir3", "file.txt", strerror(errno));
+ printf("glfs_h_rename tests: FAILED\n");
+ goto out;
+ }
+
+ printf("glfs_h_rename tests: PASSED\n");
+
+out:
+ if (root)
+ glfs_h_close(root);
+ if (parent)
+ glfs_h_close(parent);
+ if (leaf)
+ glfs_h_close(leaf);
+ if (dirsrc)
+ glfs_h_close(dirsrc);
+ if (dirtgt)
+ glfs_h_close(dirtgt);
+ if (dleaf)
+ glfs_h_close(dleaf);
+
+ return;
+}
+
+void
+assimilatetime(struct timespec *ts, struct timespec ts_st,
+ struct timespec ts_ed)
+{
+ if ((ts_ed.tv_nsec - ts_st.tv_nsec) < 0) {
+ ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec - 1;
+ ts->tv_nsec += 1000000000 + ts_ed.tv_nsec - ts_st.tv_nsec;
+ } else {
+ ts->tv_sec += ts_ed.tv_sec - ts_st.tv_sec;
+ ts->tv_nsec += ts_ed.tv_nsec - ts_st.tv_nsec;
+ }
+
+ if (ts->tv_nsec > 1000000000) {
+ ts->tv_nsec = ts->tv_nsec - 1000000000;
+ ts->tv_sec += 1;
+ }
+
+ return;
+}
+
+#define MAX_FILES_CREATE 10
+#define MAXPATHNAME 512
+void
+test_h_performance(void)
+{
+ char *my_dir = "perftest", *full_dir_path = "/testdir/perftest";
+ char *my_file = "file_", my_file_name[MAXPATHNAME];
+ struct glfs_object *parent = NULL, *leaf = NULL, *dir = NULL;
+ struct stat sb;
+ int ret, i;
+ struct glfs_fd *fd;
+ struct timespec c_ts = {0, 0}, c_ts_st, c_ts_ed;
+ struct timespec o_ts = {0, 0}, o_ts_st, o_ts_ed;
+
+ printf("glfs_h_performance tests: In Progress\n");
+
+ /* Prepare tests */
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, NULL, strerror(errno));
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+
+ dir = glfs_h_mkdir(fs, parent, my_dir, 0755, &sb);
+ if (dir == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error creating %s: from (%p),%s\n",
+ my_dir, parent, strerror(errno));
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* create performance */
+ ret = clock_gettime(CLOCK_REALTIME, &o_ts_st);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ for (i = 0; i < MAX_FILES_CREATE; i++) {
+ sprintf(my_file_name, "%s%d", my_file, i);
+
+ ret = clock_gettime(CLOCK_REALTIME, &c_ts_st);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ leaf = glfs_h_lookupat(fs, dir, my_file_name, &sb, 0);
+ if (leaf != NULL) {
+ fprintf(stderr, "glfs_h_lookup: exists %s\n", my_file_name);
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+
+ leaf = glfs_h_creat(fs, dir, my_file_name, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error creating %s: from (%p),%s\n",
+ my_file, dir, strerror(errno));
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+
+ ret = clock_gettime(CLOCK_REALTIME, &c_ts_ed);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ assimilatetime(&c_ts, c_ts_st, c_ts_ed);
+ glfs_h_close(leaf);
+ leaf = NULL;
+ }
+
+ ret = clock_gettime(CLOCK_REALTIME, &o_ts_ed);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ assimilatetime(&o_ts, o_ts_st, o_ts_ed);
+
+ printf("Creation performance (handle based):\n\t# empty files:%d\n",
+ MAX_FILES_CREATE);
+ printf("\tOverall time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", o_ts.tv_sec,
+ o_ts.tv_nsec);
+ printf("\tcreate call time time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n",
+ c_ts.tv_sec, c_ts.tv_nsec);
+
+ /* create using path */
+ c_ts.tv_sec = o_ts.tv_sec = 0;
+ c_ts.tv_nsec = o_ts.tv_nsec = 0;
+
+ sprintf(my_file_name, "%s1", full_dir_path);
+ ret = glfs_mkdir(fs, my_file_name, 0755);
+ if (ret != 0) {
+ fprintf(stderr, "glfs_mkdir: error creating %s: from (%p),%s\n", my_dir,
+ parent, strerror(errno));
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ ret = clock_gettime(CLOCK_REALTIME, &o_ts_st);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ for (i = 0; i < MAX_FILES_CREATE; i++) {
+ sprintf(my_file_name, "%s1/%sn%d", full_dir_path, my_file, i);
+
+ ret = clock_gettime(CLOCK_REALTIME, &c_ts_st);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ ret = glfs_stat(fs, my_file_name, &sb);
+ if (ret == 0) {
+ fprintf(stderr, "glfs_stat: exists %s\n", my_file_name);
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+
+ fd = glfs_creat(fs, my_file_name, O_CREAT, 0644);
+ if (fd == NULL) {
+ fprintf(stderr, "glfs_creat: error creating %s: from (%p),%s\n",
+ my_file, dir, strerror(errno));
+ printf("glfs_h_performance tests: FAILED\n");
+ goto out;
+ }
+
+ ret = clock_gettime(CLOCK_REALTIME, &c_ts_ed);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ assimilatetime(&c_ts, c_ts_st, c_ts_ed);
+ glfs_close(fd);
+ }
+
+ ret = clock_gettime(CLOCK_REALTIME, &o_ts_ed);
+ if (ret != 0) {
+ fprintf(stderr, "clock_gettime: error %s\n", strerror(errno));
+ printf("glfs_h_getattrs and setattrs tests: FAILED\n");
+ goto out;
+ }
+
+ assimilatetime(&o_ts, o_ts_st, o_ts_ed);
+
+ printf("Creation performance (path based):\n\t# empty files:%d\n",
+ MAX_FILES_CREATE);
+ printf("\tOverall time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n", o_ts.tv_sec,
+ o_ts.tv_nsec);
+ printf("\tcreate call time time:\n\t\tSecs:%ld\n\t\tnSecs:%ld\n",
+ c_ts.tv_sec, c_ts.tv_nsec);
+out:
+ return;
+}
+
+int
+test_handleops(int argc, char *argv[])
+{
+ int ret = 0;
+ glfs_fd_t *fd = NULL;
+ struct stat sb = {
+ 0,
+ };
+ struct glfs_object *root = NULL, *parent = NULL, *leaf = NULL, *tmp = NULL;
+ char readbuf[32], writebuf[32];
+ unsigned char leaf_handle[GFAPI_HANDLE_LENGTH];
+
+ char *full_leaf_name = "/testdir/testfile.txt", *leaf_name = "testfile.txt",
+ *relative_leaf_name = "testdir/testfile.txt";
+ char *leaf_name1 = "testfile1.txt";
+ char *full_newparent_name = "/testdir/dir1", *newparent_name = "dir1";
+ char *full_newnod_name = "/testdir/nod1", *newnod_name = "nod1";
+
+ /* Initialize test area */
+ ret = glfs_mkdir(fs, full_parent_name, 0755);
+ if (ret != 0 && errno != EEXIST) {
+ fprintf(stderr, "%s: (%p) %s\n", full_parent_name, fd, strerror(errno));
+ printf("Test initialization failed on volume %s\n", argv[1]);
+ goto out;
+ } else if (ret != 0) {
+ printf("Found test directory %s to be existing\n", full_parent_name);
+ printf("Cleanup test directory and restart tests\n");
+ goto out;
+ }
+
+ fd = glfs_creat(fs, full_leaf_name, O_CREAT, 0644);
+ if (fd == NULL) {
+ fprintf(stderr, "%s: (%p) %s\n", full_leaf_name, fd, strerror(errno));
+ printf("Test initialization failed on volume %s\n", argv[1]);
+ goto out;
+ }
+ glfs_close(fd);
+
+ printf("Initialized the test area, within volume %s\n", argv[1]);
+
+ /* Handle based APIs test area */
+
+ /* glfs_lookupat test */
+ printf("glfs_h_lookupat tests: In Progress\n");
+ /* start at root of the volume */
+ root = glfs_h_lookupat(fs, NULL, "/", &sb, 0);
+ if (root == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", "/",
+ NULL, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* lookup a parent within root */
+ parent = glfs_h_lookupat(fs, root, parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ parent_name, root, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* lookup a leaf/child within the parent */
+ leaf = glfs_h_lookupat(fs, parent, leaf_name, &sb, 0);
+ if (leaf == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ leaf_name, parent, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* reset */
+ glfs_h_close(root);
+ root = NULL;
+ glfs_h_close(leaf);
+ leaf = NULL;
+ glfs_h_close(parent);
+ parent = NULL;
+
+ /* check absolute paths */
+ root = glfs_h_lookupat(fs, NULL, "/", &sb, 0);
+ if (root == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n", "/",
+ NULL, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, root, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_lookupat(fs, NULL, full_leaf_name, &sb, 0);
+ if (leaf == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_leaf_name, parent, strerror(errno));
+ printf("glfs_h_lookupat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* reset */
+ glfs_h_close(leaf);
+ leaf = NULL;
+
+ /* check multiple component paths */
+ leaf = glfs_h_lookupat(fs, root, relative_leaf_name, &sb, 0);
+ if (leaf == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ relative_leaf_name, parent, strerror(errno));
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* reset */
+ glfs_h_close(root);
+ root = NULL;
+ glfs_h_close(parent);
+ parent = NULL;
+
+ /* check symlinks in path */
+
+ /* TODO: -ve test cases */
+ /* parent invalid
+ * path invalid
+ * path does not exist after some components
+ * no parent, but relative path
+ * parent and full path? -ve?
+ */
+
+ printf("glfs_h_lookupat tests: PASSED\n");
+
+ /* glfs_openat test */
+ printf("glfs_h_open tests: In Progress\n");
+ fd = glfs_h_open(fs, leaf, O_RDWR);
+ if (fd == NULL) {
+ fprintf(stderr, "glfs_h_open: error on open of %s: %s\n",
+ full_leaf_name, strerror(errno));
+ printf("glfs_h_open tests: FAILED\n");
+ goto out;
+ }
+
+ /* test read/write based on fd */
+ memcpy(writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32);
+ ret = glfs_write(fd, writebuf, 32, 0);
+
+ glfs_lseek(fd, 0, SEEK_SET);
+
+ ret = glfs_read(fd, readbuf, 32, 0);
+ if (memcmp(readbuf, writebuf, 32)) {
+ printf("Failed to read what I wrote: %s %s\n", readbuf, writebuf);
+ glfs_close(fd);
+ printf("glfs_h_open tests: FAILED\n");
+ goto out;
+ }
+
+ glfs_h_close(leaf);
+ leaf = NULL;
+ glfs_close(fd);
+
+ printf("glfs_h_open tests: PASSED\n");
+
+ /* Create tests */
+ printf("glfs_h_creat tests: In Progress\n");
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, root, strerror(errno));
+ printf("glfs_h_creat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_creat(fs, parent, leaf_name1, O_CREAT, 0644, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_creat: error on create of %s: from (%p),%s\n",
+ leaf_name1, parent, strerror(errno));
+ printf("glfs_h_creat tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ glfs_h_close(leaf);
+ leaf = NULL;
+
+ leaf = glfs_h_creat(fs, parent, leaf_name1, O_CREAT | O_EXCL, 0644, &sb);
+ if (leaf != NULL || errno != EEXIST) {
+ fprintf(stderr,
+ "glfs_h_creat: existing file, leaf = (%p), errno = %s\n", leaf,
+ strerror(errno));
+ printf("glfs_h_creat tests: FAILED\n");
+ if (leaf != NULL) {
+ glfs_h_close(leaf);
+ leaf = NULL;
+ }
+ }
+
+ tmp = glfs_h_creat(fs, root, parent_name, O_CREAT, 0644, &sb);
+ if (tmp != NULL || !(errno == EISDIR || errno == EINVAL)) {
+ fprintf(stderr, "glfs_h_creat: dir create, tmp = (%p), errno = %s\n",
+ leaf, strerror(errno));
+ printf("glfs_h_creat tests: FAILED\n");
+ if (tmp != NULL) {
+ glfs_h_close(tmp);
+ tmp = NULL;
+ }
+ }
+
+ /* TODO: Other combinations and -ve cases as applicable */
+ printf("glfs_h_creat tests: PASSED\n");
+
+ /* extract handle and create from handle test */
+ printf(
+ "glfs_h_extract_handle and glfs_h_create_from_handle tests: In "
+ "Progress\n");
+ /* TODO: Change the lookup to create below for a GIFD recovery failure,
+ * that needs to be fixed */
+ leaf = glfs_h_lookupat(fs, parent, leaf_name1, &sb, 0);
+ if (leaf == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ leaf_name1, parent, strerror(errno));
+ printf("glfs_h_extract_handle tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ ret = glfs_h_extract_handle(leaf, leaf_handle, GFAPI_HANDLE_LENGTH);
+ if (ret < 0) {
+ fprintf(stderr,
+ "glfs_h_extract_handle: error extracting handle of %s: %s\n",
+ full_leaf_name, strerror(errno));
+ printf("glfs_h_extract_handle tests: FAILED\n");
+ goto out;
+ }
+ peek_handle(leaf_handle);
+
+ glfs_h_close(leaf);
+ leaf = NULL;
+
+ leaf = glfs_h_create_from_handle(fs, leaf_handle, GFAPI_HANDLE_LENGTH, &sb);
+ if (leaf == NULL) {
+ fprintf(
+ stderr,
+ "glfs_h_create_from_handle: error on create of %s: from (%p),%s\n",
+ leaf_name1, leaf_handle, strerror(errno));
+ printf("glfs_h_create_from_handle tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ fd = glfs_h_open(fs, leaf, O_RDWR);
+ if (fd == NULL) {
+ fprintf(stderr, "glfs_h_open: error on open of %s: %s\n",
+ full_leaf_name, strerror(errno));
+ printf("glfs_h_create_from_handle tests: FAILED\n");
+ goto out;
+ }
+
+ /* test read/write based on fd */
+ memcpy(writebuf, "abcdefghijklmnopqrstuvwxyz012345", 32);
+ ret = glfs_write(fd, writebuf, 32, 0);
+
+ glfs_lseek(fd, 0, SEEK_SET);
+
+ ret = glfs_read(fd, readbuf, 32, 0);
+ if (memcmp(readbuf, writebuf, 32)) {
+ printf("Failed to read what I wrote: %s %s\n", writebuf, writebuf);
+ printf("glfs_h_create_from_handle tests: FAILED\n");
+ glfs_close(fd);
+ goto out;
+ }
+
+ glfs_close(fd);
+ glfs_h_close(leaf);
+ leaf = NULL;
+ glfs_h_close(parent);
+ parent = NULL;
+
+ printf(
+ "glfs_h_extract_handle and glfs_h_create_from_handle tests: PASSED\n");
+
+ /* Mkdir tests */
+ printf("glfs_h_mkdir tests: In Progress\n");
+
+ ret = glfs_rmdir(fs, full_newparent_name);
+ if (ret && errno != ENOENT) {
+ fprintf(stderr, "glfs_rmdir: Failed for %s: %s\n", full_newparent_name,
+ strerror(errno));
+ printf("glfs_h_mkdir tests: FAILED\n");
+ goto out;
+ }
+
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, root, strerror(errno));
+ printf("glfs_h_mkdir tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_mkdir(fs, parent, newparent_name, 0755, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error on mkdir of %s: from (%p),%s\n",
+ newparent_name, parent, strerror(errno));
+ printf("glfs_h_mkdir tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ glfs_h_close(leaf);
+ leaf = NULL;
+
+ leaf = glfs_h_mkdir(fs, parent, newparent_name, 0755, &sb);
+ if (leaf != NULL || errno != EEXIST) {
+ fprintf(stderr,
+ "glfs_h_mkdir: existing directory, leaf = (%p), errno = %s\n",
+ leaf, strerror(errno));
+ printf("glfs_h_mkdir tests: FAILED\n");
+ if (leaf != NULL) {
+ glfs_h_close(leaf);
+ leaf = NULL;
+ }
+ }
+
+ glfs_h_close(parent);
+ parent = NULL;
+
+ printf("glfs_h_mkdir tests: PASSED\n");
+
+ /* Mknod tests */
+ printf("glfs_h_mknod tests: In Progress\n");
+ ret = glfs_unlink(fs, full_newnod_name);
+ if (ret && errno != ENOENT) {
+ fprintf(stderr, "glfs_unlink: Failed for %s: %s\n", full_newnod_name,
+ strerror(errno));
+ printf("glfs_h_mknod tests: FAILED\n");
+ goto out;
+ }
+
+ parent = glfs_h_lookupat(fs, NULL, full_parent_name, &sb, 0);
+ if (parent == NULL) {
+ fprintf(stderr,
+ "glfs_h_lookupat: error on lookup of %s: from (%p),%s\n",
+ full_parent_name, root, strerror(errno));
+ printf("glfs_h_mknod tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ leaf = glfs_h_mknod(fs, parent, newnod_name, S_IFIFO, 0, &sb);
+ if (leaf == NULL) {
+ fprintf(stderr, "glfs_h_mkdir: error on mkdir of %s: from (%p),%s\n",
+ newnod_name, parent, strerror(errno));
+ printf("glfs_h_mknod tests: FAILED\n");
+ goto out;
+ }
+ peek_stat(&sb);
+
+ /* TODO: create op on a FIFO node hangs, need to check and fix
+ tmp = glfs_h_creat (fs, parent, newnod_name, O_CREAT, 0644, &sb);
+ if (tmp != NULL || errno != EINVAL) {
+ fprintf (stderr, "glfs_h_creat: node create, tmp = (%p), errno =
+ %s\n", tmp, strerror (errno)); printf ("glfs_h_creat/mknod tests:
+ FAILED\n"); if (tmp != NULL) { glfs_h_close(tmp); tmp = NULL;
+ }
+ } */
+
+ glfs_h_close(leaf);
+ leaf = NULL;
+
+ leaf = glfs_h_mknod(fs, parent, newnod_name, 0644, 0, &sb);
+ if (leaf != NULL || errno != EEXIST) {
+ fprintf(stderr,
+ "glfs_h_mknod: existing node, leaf = (%p), errno = %s\n", leaf,
+ strerror(errno));
+ printf("glfs_h_mknod tests: FAILED\n");
+ if (leaf != NULL) {
+ glfs_h_close(leaf);
+ leaf = NULL;
+ }
+ }
+
+ glfs_h_close(parent);
+ parent = NULL;
+
+ printf("glfs_h_mknod tests: PASSED\n");
+
+ /* unlink tests */
+ test_h_unlink();
+
+ /* TODO: opendir tests */
+
+ /* getattr tests */
+ test_h_getsetattrs();
+
+ /* TODO: setattr tests */
+
+ /* truncate tests */
+ test_h_truncate();
+
+ /* link tests */
+ test_h_links();
+
+ /* rename tests */
+ test_h_rename();
+
+ /* performance tests */
+ test_h_performance();
+
+ /* END: New APIs test area */
+
+out:
+ /* Cleanup glfs handles */
+ if (root)
+ glfs_h_close(root);
+ if (parent)
+ glfs_h_close(parent);
+ if (leaf)
+ glfs_h_close(leaf);
+
+ return ret;
+}
+
+int
+test_write_apis(glfs_t *fs)
+{
+ /* Add more content here */
+ /* Some apis we can get are */
+ /*
+ 0. glfs_set_xlator_option()
+
+ Read/Write combinations:
+ . glfs_{p,}readv/{p,}writev
+ . glfs_pread/pwrite
+
+ tests/basic/gfapi/gfapi-async-calls-test.c
+ . glfs_read_async/write_async
+ . glfs_pread_async/pwrite_async
+ . glfs_readv_async/writev_async
+ . glfs_preadv_async/pwritev_async
+
+ . ftruncate/ftruncate_async
+ . fsync/fsync_async
+ . fdatasync/fdatasync_async
+
+ */
+
+ glfs_fd_t *fd = NULL;
+ char *filename = "/filename2";
+ int flags = O_RDWR;
+ char *buf = "some bytes!";
+ char writestr[TEST_STR_LEN];
+ struct iovec iov = {&writestr, TEST_STR_LEN};
+ int ret, i;
+
+ for (i = 0; i < TEST_STR_LEN; i++)
+ writestr[i] = 0x11;
+
+ fd = glfs_open(fs, filename, flags);
+ if (!fd)
+ fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno));
+
+ ret = glfs_writev(fd, &iov, 1, flags);
+ if (ret < 0) {
+ fprintf(stderr, "writev(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+ }
+
+ ret = glfs_pwrite(fd, buf, 10, 4, flags, NULL, NULL);
+ if (ret < 0) {
+ fprintf(stderr, "pwrite(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+ }
+
+ ret = glfs_pwritev(fd, &iov, 1, 4, flags);
+ if (ret < 0) {
+ fprintf(stderr, "pwritev(%s): %d (%s)\n", filename, ret,
+ strerror(errno));
+ }
+
+ return 0;
+}
+
+int
+test_metadata_ops(glfs_t *fs, glfs_t *fs2)
+{
+ glfs_fd_t *fd = NULL;
+ glfs_fd_t *fd2 = NULL;
+ struct stat sb = {
+ 0,
+ };
+ struct glfs_stat gsb = {
+ 0,
+ };
+ struct statvfs sfs;
+ char readbuf[32];
+ char writebuf[32];
+
+ char *filename = "/filename2";
+ int ret;
+
+ ret = glfs_lstat(fs, filename, &sb);
+ fprintf(stderr, "lstat(%s): (%d) %s\n", filename, ret, strerror(errno));
+
+ fd = glfs_creat(fs, filename, O_RDWR, 0644);
+ fprintf(stderr, "creat(%s): (%p) %s\n", filename, fd, strerror(errno));
+
+ fd2 = glfs_open(fs2, filename, O_RDWR);
+ fprintf(stderr, "open(%s): (%p) %s\n", filename, fd, strerror(errno));
+
+ glfs_lseek(fd2, 0, SEEK_SET);
+
+ ret = glfs_read(fd2, readbuf, 32, 0);
+
+ printf("read %d, %s", ret, readbuf);
+
+ /* get stat */
+ ret = glfs_fstat(fd2, &sb);
+
+ ret = glfs_access(fs, filename, R_OK);
+
+ /* set stat */
+ /* TODO: got some errors, need to fix */
+ /* ret = glfs_fsetattr(fd2, &gsb); */
+
+ glfs_close(fd);
+ glfs_close(fd2);
+
+ filename = "/filename3";
+ ret = glfs_mknod(fs, filename, S_IFIFO, 0);
+ fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno));
+
+ ret = glfs_lstat(fs, filename, &sb);
+ fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno));
+
+ ret = glfs_rename(fs, filename, "/filename4");
+ fprintf(stderr, "rename(%s): (%d) %s\n", filename, ret, strerror(errno));
+
+ ret = glfs_unlink(fs, "/filename4");
+ fprintf(stderr, "unlink(%s): (%d) %s\n", "/filename4", ret,
+ strerror(errno));
+
+ filename = "/dirname2";
+ ret = glfs_mkdir(fs, filename, 0);
+ fprintf(stderr, "%s: (%d) %s\n", filename, ret, strerror(errno));
+
+ ret = glfs_lstat(fs, filename, &sb);
+ fprintf(stderr, "lstat(%s): (%d) %s\n", filename, ret, strerror(errno));
+
+ ret = glfs_rmdir(fs, filename);
+ fprintf(stderr, "rmdir(%s): (%d) %s\n", filename, ret, strerror(errno));
+}
+int
+main(int argc, char *argv[])
+{
+ glfs_t *fs2 = NULL;
+ int ret = 0;
+ glfs_fd_t *fd = NULL;
+ glfs_fd_t *fd2 = NULL;
+ struct stat sb = {
+ 0,
+ };
+ struct glfs_stat gsb = {
+ 0,
+ };
+ struct statvfs sfs;
+ char readbuf[32];
+ char writebuf[32];
+
+ char *filename = "/filename2";
+
+ if (argc != 3) {
+ printf("Expect following args\n\t%s <volname> <hostname>\n", argv[0]);
+ return -1;
+ }
+
+ fs = glfs_new(argv[1]);
+ if (!fs) {
+ fprintf(stderr, "glfs_new: returned NULL\n");
+ return 1;
+ }
+
+ // ret = glfs_set_volfile (fs, "/tmp/posix.vol");
+
+ ret = glfs_set_volfile_server(fs, "tcp", argv[2], 24007);
+
+ // ret = glfs_set_volfile_server (fs, "unix", "/tmp/gluster.sock", 0);
+
+ ret = glfs_set_logging(fs, "/dev/stderr", 7);
+
+ ret = glfs_init(fs);
+
+ fprintf(stderr, "glfs_init: returned %d\n", ret);
+
+ if (ret)
+ goto out;
+
+ sleep(2);
+
+ fs2 = glfs_new(argv[1]);
+ if (!fs2) {
+ fprintf(stderr, "glfs_new: returned NULL\n");
+ return 1;
+ }
+
+ // ret = glfs_set_volfile (fs2, "/tmp/posix.vol");
+
+ ret = glfs_set_volfile_server(fs2, "tcp", argv[2], 24007);
+
+ ret = glfs_set_logging(fs2, "/dev/stderr", 7);
+
+ ret = glfs_init(fs2);
+
+ fprintf(stderr, "glfs_init: returned %d\n", ret);
+
+ test_metadata_ops(fs, fs2);
+
+ test_dirops(fs);
+
+ test_xattr(fs);
+
+ test_chdir(fs);
+
+ test_handleops(argc, argv);
+ // done
+
+ /* Test some extra apis */
+ test_write_apis(fs);
+
+ glfs_statvfs(fs, "/", &sfs);
+
+ glfs_fini(fs);
+ glfs_fini(fs2);
+
+ ret = 0;
+out:
+ return ret;
+}
diff --git a/api/src/Makefile.am b/api/src/Makefile.am
new file mode 100644
index 00000000000..7f9a7d17b35
--- /dev/null
+++ b/api/src/Makefile.am
@@ -0,0 +1,43 @@
+lib_LTLIBRARIES = libgfapi.la
+noinst_HEADERS = glfs-mem-types.h glfs-internal.h gfapi-messages.h
+libgfapi_HEADERS = glfs.h glfs-handles.h
+libgfapidir = $(includedir)/glusterfs/api
+
+EXTRA_DIST = gfapi.map gfapi.aliases
+
+libgfapi_la_SOURCES = glfs.c glfs-mgmt.c glfs-fops.c glfs-resolve.c \
+ glfs-handleops.c
+libgfapi_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
+ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \
+ $(top_builddir)/rpc/xdr/src/libgfxdr.la
+
+libgfapi_la_LDFLAGS = -version-info $(GFAPI_LT_VERSION) $(GF_LDFLAGS) \
+ $(GFAPI_EXTRA_LDFLAGS) $(ACL_LIBS)
+
+libgfapi_la_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
+ -I$(top_srcdir)/rpc/rpc-lib/src \
+ -I$(top_srcdir)/rpc/xdr/src \
+ -I$(top_builddir)/rpc/xdr/src \
+ -DDATADIR=\"$(localstatedir)\" \
+ -D__USE_FILE_OFFSET64 -D__USE_LARGEFILE64
+
+AM_CFLAGS = -Wall $(GF_CFLAGS)
+
+xlator_LTLIBRARIES = api.la
+xlatordir = $(libdir)/glusterfs/$(PACKAGE_VERSION)/xlator/mount
+# workaround for broken parallel install support in automake with LTLIBRARIES
+# http://debbugs.gnu.org/cgi/bugreport.cgi?bug=7328
+install_xlatorLTLIBRARIES = install-xlatorLTLIBRARIES
+$(install_xlatorLTLIBRARIES): install-libLTLIBRARIES
+
+api_la_SOURCES = glfs-master.c
+api_la_DEPENDENCIES = libgfapi.la
+api_la_CPPFLAGS = $(GF_CPPFLAGS) -I$(top_srcdir)/libglusterfs/src \
+ -I$(top_srcdir)/rpc/xdr/src \
+ -I$(top_builddir)/rpc/xdr/src
+api_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS)
+#api_la_LDFLAGS = -module $(GF_XLATOR_DEFAULT_LDFLAGS) $(GF_LDFLAGS)
+api_la_LIBADD = $(top_builddir)/libglusterfs/src/libglusterfs.la \
+ $(top_builddir)/rpc/rpc-lib/src/libgfrpc.la \
+ $(top_builddir)/rpc/xdr/src/libgfxdr.la \
+ $(top_builddir)/api/src/libgfapi.la
diff --git a/api/src/README.Symbol_Versions b/api/src/README.Symbol_Versions
new file mode 100644
index 00000000000..b6ec95f9311
--- /dev/null
+++ b/api/src/README.Symbol_Versions
@@ -0,0 +1,3 @@
+
+See ../../doc/developer-guide/gfapi-symbol-versions.md
+
diff --git a/api/src/gfapi-messages.h b/api/src/gfapi-messages.h
new file mode 100644
index 00000000000..b9223940416
--- /dev/null
+++ b/api/src/gfapi-messages.h
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2015-2018 Red Hat, Inc. <http://www.redhat.com>
+ * This file is part of GlusterFS.
+ *
+ * This file is licensed to you under your choice of the GNU Lesser
+ * General Public License, version 3 or any later version (LGPLv3 or
+ * later), or the GNU General Public License, version 2 (GPLv2), in all
+ * cases as published by the Free Software Foundation.
+ * */
+
+#ifndef _GFAPI_MESSAGES_H__
+#define _GFAPI_MESSAGES_H__
+
+#include <glusterfs/glfs-message-id.h>
+
+/* To add new message IDs, append new identifiers at the end of the list.
+ *
+ * Never remove a message ID. If it's not used anymore, you can rename it or
+ * leave it as it is, but not delete it. This is to prevent reutilization of
+ * IDs by other messages.
+ *
+ * The component name must match one of the entries defined in
+ * glfs-message-id.h.
+ */
+
+GLFS_MSGID(API, API_MSG_MEM_ACCT_INIT_FAILED, API_MSG_MASTER_XLATOR_INIT_FAILED,
+ API_MSG_GFAPI_XLATOR_INIT_FAILED, API_MSG_VOLFILE_OPEN_FAILED,
+ API_MSG_VOL_SPEC_FILE_ERROR, API_MSG_GLFS_FSOBJ_NULL,
+ API_MSG_INVALID_ENTRY, API_MSG_FSMUTEX_LOCK_FAILED,
+ API_MSG_COND_WAIT_FAILED, API_MSG_FSMUTEX_UNLOCK_FAILED,
+ API_MSG_INODE_REFRESH_FAILED, API_MSG_GRAPH_CONSTRUCT_FAILED,
+ API_MSG_API_XLATOR_ERROR, API_MSG_XDR_PAYLOAD_FAILED,
+ API_MSG_GET_VOLINFO_CBK_FAILED, API_MSG_FETCH_VOLUUID_FAILED,
+ API_MSG_INSUFF_SIZE, API_MSG_FRAME_CREAT_FAILED,
+ API_MSG_DICT_SET_FAILED, API_MSG_XDR_DECODE_FAILED,
+ API_MSG_GET_VOLFILE_FAILED, API_MSG_WRONG_OPVERSION,
+ API_MSG_DICT_SERIALIZE_FAILED, API_MSG_REMOTE_HOST_CONN_FAILED,
+ API_MSG_VOLFILE_SERVER_EXHAUST, API_MSG_CREATE_RPC_CLIENT_FAILED,
+ API_MSG_REG_NOTIFY_FUNC_FAILED, API_MSG_REG_CBK_FUNC_FAILED,
+ API_MSG_GET_CWD_FAILED, API_MSG_FGETXATTR_FAILED,
+ API_MSG_LOCKINFO_KEY_MISSING, API_MSG_FSETXATTR_FAILED,
+ API_MSG_FSYNC_FAILED, API_MSG_FDCREATE_FAILED,
+ API_MSG_INODE_PATH_FAILED, API_MSG_SYNCOP_OPEN_FAILED,
+ API_MSG_LOCK_MIGRATE_FAILED, API_MSG_OPENFD_SKIPPED,
+ API_MSG_FIRST_LOOKUP_GRAPH_FAILED, API_MSG_CWD_GRAPH_REF_FAILED,
+ API_MSG_SWITCHED_GRAPH, API_MSG_XDR_RESPONSE_DECODE_FAILED,
+ API_MSG_VOLFILE_INFO, API_MSG_VOLFILE_CONNECTING, API_MSG_NEW_GRAPH,
+ API_MSG_ALLOC_FAILED, API_MSG_CREATE_HANDLE_FAILED,
+ API_MSG_INODE_LINK_FAILED, API_MSG_STATEDUMP_FAILED,
+ API_MSG_XREADDIRP_R_FAILED, API_MSG_LOCK_INSERT_MERGE_FAILED,
+ API_MSG_SETTING_LOCK_TYPE_FAILED, API_MSG_INODE_FIND_FAILED,
+ API_MSG_FDCTX_SET_FAILED, API_MSG_UPCALL_SYNCOP_FAILED,
+ API_MSG_INVALID_ARG, API_MSG_UPCALL_EVENT_NULL_RECEIVED,
+ API_MSG_FLAGS_HANDLE, API_MSG_FDCREATE_FAILED_ON_GRAPH,
+ API_MSG_TRANS_RDMA_DEP, API_MSG_TRANS_NOT_SUPPORTED,
+ API_MSG_FS_NOT_INIT, API_MSG_INVALID_SYSRQ,
+ API_MSG_DECODE_XDR_FAILED, API_MSG_NULL, API_MSG_CALL_NOT_SUCCESSFUL,
+ API_MSG_CALL_NOT_VALID, API_MSG_UNABLE_TO_DEL,
+ API_MSG_REMOTE_HOST_DISCONN, API_MSG_HANDLE_NOT_SET);
+
+#define API_MSG_ALLOC_FAILED_STR "Upcall allocation failed"
+#define API_MSG_LOCK_INSERT_MERGE_FAILED_STR \
+ "Lock insertion and splitting/merging failed"
+#define API_MSG_SETTING_LOCK_TYPE_FAILED_STR "Setting lock type failed"
+
+#define API_MSG_INVALID_ARG_STR "Invalid"
+#define API_MSG_INVALID_ENTRY_STR "Upcall entry validation failed"
+#define API_MSG_INODE_FIND_FAILED_STR "Unable to find inode entry"
+#define API_MSG_CREATE_HANDLE_FAILED_STR "handle creation failed"
+#define API_MSG_UPCALL_EVENT_NULL_RECEIVED_STR \
+ "Upcall_EVENT_NULL received. Skipping it"
+#define API_MSG_UPCALL_SYNCOP_FAILED_STR "Synctask for upcall failed"
+#define API_MSG_FDCREATE_FAILED_STR "Allocating anonymous fd failed"
+#define API_MSG_XREADDIRP_R_FAILED_STR "glfs_x_readdirp_r failed"
+#define API_MSG_FDCTX_SET_FAILED_STR "Setting fd ctx failed"
+#define API_MSG_FLAGS_HANDLE_STR "arg not set. Flags handled are"
+#define API_MSG_INODE_REFRESH_FAILED_STR "inode refresh failed"
+#define API_MSG_INODE_LINK_FAILED_STR "inode linking failed"
+#define API_MSG_GET_CWD_FAILED_STR "Failed to get cwd"
+#define API_MSG_FGETXATTR_FAILED_STR "fgetxattr failed"
+#define API_MSG_LOCKINFO_KEY_MISSING_STR "missing lockinfo key"
+#define API_MSG_FSYNC_FAILED_STR "fsync() failed"
+#define API_MSG_FDCREATE_FAILED_ON_GRAPH_STR "fd_create failed on graph"
+#define API_MSG_INODE_PATH_FAILED_STR "inode_path failed"
+#define API_MSG_SYNCOP_OPEN_FAILED_STR "syncop_open failed"
+#define API_MSG_LOCK_MIGRATE_FAILED_STR "lock migration failed on graph"
+#define API_MSG_OPENFD_SKIPPED_STR "skipping openfd in graph"
+#define API_MSG_FIRST_LOOKUP_GRAPH_FAILED_STR "first lookup on graph failed"
+#define API_MSG_CWD_GRAPH_REF_FAILED_STR "cwd refresh of graph failed"
+#define API_MSG_SWITCHED_GRAPH_STR "switched to graph"
+#define API_MSG_FSETXATTR_FAILED_STR "fsetxattr failed"
+#define API_MSG_MEM_ACCT_INIT_FAILED_STR "Memory accounting init failed"
+#define API_MSG_MASTER_XLATOR_INIT_FAILED_STR \
+ "master xlator for initialization failed"
+#define API_MSG_GFAPI_XLATOR_INIT_FAILED_STR \
+ "failed to initialize gfapi translator"
+#define API_MSG_VOLFILE_OPEN_FAILED_STR "volume file open failed"
+#define API_MSG_VOL_SPEC_FILE_ERROR_STR "Cannot reach volume specification file"
+#define API_MSG_TRANS_RDMA_DEP_STR \
+ "transport RDMA is deprecated, falling back to tcp"
+#define API_MSG_TRANS_NOT_SUPPORTED_STR \
+ "transport is not supported, possible values tcp|unix"
+#define API_MSG_GLFS_FSOBJ_NULL_STR "fs is NULL"
+#define API_MSG_FS_NOT_INIT_STR "fs is not properly initialized"
+#define API_MSG_FSMUTEX_LOCK_FAILED_STR \
+ "pthread lock on glfs mutex, returned error"
+#define API_MSG_FSMUTEX_UNLOCK_FAILED_STR \
+ "pthread unlock on glfs mutex, returned error"
+#define API_MSG_COND_WAIT_FAILED_STR "cond wait failed"
+#define API_MSG_INVALID_SYSRQ_STR "not a valid sysrq"
+#define API_MSG_GRAPH_CONSTRUCT_FAILED_STR "failed to construct the graph"
+#define API_MSG_API_XLATOR_ERROR_STR \
+ "api master xlator cannot be specified in volume file"
+#define API_MSG_STATEDUMP_FAILED_STR "statedump failed"
+#define API_MSG_DECODE_XDR_FAILED_STR \
+ "Failed to decode xdr response for GF_CBK_STATEDUMP"
+#define API_MSG_NULL_STR "NULL"
+#define API_MSG_XDR_PAYLOAD_FAILED_STR "failed to create XDR payload"
+#define API_MSG_CALL_NOT_SUCCESSFUL_STR \
+ "GET_VOLUME_INFO RPC call is not successful"
+#define API_MSG_XDR_RESPONSE_DECODE_FAILED_STR \
+ "Failed to decode xdr response for GET_VOLUME_INFO"
+#define API_MSG_CALL_NOT_VALID_STR \
+ "Response received for GET_VOLUME_INFO RPC is not valid"
+#define API_MSG_GET_VOLINFO_CBK_FAILED_STR \
+ "In GET_VOLUME_INFO cbk, received error"
+#define API_MSG_FETCH_VOLUUID_FAILED_STR "Unable to fetch volume UUID"
+#define API_MSG_INSUFF_SIZE_STR "Insufficient size passed"
+#define API_MSG_FRAME_CREAT_FAILED_STR "failed to create the frame"
+#define API_MSG_DICT_SET_FAILED_STR "failed to set"
+#define API_MSG_XDR_DECODE_FAILED_STR "XDR decoding error"
+#define API_MSG_GET_VOLFILE_FAILED_STR "failed to get the volume file"
+#define API_MSG_VOLFILE_INFO_STR "No change in volfile, continuing"
+#define API_MSG_UNABLE_TO_DEL_STR "unable to delete file"
+#define API_MSG_WRONG_OPVERSION_STR \
+ "Server is operating at an op-version which is not supported"
+#define API_MSG_DICT_SERIALIZE_FAILED_STR "Failed to serialize dictionary"
+#define API_MSG_REMOTE_HOST_CONN_FAILED_STR "Failed to connect to remote-host"
+#define API_MSG_REMOTE_HOST_DISCONN_STR "disconnected from remote-host"
+#define API_MSG_VOLFILE_SERVER_EXHAUST_STR "Exhausted all volfile servers"
+#define API_MSG_VOLFILE_CONNECTING_STR "connecting to next volfile server"
+#define API_MSG_CREATE_RPC_CLIENT_FAILED_STR "failed to create rpc clnt"
+#define API_MSG_REG_NOTIFY_FUNC_FAILED_STR "failed to register notify function"
+#define API_MSG_REG_CBK_FUNC_FAILED_STR "failed to register callback function"
+#define API_MSG_NEW_GRAPH_STR "New graph coming up"
+#define API_MSG_HANDLE_NOT_SET_STR "handle not set. Flags handled for xstat are"
+#endif /* !_GFAPI_MESSAGES_H__ */
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases
new file mode 100644
index 00000000000..bc639e6b99f
--- /dev/null
+++ b/api/src/gfapi.aliases
@@ -0,0 +1,201 @@
+
+_priv_glfs_loc_touchup _glfs_loc_touchup$GFAPI_PRIVATE_3.4.0
+_priv_glfs_active_subvol _glfs_active_subvol$GFAPI_PRIVATE_3.4.0
+_priv_glfs_subvol_done _glfs_subvol_done$GFAPI_PRIVATE_3.4.0
+_priv_glfs_init_done _glfs_init_done$GFAPI_PRIVATE_3.4.0
+_priv_glfs_resolve_at _glfs_resolve_at$GFAPI_PRIVATE_3.4.0
+
+_pub_glfs_new _glfs_new$GFAPI_3.4.0
+_pub_glfs_set_volfile _glfs_set_volfile$GFAPI_3.4.0
+_pub_glfs_set_volfile_server _glfs_set_volfile_server$GFAPI_3.4.0
+_pub_glfs_set_logging _glfs_set_logging$GFAPI_3.4.0
+_pub_glfs_init _glfs_init$GFAPI_3.4.0
+_pub_glfs_fini _glfs_fini$GFAPI_3.4.0
+_pub_glfs_open _glfs_open$GFAPI_3.4.0
+_pub_glfs_creat _glfs_creat$GFAPI_3.4.0
+_pub_glfs_close _glfs_close$GFAPI_3.4.0
+_pub_glfs_from_glfd _glfs_from_glfd$GFAPI_3.4.0
+_pub_glfs_set_xlator_option _glfs_set_xlator_option$GFAPI_3.4.0
+_pub_glfs_read _glfs_read$GFAPI_3.4.0
+_pub_glfs_write _glfs_write$GFAPI_3.4.0
+_pub_glfs_readv _glfs_readv$GFAPI_3.4.0
+_pub_glfs_writev _glfs_writev$GFAPI_3.4.0
+_pub_glfs_pread34 _glfs_pread$GFAPI_3.4.0
+_pub_glfs_pwrite34 _glfs_pwrite$GFAPI_3.4.0
+_pub_glfs_pread_async34 _glfs_pread_async$GFAPI_3.4.0
+_pub_glfs_pwrite_async34 _glfs_pwrite_async$GFAPI_3.4.0
+_pub_glfs_preadv _glfs_preadv$GFAPI_3.4.0
+_pub_glfs_pwritev _glfs_pwritev$GFAPI_3.4.0
+_pub_glfs_lseek _glfs_lseek$GFAPI_3.4.0
+_pub_glfs_ftruncate34 _glfs_ftruncate$GFAPI_3.4.0
+_pub_glfs_ftruncate_async34 _glfs_ftruncate_async$GFAPI_3.4.0
+_pub_glfs_lstat _glfs_lstat$GFAPI_3.4.0
+_pub_glfs_stat _glfs_stat$GFAPI_3.4.0
+_pub_glfs_fstat _glfs_fstat$GFAPI_3.4.0
+_pub_glfs_fsync34 _glfs_fsync$GFAPI_3.4.0
+_pub_glfs_fsync_async34 _glfs_fsync_async$GFAPI_3.4.0
+_pub_glfs_fdatasync34 _glfs_fdatasync$GFAPI_3.4.0
+_pub_glfs_fdatasync_async34 _glfs_fdatasync_async$GFAPI_3.4.0
+_pub_glfs_access _glfs_access$GFAPI_3.4.0
+_pub_glfs_symlink _glfs_symlink$GFAPI_3.4.0
+_pub_glfs_readlink _glfs_readlink$GFAPI_3.4.0
+_pub_glfs_mknod _glfs_mknod$GFAPI_3.4.0
+_pub_glfs_mkdir _glfs_mkdir$GFAPI_3.4.0
+_pub_glfs_unlink _glfs_unlink$GFAPI_3.4.0
+_pub_glfs_rmdir _glfs_rmdir$GFAPI_3.4.0
+_pub_glfs_rename _glfs_rename$GFAPI_3.4.0
+_pub_glfs_link _glfs_link$GFAPI_3.4.0
+_pub_glfs_opendir _glfs_opendir$GFAPI_3.4.0
+_pub_glfs_readdir_r _glfs_readdir_r$GFAPI_3.4.0
+_pub_glfs_readdirplus_r _glfs_readdirplus_r$GFAPI_3.4.0
+_pub_glfs_telldir _glfs_telldir$GFAPI_3.4.0
+_pub_glfs_seekdir _glfs_seekdir$GFAPI_3.4.0
+_pub_glfs_closedir _glfs_closedir$GFAPI_3.4.0
+_pub_glfs_statvfs _glfs_statvfs$GFAPI_3.4.0
+_pub_glfs_chmod _glfs_chmod$GFAPI_3.4.0
+_pub_glfs_fchmod _glfs_fchmod$GFAPI_3.4.0
+_pub_glfs_chown _glfs_chown$GFAPI_3.4.0
+_pub_glfs_lchown _glfs_lchown$GFAPI_3.4.0
+_pub_glfs_fchown _glfs_fchown$GFAPI_3.4.0
+_pub_glfs_utimens _glfs_utimens$GFAPI_3.4.0
+_pub_glfs_lutimens _glfs_lutimens$GFAPI_3.4.0
+_pub_glfs_futimens _glfs_futimens$GFAPI_3.4.0
+_pub_glfs_getxattr _glfs_getxattr$GFAPI_3.4.0
+_pub_glfs_lgetxattr _glfs_lgetxattr$GFAPI_3.4.0
+_pub_glfs_fgetxattr _glfs_fgetxattr$GFAPI_3.4.0
+_pub_glfs_listxattr _glfs_listxattr$GFAPI_3.4.0
+_pub_glfs_llistxattr _glfs_llistxattr$GFAPI_3.4.0
+_pub_glfs_flistxattr _glfs_flistxattr$GFAPI_3.4.0
+_pub_glfs_setxattr _glfs_setxattr$GFAPI_3.4.0
+_pub_glfs_lsetxattr _glfs_lsetxattr$GFAPI_3.4.0
+_pub_glfs_fsetxattr _glfs_fsetxattr$GFAPI_3.4.0
+_pub_glfs_removexattr _glfs_removexattr$GFAPI_3.4.0
+_pub_glfs_lremovexattr _glfs_lremovexattr$GFAPI_3.4.0
+_pub_glfs_fremovexattr _glfs_fremovexattr$GFAPI_3.4.0
+_pub_glfs_getcwd _glfs_getcwd$GFAPI_3.4.0
+_pub_glfs_chdir _glfs_chdir$GFAPI_3.4.0
+_pub_glfs_fchdir _glfs_fchdir$GFAPI_3.4.0
+_pub_glfs_realpath34 _glfs_realpath$GFAPI_3.4.0
+_pub_glfs_posix_lock _glfs_posix_lock$GFAPI_3.4.0
+_pub_glfs_dup _glfs_dup$GFAPI_3.4.0
+
+_pub_glfs_setfsuid _glfs_setfsuid$GFAPI_3.4.2
+_pub_glfs_setfsgid _glfs_setfsgid$GFAPI_3.4.2
+_pub_glfs_setfsgroups _glfs_setfsgroups$GFAPI_3.4.2
+_pub_glfs_h_lookupat34 _glfs_h_lookupat$GFAPI_3.4.2
+_pub_glfs_h_creat _glfs_h_creat$GFAPI_3.4.2
+_pub_glfs_h_mkdir _glfs_h_mkdir$GFAPI_3.4.2
+_pub_glfs_h_mknod _glfs_h_mknod$GFAPI_3.4.2
+_pub_glfs_h_symlink _glfs_h_symlink$GFAPI_3.4.2
+_pub_glfs_h_unlink _glfs_h_unlink$GFAPI_3.4.2
+_pub_glfs_h_close _glfs_h_close$GFAPI_3.4.2
+_pub_glfs_h_truncate _glfs_h_truncate$GFAPI_3.4.2
+_pub_glfs_h_stat _glfs_h_stat$GFAPI_3.4.2
+_pub_glfs_h_getattrs _glfs_h_getattrs$GFAPI_3.4.2
+_pub_glfs_h_setattrs _glfs_h_setattrs$GFAPI_3.4.2
+_pub_glfs_h_readlink _glfs_h_readlink$GFAPI_3.4.2
+_pub_glfs_h_link _glfs_h_link$GFAPI_3.4.2
+_pub_glfs_h_rename _glfs_h_rename$GFAPI_3.4.2
+_pub_glfs_h_extract_handle _glfs_h_extract_handle$GFAPI_3.4.2
+_pub_glfs_h_create_from_handle _glfs_h_create_from_handle$GFAPI_3.4.2
+_pub_glfs_h_opendir _glfs_h_opendir$GFAPI_3.4.2
+_pub_glfs_h_open _glfs_h_open$GFAPI_3.4.2
+
+_pub_glfs_get_volumeid _glfs_get_volumeid$GFAPI_3.5.0
+_pub_glfs_readdir _glfs_readdir$GFAPI_3.5.0
+_pub_glfs_readdirplus _glfs_readdirplus$GFAPI_3.5.0
+_pub_glfs_fallocate _glfs_fallocate$GFAPI_3.5.0
+_pub_glfs_discard _glfs_discard$GFAPI_3.5.0
+_pub_glfs_zerofill _glfs_zerofill$GFAPI_3.5.0
+_pub_glfs_caller_specific_init _glfs_caller_specific_init$GFAPI_3.5.0
+_pub_glfs_h_setxattrs _glfs_h_setxattrs$GFAPI_3.5.0
+
+_pub_glfs_unset_volfile_server _glfs_unset_volfile_server$GFAPI_3.5.1
+_pub_glfs_h_getxattrs _glfs_h_getxattrs$GFAPI_3.5.1
+_pub_glfs_h_removexattrs _glfs_h_removexattrs$GFAPI_3.5.1
+
+_pub_glfs_get_volfile _glfs_get_volfile$GFAPI_3.6.0
+_pub_glfs_h_access _glfs_h_access$GFAPI_3.6.0
+
+_pub_glfs_h_poll_upcall370 _glfs_h_poll_upcall$GFAPI_3.7.0
+_pub_glfs_h_acl_set _glfs_h_acl_set$GFAPI_3.7.0
+_pub_glfs_h_acl_get _glfs_h_acl_get$GFAPI_3.7.0
+_pub_glfs_h_statfs _glfs_h_statfs$GFAPI_3.7.0
+_pub_glfs_h_anonymous_read _glfs_h_anonymous_read$GFAPI_3.7.0
+_pub_glfs_h_anonymous_write _glfs_h_anonymous_write$GFAPI_3.7.0
+
+_priv_glfs_free_from_ctx _glfs_free_from_ctx$GFAPI_PRIVATE_3.7.0
+_priv_glfs_new_from_ctx _glfs_new_from_ctx$GFAPI_PRIVATE_3.7.0
+_priv_glfs_resolve _glfs_resolve$GFAPI_PRIVATE_3.7.0
+_priv_glfs_process_upcall_event _glfs_process_upcall_event$GFAPI_PRIVATE_3.7.0
+
+_pub_glfs_h_lookupat _glfs_h_lookupat$GFAPI_3.7.4
+
+_pub_glfs_truncate _glfs_truncate$GFAPI_3.7.15
+
+_pub_glfs_free _glfs_free$GFAPI_3.7.16
+_pub_glfs_h_poll_upcall _glfs_h_poll_upcall$GFAPI_3.7.16
+_pub_glfs_upcall_get_fs _glfs_upcall_get_fs$GFAPI_3.7.16
+_pub_glfs_upcall_get_reason _glfs_upcall_get_reason$GFAPI_3.7.16
+_pub_glfs_upcall_get_event _glfs_upcall_get_event$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_object _glfs_upcall_inode_get_object$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_flags _glfs_upcall_inode_get_flags$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_stat _glfs_upcall_inode_get_stat$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_expire _glfs_upcall_inode_get_expire$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_pobject _glfs_upcall_inode_get_pobject$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_pstat _glfs_upcall_inode_get_pstat$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_oldpobject _glfs_upcall_inode_get_oldpobject$GFAPI_3.7.16
+_pub_glfs_upcall_inode_get_oldpstat _glfs_upcall_inode_get_oldpstat$GFAPI_3.7.16
+
+_pub_glfs_realpath _glfs_realpath$GFAPI_3.7.17
+
+_pub_glfs_sysrq _glfs_sysrq$GFAPI_3.10.0
+
+_pub_glfs_fd_set_lkowner _glfs_fd_set_lkowner$GFAPI_3.10.7
+
+_pub_glfs_xreaddirplus_r _glfs_xreaddirplus_r$GFAPI_3.11.0
+_pub_glfs_xreaddirplus_r_get_stat _glfs_xreaddirplus_r_get_stat$GFAPI_3.11.0
+_pub_glfs_xreaddirplus_r_get_object _glfs_xreaddirplus_r_get_object$GFAPI_3.11.0
+_pub_glfs_object_copy _glfs_object_copy$GFAPI_3.11.0
+
+_priv_glfs_ipc _glfs_ipc$GFAPI_3.12.0
+
+_pub_glfs_upcall_register _glfs_upcall_register$GFAPI_3.13.0
+_pub_glfs_upcall_unregister _glfs_upcall_unregister$GFAPI_3.13.0
+
+_pub_glfs_setfsleaseid _glfs_setfsleaseid$GFAPI_4.0.0
+_pub_glfs_file_lock _glfs_file_lock$GFAPI_4.0.0
+_pub_glfs_lease _glfs_lease$GFAPI_4.0.0
+_pub_glfs_h_lease _glfs_h_lease$GFAPI_4.0.0
+_pub_glfs_upcall_lease_get_object _glfs_upcall_lease_get_object$GFAPI_4.1.6
+_pub_glfs_upcall_lease_get_lease_type _glfs_upcall_lease_get_lease_type$GFAPI_4.1.6
+
+_priv_glfs_statx _glfs_statx$GFAPI_6.0
+_priv_glfs_iatt_from_statx _glfs_iatt_from_statx$GFAPI_6.0
+_priv_glfs_setfspid _glfs_setfspid$GFAPI_6.1
+
+_pub_glfs_read_async _glfs_read_async$GFAPI_6.0
+_pub_glfs_write_async _glfs_write_async$GFAPI_6.0
+_pub_glfs_readv_async _glfs_readv_async$GFAPI_6.0
+_pub_glfs_writev_async _glfs_writev_async$GFAPI_6.0
+_pub_glfs_pread _glfs_pread$GFAPI_6.0
+_pub_glfs_pwrite _glfs_pwrite$GFAPI_6.0
+_pub_glfs_pread_async _glfs_pread_async$GFAPI_6.0
+_pub_glfs_pwrite_async _glfs_pwrite_async$GFAPI_6.0
+_pub_glfs_preadv_async _glfs_preadv_async$GFAPI_6.0
+_pub_glfs_pwritev_async _glfs_pwritev_async$GFAPI_6.0
+_pub_glfs_fsync _glfs_fsync$GFAPI_6.0
+_pub_glfs_fsync_async _glfs_fsync_async$GFAPI_6.0
+_pub_glfs_fdatasync _glfs_fdatasync$GFAPI_6.0
+_pub_glfs_fdatasync_async _glfs_fdatasync_async$GFAPI_6.0
+_pub_glfs_ftruncate _glfs_ftruncate$GFAPI_6.0
+_pub_glfs_ftruncate_async _glfs_ftruncate_async$GFAPI_6.0
+_pub_glfs_discard_async _glfs_discard_async$GFAPI_6.0
+_pub_glfs_zerofill_async _glfs_zerofill_async$GFAPI_6.0
+_pub_glfs_copy_file_range _glfs_copy_file_range$GFAPI_6.0
+_pub_glfs_fsetattr _glfs_fsetattr$GFAPI_6.0
+_pub_glfs_setattr _glfs_setattr$GFAPI_6.0
+
+_pub_glfs_set_statedump_path _glfs_set_statedump_path@GFAPI_7.0
+
+_pub_glfs_h_creat_open _glfs_h_creat_open@GFAPI_6.6
diff --git a/api/src/gfapi.map b/api/src/gfapi.map
new file mode 100644
index 00000000000..228ac47c084
--- /dev/null
+++ b/api/src/gfapi.map
@@ -0,0 +1,283 @@
+
+GFAPI_PRIVATE_3.4.0 {
+ global:
+ glfs_loc_touchup;
+ glfs_active_subvol;
+ glfs_subvol_done;
+ glfs_init_done;
+ glfs_resolve_at;
+ local: *;
+};
+
+GFAPI_3.4.0 {
+ global:
+ glfs_new;
+ glfs_set_volfile;
+ glfs_set_volfile_server;
+ glfs_set_logging;
+ glfs_init;
+ glfs_fini;
+ glfs_open;
+ glfs_creat;
+ glfs_close;
+ glfs_from_glfd;
+ glfs_set_xlator_option;
+ glfs_read;
+ glfs_write;
+ glfs_read_async;
+ glfs_write_async;
+ glfs_readv;
+ glfs_writev;
+ glfs_readv_async;
+ glfs_writev_async;
+ glfs_pread;
+ glfs_pwrite;
+ glfs_pread_async;
+ glfs_pwrite_async;
+ glfs_preadv;
+ glfs_pwritev;
+ glfs_preadv_async;
+ glfs_pwritev_async;
+ glfs_lseek;
+ glfs_ftruncate;
+ glfs_ftruncate_async;
+ glfs_lstat;
+ glfs_stat;
+ glfs_fstat;
+ glfs_fsync;
+ glfs_fsync_async;
+ glfs_fdatasync;
+ glfs_fdatasync_async;
+ glfs_access;
+ glfs_symlink;
+ glfs_readlink;
+ glfs_mknod;
+ glfs_mkdir;
+ glfs_unlink;
+ glfs_rmdir;
+ glfs_rename;
+ glfs_link;
+ glfs_opendir;
+ glfs_readdir_r;
+ glfs_readdirplus_r;
+ glfs_telldir;
+ glfs_seekdir;
+ glfs_closedir;
+ glfs_statvfs;
+ glfs_chmod;
+ glfs_fchmod;
+ glfs_chown;
+ glfs_lchown;
+ glfs_fchown;
+ glfs_utimens;
+ glfs_lutimens;
+ glfs_futimens;
+ glfs_getxattr;
+ glfs_lgetxattr;
+ glfs_fgetxattr;
+ glfs_listxattr;
+ glfs_llistxattr;
+ glfs_flistxattr;
+ glfs_setxattr;
+ glfs_lsetxattr;
+ glfs_fsetxattr;
+ glfs_removexattr;
+ glfs_lremovexattr;
+ glfs_fremovexattr;
+ glfs_getcwd;
+ glfs_chdir;
+ glfs_fchdir;
+ glfs_realpath;
+ glfs_posix_lock;
+ glfs_dup;
+} GFAPI_PRIVATE_3.4.0;
+
+GFAPI_3.4.2 {
+ global:
+ glfs_setfsuid;
+ glfs_setfsgid;
+ glfs_setfsgroups;
+ glfs_h_creat;
+ glfs_h_mkdir;
+ glfs_h_mknod;
+ glfs_h_symlink;
+ glfs_h_unlink;
+ glfs_h_close;
+ glfs_h_truncate;
+ glfs_h_stat;
+ glfs_h_getattrs;
+ glfs_h_setattrs;
+ glfs_h_readlink;
+ glfs_h_link;
+ glfs_h_rename;
+ glfs_h_extract_handle;
+ glfs_h_create_from_handle;
+ glfs_h_opendir;
+ glfs_h_open;
+ glfs_h_lookupat;
+} GFAPI_3.4.0;
+
+GFAPI_3.5.0 {
+ global:
+ glfs_get_volumeid;
+ glfs_readdir;
+ glfs_readdirplus;
+ glfs_fallocate;
+ glfs_discard;
+ glfs_discard_async;
+ glfs_zerofill;
+ glfs_zerofill_async;
+ glfs_caller_specific_init;
+ glfs_h_setxattrs;
+} GFAPI_3.4.2;
+
+GFAPI_3.5.1 {
+ global:
+ glfs_unset_volfile_server;
+ glfs_h_getxattrs;
+ glfs_h_removexattrs;
+} GFAPI_3.5.0;
+
+GFAPI_3.6.0 {
+ global:
+ glfs_get_volfile;
+ glfs_h_access;
+} GFAPI_3.5.1;
+
+GFAPI_3.7.0 {
+ global:
+ glfs_h_poll_upcall;
+ glfs_h_acl_set;
+ glfs_h_acl_get;
+ glfs_h_statfs;
+ glfs_h_anonymous_read;
+ glfs_h_anonymous_write;
+} GFAPI_3.6.0;
+
+GFAPI_PRIVATE_3.7.0 {
+ global:
+ glfs_free_from_ctx;
+ glfs_new_from_ctx;
+ glfs_resolve;
+ glfs_process_upcall_event;
+} GFAPI_3.7.0;
+
+GFAPI_3.7.4 {
+ global:
+ glfs_h_lookupat;
+} GFAPI_PRIVATE_3.7.0;
+
+GFAPI_3.7.15 {
+ global:
+ glfs_truncate;
+} GFAPI_3.7.4;
+
+GFAPI_3.7.16 {
+ global:
+ glfs_free;
+ glfs_upcall_get_fs;
+ glfs_upcall_get_reason;
+ glfs_upcall_get_event;
+ glfs_upcall_inode_get_object;
+ glfs_upcall_inode_get_flags;
+ glfs_upcall_inode_get_stat;
+ glfs_upcall_inode_get_expire;
+ glfs_upcall_inode_get_pobject;
+ glfs_upcall_inode_get_pstat;
+ glfs_upcall_inode_get_oldpobject;
+ glfs_upcall_inode_get_oldpstat;
+ glfs_h_poll_upcall;
+} GFAPI_3.7.15;
+
+GFAPI_3.7.17 {
+ global:
+ glfs_realpath;
+} GFAPI_3.7.16;
+
+GFAPI_3.10.0 {
+ global:
+ glfs_sysrq;
+} GFAPI_3.7.17;
+
+GFAPI_3.10.7 {
+ global:
+ glfs_fd_set_lkowner;
+} GFAPI_3.10.0;
+
+GFAPI_3.11.0 {
+ glfs_xreaddirplus_r;
+ glfs_xreaddirplus_r_get_stat;
+ glfs_xreaddirplus_r_get_object;
+ glfs_object_copy;
+} GFAPI_3.10.7;
+
+GFAPI_PRIVATE_3.12.0 {
+ global:
+ glfs_ipc;
+} GFAPI_3.11.0;
+
+GFAPI_3.13.0 {
+ global:
+ glfs_upcall_register;
+ glfs_upcall_unregister;
+} GFAPI_PRIVATE_3.12.0;
+
+GFAPI_4.0.0 {
+ global:
+ glfs_setfsleaseid;
+ glfs_file_lock;
+ glfs_lease;
+ glfs_h_lease;
+} GFAPI_3.13.0;
+
+GFAPI_4.1.6 {
+ global:
+ glfs_upcall_lease_get_object;
+ glfs_upcall_lease_get_lease_type;
+} GFAPI_4.0.0;
+
+GFAPI_PRIVATE_6.0 {
+ global:
+ glfs_statx;
+ glfs_iatt_from_statx;
+} GFAPI_4.1.6;
+
+GFAPI_6.0 {
+ global:
+ glfs_read_async;
+ glfs_write_async;
+ glfs_readv_async;
+ glfs_writev_async;
+ glfs_pread;
+ glfs_pwrite;
+ glfs_pread_async;
+ glfs_pwrite_async;
+ glfs_preadv_async;
+ glfs_pwritev_async;
+ glfs_fsync;
+ glfs_fsync_async;
+ glfs_fdatasync;
+ glfs_fdatasync_async;
+ glfs_ftruncate;
+ glfs_ftruncate_async;
+ glfs_discard_async;
+ glfs_zerofill_async;
+ glfs_copy_file_range;
+ glfs_setattr;
+ glfs_fsetattr;
+} GFAPI_PRIVATE_6.0;
+
+GFAPI_PRIVATE_6.1 {
+ global:
+ glfs_setfspid;
+} GFAPI_6.0;
+
+GFAPI_6.6 {
+ global:
+ glfs_h_creat_open;
+} GFAPI_PRIVATE_6.1;
+
+GFAPI_7.0 {
+ global:
+ glfs_set_statedump_path;
+} GFAPI_6.6;
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
new file mode 100644
index 00000000000..6aa3c5602d1
--- /dev/null
+++ b/api/src/glfs-fops.c
@@ -0,0 +1,6445 @@
+
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+/* for SEEK_HOLE and SEEK_DATA */
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <unistd.h>
+
+#include "glfs-internal.h"
+#include "glfs-mem-types.h"
+#include <glusterfs/syncop.h>
+#include "glfs.h"
+#include "gfapi-messages.h"
+#include <glusterfs/compat-errno.h>
+#include <limits.h>
+#include "glusterfs3.h"
+#include <glusterfs/iatt.h>
+
+#ifdef NAME_MAX
+#define GF_NAME_MAX NAME_MAX
+#else
+#define GF_NAME_MAX 255
+#endif
+
+struct upcall_syncop_args {
+ struct glfs *fs;
+ struct gf_upcall upcall_data;
+};
+
+#define READDIRBUF_SIZE (sizeof(struct dirent) + GF_NAME_MAX + 1)
+
+typedef void (*glfs_io_cbk34)(glfs_fd_t *fd, ssize_t ret, void *data);
+
+/*
+ * This function will mark glfd for deletion and decrement its refcount.
+ */
+int
+glfs_mark_glfd_for_deletion(struct glfs_fd *glfd)
+{
+ LOCK(&glfd->lock);
+ {
+ glfd->state = GLFD_CLOSE;
+ }
+ UNLOCK(&glfd->lock);
+
+ GF_REF_PUT(glfd);
+
+ return 0;
+}
+
+/* This function is useful for all async fops. There is chance that glfd is
+ * closed before async fop is completed. When glfd is closed we change the
+ * state to GLFD_CLOSE.
+ *
+ * This function will return _gf_true if the glfd is still valid else return
+ * _gf_false.
+ */
+gf_boolean_t
+glfs_is_glfd_still_valid(struct glfs_fd *glfd)
+{
+ gf_boolean_t ret = _gf_false;
+
+ LOCK(&glfd->lock);
+ {
+ if (glfd->state != GLFD_CLOSE)
+ ret = _gf_true;
+ }
+ UNLOCK(&glfd->lock);
+
+ return ret;
+}
+
+void
+glfd_set_state_bind(struct glfs_fd *glfd)
+{
+ LOCK(&glfd->lock);
+ {
+ glfd->state = GLFD_OPEN;
+ }
+ UNLOCK(&glfd->lock);
+
+ fd_bind(glfd->fd);
+ glfs_fd_bind(glfd);
+
+ return;
+}
+
+/*
+ * This routine is called when an upcall event of type
+ * 'GF_UPCALL_CACHE_INVALIDATION' is received.
+ * It makes a copy of the contents of the upcall cache-invalidation
+ * data received into an entry which is stored in the upcall list
+ * maintained by gfapi.
+ */
+int
+glfs_get_upcall_cache_invalidation(struct gf_upcall *to_up_data,
+ struct gf_upcall *from_up_data)
+{
+ struct gf_upcall_cache_invalidation *ca_data = NULL;
+ struct gf_upcall_cache_invalidation *f_ca_data = NULL;
+ int ret = -1;
+
+ GF_VALIDATE_OR_GOTO(THIS->name, to_up_data, out);
+ GF_VALIDATE_OR_GOTO(THIS->name, from_up_data, out);
+
+ f_ca_data = from_up_data->data;
+ GF_VALIDATE_OR_GOTO(THIS->name, f_ca_data, out);
+
+ ca_data = GF_CALLOC(1, sizeof(*ca_data), glfs_mt_upcall_entry_t);
+
+ if (!ca_data) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ to_up_data->data = ca_data;
+
+ ca_data->flags = f_ca_data->flags;
+ ca_data->expire_time_attr = f_ca_data->expire_time_attr;
+ ca_data->stat = f_ca_data->stat;
+ ca_data->p_stat = f_ca_data->p_stat;
+ ca_data->oldp_stat = f_ca_data->oldp_stat;
+
+ ret = 0;
+out:
+ return ret;
+}
+
+int
+glfs_get_upcall_lease(struct gf_upcall *to_up_data,
+ struct gf_upcall *from_up_data)
+{
+ struct gf_upcall_recall_lease *ca_data = NULL;
+ struct gf_upcall_recall_lease *f_ca_data = NULL;
+ int ret = -1;
+
+ GF_VALIDATE_OR_GOTO(THIS->name, to_up_data, out);
+ GF_VALIDATE_OR_GOTO(THIS->name, from_up_data, out);
+
+ f_ca_data = from_up_data->data;
+ GF_VALIDATE_OR_GOTO(THIS->name, f_ca_data, out);
+
+ ca_data = GF_CALLOC(1, sizeof(*ca_data), glfs_mt_upcall_entry_t);
+
+ if (!ca_data) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ to_up_data->data = ca_data;
+
+ ca_data->lease_type = f_ca_data->lease_type;
+ gf_uuid_copy(ca_data->tid, f_ca_data->tid);
+ ca_data->dict = f_ca_data->dict;
+
+ ret = 0;
+out:
+ return ret;
+}
+int
+glfs_loc_link(loc_t *loc, struct iatt *iatt)
+{
+ int ret = -1;
+ inode_t *old_inode = NULL;
+ uint64_t ctx_value = LOOKUP_NOT_NEEDED;
+
+ if (!loc->inode) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ old_inode = loc->inode;
+
+ /* If the inode already exists in the cache, the inode
+ * returned here points to the existing one. We need
+ * to update loc.inode accordingly.
+ */
+ loc->inode = inode_link(loc->inode, loc->parent, loc->name, iatt);
+ if (loc->inode) {
+ inode_ctx_set(loc->inode, THIS, &ctx_value);
+ inode_lookup(loc->inode);
+ inode_unref(old_inode);
+ ret = 0;
+ } else {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+void
+glfs_iatt_to_stat(struct glfs *fs, struct iatt *iatt, struct stat *stat)
+{
+ iatt_to_stat(iatt, stat);
+ stat->st_dev = fs->dev_id;
+}
+
+void
+glfs_iatt_to_statx(struct glfs *fs, const struct iatt *iatt,
+ struct glfs_stat *statx)
+{
+ statx->glfs_st_mask = 0;
+
+ statx->glfs_st_mode = 0;
+ if (IATT_TYPE_VALID(iatt->ia_flags)) {
+ statx->glfs_st_mode |= st_mode_type_from_ia(iatt->ia_type);
+ statx->glfs_st_mask |= GLFS_STAT_TYPE;
+ }
+
+ if (IATT_MODE_VALID(iatt->ia_flags)) {
+ statx->glfs_st_mode |= st_mode_prot_from_ia(iatt->ia_prot);
+ statx->glfs_st_mask |= GLFS_STAT_MODE;
+ }
+
+ if (IATT_NLINK_VALID(iatt->ia_flags)) {
+ statx->glfs_st_nlink = iatt->ia_nlink;
+ statx->glfs_st_mask |= GLFS_STAT_NLINK;
+ }
+
+ if (IATT_UID_VALID(iatt->ia_flags)) {
+ statx->glfs_st_uid = iatt->ia_uid;
+ statx->glfs_st_mask |= GLFS_STAT_UID;
+ }
+
+ if (IATT_GID_VALID(iatt->ia_flags)) {
+ statx->glfs_st_gid = iatt->ia_gid;
+ statx->glfs_st_mask |= GLFS_STAT_GID;
+ }
+
+ if (IATT_ATIME_VALID(iatt->ia_flags)) {
+ statx->glfs_st_atime.tv_sec = iatt->ia_atime;
+ statx->glfs_st_atime.tv_nsec = iatt->ia_atime_nsec;
+ statx->glfs_st_mask |= GLFS_STAT_ATIME;
+ }
+
+ if (IATT_MTIME_VALID(iatt->ia_flags)) {
+ statx->glfs_st_mtime.tv_sec = iatt->ia_mtime;
+ statx->glfs_st_mtime.tv_nsec = iatt->ia_mtime_nsec;
+ statx->glfs_st_mask |= GLFS_STAT_MTIME;
+ }
+
+ if (IATT_CTIME_VALID(iatt->ia_flags)) {
+ statx->glfs_st_ctime.tv_sec = iatt->ia_ctime;
+ statx->glfs_st_ctime.tv_nsec = iatt->ia_ctime_nsec;
+ statx->glfs_st_mask |= GLFS_STAT_CTIME;
+ }
+
+ if (IATT_BTIME_VALID(iatt->ia_flags)) {
+ statx->glfs_st_btime.tv_sec = iatt->ia_btime;
+ statx->glfs_st_btime.tv_nsec = iatt->ia_btime_nsec;
+ statx->glfs_st_mask |= GLFS_STAT_BTIME;
+ }
+
+ if (IATT_INO_VALID(iatt->ia_flags)) {
+ statx->glfs_st_ino = iatt->ia_ino;
+ statx->glfs_st_mask |= GLFS_STAT_INO;
+ }
+
+ if (IATT_SIZE_VALID(iatt->ia_flags)) {
+ statx->glfs_st_size = iatt->ia_size;
+ statx->glfs_st_mask |= GLFS_STAT_SIZE;
+ }
+
+ if (IATT_BLOCKS_VALID(iatt->ia_flags)) {
+ statx->glfs_st_blocks = iatt->ia_blocks;
+ statx->glfs_st_mask |= GLFS_STAT_BLOCKS;
+ }
+
+ /* unconditionally present, encode as is */
+ statx->glfs_st_blksize = iatt->ia_blksize;
+ statx->glfs_st_rdev_major = ia_major(iatt->ia_rdev);
+ statx->glfs_st_rdev_minor = ia_minor(iatt->ia_rdev);
+ statx->glfs_st_dev_major = ia_major(fs->dev_id);
+ statx->glfs_st_dev_minor = ia_minor(fs->dev_id);
+
+ /* At present we do not read any localFS attributes and pass them along,
+ * so setting this to 0. As we start supporting file attributes we can
+ * populate the same here as well */
+ statx->glfs_st_attributes = 0;
+ statx->glfs_st_attributes_mask = 0;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_iatt_from_statx, 6.0)
+void
+priv_glfs_iatt_from_statx(struct iatt *iatt, const struct glfs_stat *statx)
+{
+ /* Most code in xlators are not checking validity flags before accessing
+ the items. Hence zero everything before setting valid items */
+ memset(iatt, 0, sizeof(struct iatt));
+
+ if (GLFS_STAT_TYPE_VALID(statx->glfs_st_mask)) {
+ iatt->ia_type = ia_type_from_st_mode(statx->glfs_st_mode);
+ iatt->ia_flags |= IATT_TYPE;
+ }
+
+ if (GLFS_STAT_MODE_VALID(statx->glfs_st_mask)) {
+ iatt->ia_prot = ia_prot_from_st_mode(statx->glfs_st_mode);
+ iatt->ia_flags |= IATT_MODE;
+ }
+
+ if (GLFS_STAT_NLINK_VALID(statx->glfs_st_mask)) {
+ iatt->ia_nlink = statx->glfs_st_nlink;
+ iatt->ia_flags |= IATT_NLINK;
+ }
+
+ if (GLFS_STAT_UID_VALID(statx->glfs_st_mask)) {
+ iatt->ia_uid = statx->glfs_st_uid;
+ iatt->ia_flags |= IATT_UID;
+ }
+
+ if (GLFS_STAT_GID_VALID(statx->glfs_st_mask)) {
+ iatt->ia_gid = statx->glfs_st_gid;
+ iatt->ia_flags |= IATT_GID;
+ }
+
+ if (GLFS_STAT_ATIME_VALID(statx->glfs_st_mask)) {
+ iatt->ia_atime = statx->glfs_st_atime.tv_sec;
+ iatt->ia_atime_nsec = statx->glfs_st_atime.tv_nsec;
+ iatt->ia_flags |= IATT_ATIME;
+ }
+
+ if (GLFS_STAT_MTIME_VALID(statx->glfs_st_mask)) {
+ iatt->ia_mtime = statx->glfs_st_mtime.tv_sec;
+ iatt->ia_mtime_nsec = statx->glfs_st_mtime.tv_nsec;
+ iatt->ia_flags |= IATT_MTIME;
+ }
+
+ if (GLFS_STAT_CTIME_VALID(statx->glfs_st_mask)) {
+ iatt->ia_ctime = statx->glfs_st_ctime.tv_sec;
+ iatt->ia_ctime_nsec = statx->glfs_st_ctime.tv_nsec;
+ iatt->ia_flags |= IATT_CTIME;
+ }
+
+ if (GLFS_STAT_BTIME_VALID(statx->glfs_st_mask)) {
+ iatt->ia_btime = statx->glfs_st_btime.tv_sec;
+ iatt->ia_btime_nsec = statx->glfs_st_btime.tv_nsec;
+ iatt->ia_flags |= IATT_BTIME;
+ }
+
+ if (GLFS_STAT_INO_VALID(statx->glfs_st_mask)) {
+ iatt->ia_ino = statx->glfs_st_ino;
+ iatt->ia_flags |= IATT_INO;
+ }
+
+ if (GLFS_STAT_SIZE_VALID(statx->glfs_st_mask)) {
+ iatt->ia_size = statx->glfs_st_size;
+ iatt->ia_flags |= IATT_SIZE;
+ }
+
+ if (GLFS_STAT_BLOCKS_VALID(statx->glfs_st_mask)) {
+ iatt->ia_blocks = statx->glfs_st_blocks;
+ iatt->ia_flags |= IATT_BLOCKS;
+ }
+
+ /* unconditionally present, encode as is */
+ iatt->ia_blksize = statx->glfs_st_blksize;
+ iatt->ia_rdev = makedev(statx->glfs_st_rdev_major,
+ statx->glfs_st_rdev_minor);
+ iatt->ia_dev = makedev(statx->glfs_st_dev_major, statx->glfs_st_dev_minor);
+ iatt->ia_attributes = statx->glfs_st_attributes;
+ iatt->ia_attributes_mask = statx->glfs_st_attributes_mask;
+}
+
+void
+glfsflags_from_gfapiflags(struct glfs_stat *stat, int *glvalid)
+{
+ *glvalid = 0;
+ if (stat->glfs_st_mask & GLFS_STAT_MODE) {
+ *glvalid |= GF_SET_ATTR_MODE;
+ }
+
+ if (stat->glfs_st_mask & GLFS_STAT_SIZE) {
+ *glvalid |= GF_SET_ATTR_SIZE;
+ }
+
+ if (stat->glfs_st_mask & GLFS_STAT_UID) {
+ *glvalid |= GF_SET_ATTR_UID;
+ }
+
+ if (stat->glfs_st_mask & GLFS_STAT_GID) {
+ *glvalid |= GF_SET_ATTR_GID;
+ }
+
+ if (stat->glfs_st_mask & GLFS_STAT_ATIME) {
+ *glvalid |= GF_SET_ATTR_ATIME;
+ }
+
+ if (stat->glfs_st_mask & GLFS_STAT_MTIME) {
+ *glvalid |= GF_SET_ATTR_MTIME;
+ }
+}
+
+int
+glfs_loc_unlink(loc_t *loc)
+{
+ inode_unlink(loc->inode, loc->parent, loc->name);
+
+ /* since glfs_h_* objects hold a reference to inode
+ * it is safe to keep lookup count to '0' */
+ if (!inode_has_dentry(loc->inode))
+ inode_forget(loc->inode, 0);
+
+ return 0;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_open, 3.4.0)
+struct glfs_fd *
+pub_glfs_open(struct glfs *fs, const char *path, int flags)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd)
+ goto out;
+
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (IA_ISDIR(iatt.ia_type)) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ if (!IA_ISREG(iatt.ia_type)) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (glfd->fd) {
+ /* Retry. Safe to touch glfd->fd as we
+ still have not glfs_fd_bind() yet.
+ */
+ fd_unref(glfd->fd);
+ glfd->fd = NULL;
+ }
+
+ glfd->fd = fd_create(loc.inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ glfd->fd->flags = flags;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_open(subvol, &loc, flags, glfd->fd, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ glfd = NULL;
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return glfd;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_close, 3.4.0)
+int
+pub_glfs_close(struct glfs_fd *glfd)
+{
+ xlator_t *subvol = NULL;
+ int ret = -1;
+ fd_t *fd = NULL;
+ struct glfs *fs = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ if (glfd->lk_owner.len != 0) {
+ ret = syncopctx_setfslkowner(&glfd->lk_owner);
+ if (ret)
+ goto out;
+ }
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_flush(subvol, fd, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ fs = glfd->fs;
+
+ if (fd)
+ fd_unref(fd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_mark_glfd_for_deletion(glfd);
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lstat, 3.4.0)
+int
+pub_glfs_lstat(struct glfs *fs, const char *path, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0 && stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_stat, 3.4.0)
+int
+pub_glfs_stat(struct glfs *fs, const char *path, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0 && stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_statx, 6.0)
+int
+priv_glfs_statx(struct glfs *fs, const char *path, const unsigned int mask,
+ struct glfs_stat *statxbuf)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (path == NULL) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (mask & ~GLFS_STAT_ALL) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0 && statxbuf)
+ glfs_iatt_to_statx(fs, &iatt, statxbuf);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fstat, 3.4.0)
+int
+pub_glfs_fstat(struct glfs_fd *glfd, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ struct iatt iatt = {
+ 0,
+ };
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = syncop_fstat(subvol, fd, &iatt, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret == 0 && stat)
+ glfs_iatt_to_stat(glfd->fs, &iatt, stat);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_creat, 3.4.0)
+struct glfs_fd *
+pub_glfs_creat(struct glfs *fs, const char *path, int flags, mode_t mode)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd)
+ goto out;
+
+ /* This must be glfs_resolve() and NOT glfs_lresolve().
+ That is because open("name", O_CREAT) where "name"
+ is a danging symlink must create the dangling
+ destination.
+ */
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == -1 && errno != ENOENT)
+ /* Any other type of error is fatal */
+ goto out;
+
+ if (ret == -1 && errno == ENOENT && !loc.parent)
+ /* The parent directory or an ancestor even
+ higher does not exist
+ */
+ goto out;
+
+ if (loc.inode) {
+ if (flags & O_EXCL) {
+ ret = -1;
+ errno = EEXIST;
+ goto out;
+ }
+
+ if (IA_ISDIR(iatt.ia_type)) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ if (!IA_ISREG(iatt.ia_type)) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+ }
+
+ if (ret == -1 && errno == ENOENT) {
+ loc.inode = inode_new(loc.parent->table);
+ if (!loc.inode) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ if (glfd->fd) {
+ /* Retry. Safe to touch glfd->fd as we
+ still have not glfs_fd_bind() yet.
+ */
+ fd_unref(glfd->fd);
+ glfd->fd = NULL;
+ }
+
+ glfd->fd = fd_create(loc.inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ glfd->fd->flags = flags;
+
+ if (get_fop_attr_thrd_key(&xattr_req))
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+ if (ret == 0) {
+ ret = syncop_open(subvol, &loc, flags, glfd->fd, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ } else {
+ ret = syncop_create(subvol, &loc, flags, mode, glfd->fd, &iatt,
+ xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ }
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_link(&loc, &iatt);
+out:
+ loc_wipe(&loc);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ glfd = NULL;
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return glfd;
+}
+
+#ifdef HAVE_SEEK_HOLE
+static int
+glfs_seek(struct glfs_fd *glfd, off_t offset, int whence)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ gf_seek_what_t what = 0;
+ off_t off = -1;
+
+ switch (whence) {
+ case SEEK_DATA:
+ what = GF_SEEK_DATA;
+ break;
+ case SEEK_HOLE:
+ what = GF_SEEK_HOLE;
+ break;
+ default:
+ /* other SEEK_* do not make sense, all operations get an offset
+ * and the position in the fd is not tracked */
+ errno = EINVAL;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto done;
+ }
+
+ ret = syncop_seek(subvol, fd, offset, what, NULL, &off);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret != -1)
+ glfd->offset = off;
+
+done:
+ if (fd)
+ fd_unref(fd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+out:
+ return ret;
+}
+#endif
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lseek, 3.4.0)
+off_t
+pub_glfs_lseek(struct glfs_fd *glfd, off_t offset, int whence)
+{
+ struct stat sb = {
+ 0,
+ };
+ int ret = -1;
+ off_t off = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ switch (whence) {
+ case SEEK_SET:
+ glfd->offset = offset;
+ ret = 0;
+ break;
+ case SEEK_CUR:
+ glfd->offset += offset;
+ ret = 0;
+ break;
+ case SEEK_END:
+ ret = pub_glfs_fstat(glfd, &sb);
+ if (ret) {
+ /* seek cannot fail :O */
+ break;
+ }
+ glfd->offset = sb.st_size + offset;
+ break;
+#ifdef HAVE_SEEK_HOLE
+ case SEEK_DATA:
+ case SEEK_HOLE:
+ ret = glfs_seek(glfd, offset, whence);
+ break;
+#endif
+ default:
+ errno = EINVAL;
+ }
+
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ __GLFS_EXIT_FS;
+
+ if (ret != -1)
+ off = glfd->offset;
+
+ return off;
+
+invalid_fs:
+ return -1;
+}
+
+static ssize_t
+glfs_preadv_common(struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
+ off_t offset, int flags, struct glfs_stat *poststat)
+{
+ xlator_t *subvol = NULL;
+ ssize_t ret = -1;
+ ssize_t size = -1;
+ struct iovec *iov = NULL;
+ int cnt = 0;
+ struct iobref *iobref = NULL;
+ fd_t *fd = NULL;
+ struct iatt iatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ size = iov_length(iovec, iovcnt);
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_readv(subvol, fd, size, offset, 0, &iov, &cnt, &iobref, &iatt,
+ fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0 && poststat)
+ glfs_iatt_to_statx(glfd->fs, &iatt, poststat);
+
+ if (ret <= 0)
+ goto out;
+
+ size = iov_copy(iovec, iovcnt, iov, cnt); /* FIXME!!! */
+
+ glfd->offset = (offset + size);
+
+ ret = size;
+out:
+ if (iov)
+ GF_FREE(iov);
+ if (iobref)
+ iobref_unref(iobref);
+
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_preadv, 3.4.0)
+ssize_t
+pub_glfs_preadv(struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
+ off_t offset, int flags)
+{
+ return glfs_preadv_common(glfd, iovec, iovcnt, offset, flags, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_read, 3.4.0)
+ssize_t
+pub_glfs_read(struct glfs_fd *glfd, void *buf, size_t count, int flags)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = pub_glfs_preadv(glfd, &iov, 1, glfd->offset, flags);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_pread34, glfs_pread, 3.4.0)
+ssize_t
+pub_glfs_pread34(struct glfs_fd *glfd, void *buf, size_t count, off_t offset,
+ int flags)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = pub_glfs_preadv(glfd, &iov, 1, offset, flags);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pread, 6.0)
+ssize_t
+pub_glfs_pread(struct glfs_fd *glfd, void *buf, size_t count, off_t offset,
+ int flags, struct glfs_stat *poststat)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = glfs_preadv_common(glfd, &iov, 1, offset, flags, poststat);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readv, 3.4.0)
+ssize_t
+pub_glfs_readv(struct glfs_fd *glfd, const struct iovec *iov, int count,
+ int flags)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = pub_glfs_preadv(glfd, iov, count, glfd->offset, flags);
+
+ return ret;
+}
+
+struct glfs_io {
+ struct glfs_fd *glfd;
+ int op;
+ off_t offset;
+ struct iovec *iov;
+ int count;
+ int flags;
+ gf_boolean_t oldcb;
+ union {
+ glfs_io_cbk34 fn34;
+ glfs_io_cbk fn;
+ };
+ void *data;
+};
+
+static int
+glfs_io_async_cbk(int op_ret, int op_errno, call_frame_t *frame, void *cookie,
+ struct iovec *iovec, int count, struct iatt *prebuf,
+ struct iatt *postbuf)
+{
+ struct glfs_io *gio = NULL;
+ xlator_t *subvol = NULL;
+ struct glfs *fs = NULL;
+ struct glfs_fd *glfd = NULL;
+ int ret = -1;
+ struct glfs_stat prestat = {}, *prestatp = NULL;
+ struct glfs_stat poststat = {}, *poststatp = NULL;
+
+ GF_VALIDATE_OR_GOTO("gfapi", frame, inval);
+ GF_VALIDATE_OR_GOTO("gfapi", cookie, inval);
+
+ gio = frame->local;
+ frame->local = NULL;
+ subvol = cookie;
+ glfd = gio->glfd;
+ fs = glfd->fs;
+
+ if (!glfs_is_glfd_still_valid(glfd))
+ goto err;
+
+ if (op_ret <= 0) {
+ goto out;
+ } else if (gio->op == GF_FOP_READ) {
+ if (!iovec) {
+ op_ret = -1;
+ op_errno = EINVAL;
+ goto out;
+ }
+
+ op_ret = iov_copy(gio->iov, gio->count, iovec, count);
+ glfd->offset = gio->offset + op_ret;
+ } else if (gio->op == GF_FOP_WRITE) {
+ glfd->offset = gio->offset + gio->iov->iov_len;
+ }
+
+out:
+ errno = op_errno;
+ if (gio->oldcb) {
+ gio->fn34(gio->glfd, op_ret, gio->data);
+ } else {
+ if (prebuf) {
+ prestatp = &prestat;
+ glfs_iatt_to_statx(fs, prebuf, prestatp);
+ }
+
+ if (postbuf) {
+ poststatp = &poststat;
+ glfs_iatt_to_statx(fs, postbuf, poststatp);
+ }
+
+ gio->fn(gio->glfd, op_ret, prestatp, poststatp, gio->data);
+ }
+err:
+ fd_unref(glfd->fd);
+ /* Since the async operation is complete
+ * release the ref taken during the start
+ * of async operation
+ */
+ GF_REF_PUT(glfd);
+
+ GF_FREE(gio->iov);
+ GF_FREE(gio);
+ STACK_DESTROY(frame->root);
+ glfs_subvol_done(fs, subvol);
+
+ ret = 0;
+inval:
+ return ret;
+}
+
+static int
+glfs_preadv_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iovec *iovec, int count,
+ struct iatt *stbuf, struct iobref *iobref, dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, iovec, count, NULL,
+ stbuf);
+
+ return 0;
+}
+
+static int
+glfs_preadv_async_common(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags, gf_boolean_t oldcb,
+ glfs_io_cbk fn, void *data)
+{
+ struct glfs_io *gio = NULL;
+ int ret = 0;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ struct glfs *fs = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ fs = glfd->fs;
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->iov = iov_dup(iovec, count);
+ if (!gio->iov) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->op = GF_FOP_READ;
+ gio->glfd = glfd;
+ gio->count = count;
+ gio->offset = offset;
+ gio->flags = flags;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+
+ frame->local = gio;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ STACK_WIND_COOKIE(frame, glfs_preadv_async_cbk, subvol, subvol,
+ subvol->fops->readv, fd, iov_length(iovec, count), offset,
+ flags, fop_attr);
+
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (gio) {
+ GF_FREE(gio->iov);
+ GF_FREE(gio);
+ }
+ if (frame) {
+ STACK_DESTROY(frame->root);
+ }
+ glfs_subvol_done(fs, subvol);
+ }
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ __GLFS_EXIT_FS;
+
+ return ret;
+
+invalid_fs:
+ return -1;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_preadv_async34, glfs_preadv_async, 3.4.0)
+int
+pub_glfs_preadv_async34(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags, glfs_io_cbk34 fn,
+ void *data)
+{
+ return glfs_preadv_async_common(glfd, iovec, count, offset, flags, _gf_true,
+ (void *)fn, data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_preadv_async, 6.0)
+int
+pub_glfs_preadv_async(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags, glfs_io_cbk fn,
+ void *data)
+{
+ return glfs_preadv_async_common(glfd, iovec, count, offset, flags,
+ _gf_false, fn, data);
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_read_async34, glfs_read_async, 3.4.0)
+int
+pub_glfs_read_async34(struct glfs_fd *glfd, void *buf, size_t count, int flags,
+ glfs_io_cbk34 fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = glfs_preadv_async_common(glfd, &iov, 1, glfd->offset, flags, _gf_true,
+ (void *)fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_read_async, 6.0)
+int
+pub_glfs_read_async(struct glfs_fd *glfd, void *buf, size_t count, int flags,
+ glfs_io_cbk fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = glfs_preadv_async_common(glfd, &iov, 1, glfd->offset, flags,
+ _gf_false, fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_pread_async34, glfs_pread_async, 3.4.0)
+int
+pub_glfs_pread_async34(struct glfs_fd *glfd, void *buf, size_t count,
+ off_t offset, int flags, glfs_io_cbk34 fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = glfs_preadv_async_common(glfd, &iov, 1, offset, flags, _gf_true,
+ (void *)fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pread_async, 6.0)
+int
+pub_glfs_pread_async(struct glfs_fd *glfd, void *buf, size_t count,
+ off_t offset, int flags, glfs_io_cbk fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = buf;
+ iov.iov_len = count;
+
+ ret = glfs_preadv_async_common(glfd, &iov, 1, offset, flags, _gf_false, fn,
+ data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_readv_async34, glfs_readv_async, 3.4.0)
+int
+pub_glfs_readv_async34(struct glfs_fd *glfd, const struct iovec *iov, int count,
+ int flags, glfs_io_cbk34 fn, void *data)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = glfs_preadv_async_common(glfd, iov, count, glfd->offset, flags,
+ _gf_true, (void *)fn, data);
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readv_async, 6.0)
+int
+pub_glfs_readv_async(struct glfs_fd *glfd, const struct iovec *iov, int count,
+ int flags, glfs_io_cbk fn, void *data)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = glfs_preadv_async_common(glfd, iov, count, glfd->offset, flags,
+ _gf_false, fn, data);
+ return ret;
+}
+
+static ssize_t
+glfs_pwritev_common(struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
+ off_t offset, int flags, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ xlator_t *subvol = NULL;
+ int ret = -1;
+ struct iobref *iobref = NULL;
+ struct iobuf *iobuf = NULL;
+ struct iovec iov = {
+ 0,
+ };
+ fd_t *fd = NULL;
+ struct iatt preiatt =
+ {
+ 0,
+ },
+ postiatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = iobuf_copy(subvol->ctx->iobuf_pool, iovec, iovcnt, &iobref, &iobuf,
+ &iov);
+ if (ret)
+ goto out;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_writev(subvol, fd, &iov, 1, offset, iobref, flags, &preiatt,
+ &postiatt, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0) {
+ if (prestat)
+ glfs_iatt_to_statx(glfd->fs, &preiatt, prestat);
+ if (poststat)
+ glfs_iatt_to_statx(glfd->fs, &postiatt, poststat);
+ }
+
+ if (ret <= 0)
+ goto out;
+
+ glfd->offset = (offset + iov.iov_len);
+out:
+ if (iobuf)
+ iobuf_unref(iobuf);
+ if (iobref)
+ iobref_unref(iobref);
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_copy_file_range, 6.0)
+ssize_t
+pub_glfs_copy_file_range(struct glfs_fd *glfd_in, off64_t *off_in,
+ struct glfs_fd *glfd_out, off64_t *off_out, size_t len,
+ unsigned int flags, struct glfs_stat *statbuf,
+ struct glfs_stat *prestat, struct glfs_stat *poststat)
+{
+ xlator_t *subvol = NULL;
+ int ret = -1;
+ fd_t *fd_in = NULL;
+ fd_t *fd_out = NULL;
+ struct iatt preiatt =
+ {
+ 0,
+ },
+ iattbuf =
+ {
+ 0,
+ },
+ postiatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+ off64_t pos_in;
+ off64_t pos_out;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd_in, invalid_fs);
+ __GLFS_ENTRY_VALIDATE_FD(glfd_out, invalid_fs);
+
+ GF_REF_GET(glfd_in);
+ GF_REF_GET(glfd_out);
+
+ if (glfd_in->fs != glfd_out->fs) {
+ ret = -1;
+ errno = EXDEV;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(glfd_in->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd_in = glfs_resolve_fd(glfd_in->fs, subvol, glfd_in);
+ if (!fd_in) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ fd_out = glfs_resolve_fd(glfd_out->fs, subvol, glfd_out);
+ if (!fd_out) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ /*
+ * This is based on how the vfs layer in the kernel handles
+ * copy_file_range call. Upon receiving it follows the
+ * below method to consider the offset.
+ * if (off_in != NULL)
+ * use the value off_in to perform the op
+ * else if off_in == NULL
+ * use the current file offset position to perform the op
+ *
+ * For gfapi, glfd->offset is used. For a freshly opened
+ * fd, the offset is set to 0.
+ */
+ if (off_in)
+ pos_in = *off_in;
+ else
+ pos_in = glfd_in->offset;
+
+ if (off_out)
+ pos_out = *off_out;
+ else
+ pos_out = glfd_out->offset;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_copy_file_range(subvol, fd_in, pos_in, fd_out, pos_out, len,
+ flags, &iattbuf, &preiatt, &postiatt, fop_attr,
+ NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0) {
+ pos_in += ret;
+ pos_out += ret;
+
+ if (off_in)
+ *off_in = pos_in;
+ if (off_out)
+ *off_out = pos_out;
+
+ if (statbuf)
+ glfs_iatt_to_statx(glfd_in->fs, &iattbuf, statbuf);
+ if (prestat)
+ glfs_iatt_to_statx(glfd_in->fs, &preiatt, prestat);
+ if (poststat)
+ glfs_iatt_to_statx(glfd_in->fs, &postiatt, poststat);
+ }
+
+ if (ret <= 0)
+ goto out;
+
+ /*
+ * If *off_in is NULL, then there is no offset info that can
+ * obtained from the input argument. Hence follow below method.
+ * If *off_in is NULL, then
+ * glfd->offset = offset + ret;
+ * else
+ * do nothing.
+ *
+ * According to the man page of copy_file_range, if off_in is
+ * NULL, then the offset of the source file is advanced by
+ * the return value of the fop. The same applies to off_out as
+ * well. Otherwise, if *off_in is not NULL, then the offset
+ * is not advanced by the filesystem. The entity which sends
+ * the copy_file_range call is supposed to advance the offset
+ * value in its buffer (pointed to by *off_in or *off_out)
+ * by the return value of copy_file_range.
+ */
+ if (!off_in)
+ glfd_in->offset += ret;
+
+ if (!off_out)
+ glfd_out->offset += ret;
+
+out:
+ if (fd_in)
+ fd_unref(fd_in);
+ if (fd_out)
+ fd_unref(fd_out);
+ if (glfd_in)
+ GF_REF_PUT(glfd_in);
+ if (glfd_out)
+ GF_REF_PUT(glfd_out);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd_in->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwritev, 3.4.0)
+ssize_t
+pub_glfs_pwritev(struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
+ off_t offset, int flags)
+{
+ return glfs_pwritev_common(glfd, iovec, iovcnt, offset, flags, NULL, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_write, 3.4.0)
+ssize_t
+pub_glfs_write(struct glfs_fd *glfd, const void *buf, size_t count, int flags)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = pub_glfs_pwritev(glfd, &iov, 1, glfd->offset, flags);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_writev, 3.4.0)
+ssize_t
+pub_glfs_writev(struct glfs_fd *glfd, const struct iovec *iov, int count,
+ int flags)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = pub_glfs_pwritev(glfd, iov, count, glfd->offset, flags);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_pwrite34, glfs_pwrite, 3.4.0)
+ssize_t
+pub_glfs_pwrite34(struct glfs_fd *glfd, const void *buf, size_t count,
+ off_t offset, int flags)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = pub_glfs_pwritev(glfd, &iov, 1, offset, flags);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwrite, 6.0)
+ssize_t
+pub_glfs_pwrite(struct glfs_fd *glfd, const void *buf, size_t count,
+ off_t offset, int flags, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_pwritev_common(glfd, &iov, 1, offset, flags, prestat, poststat);
+
+ return ret;
+}
+
+extern glfs_t *
+pub_glfs_from_glfd(glfs_fd_t *);
+
+static int
+glfs_pwritev_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int op_ret, int op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, NULL, 0, prebuf,
+ postbuf);
+
+ return 0;
+}
+
+static int
+glfs_pwritev_async_common(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags,
+ gf_boolean_t oldcb, glfs_io_cbk fn, void *data)
+{
+ struct glfs_io *gio = NULL;
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct iobref *iobref = NULL;
+ struct iobuf *iobuf = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->op = GF_FOP_WRITE;
+ gio->glfd = glfd;
+ gio->offset = offset;
+ gio->flags = flags;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+ gio->count = 1;
+ gio->iov = GF_CALLOC(gio->count, sizeof(*(gio->iov)), gf_common_mt_iovec);
+ if (!gio->iov) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = iobuf_copy(subvol->ctx->iobuf_pool, iovec, count, &iobref, &iobuf,
+ gio->iov);
+ if (ret)
+ goto out;
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ frame->local = gio;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ STACK_WIND_COOKIE(frame, glfs_pwritev_async_cbk, subvol, subvol,
+ subvol->fops->writev, fd, gio->iov, gio->count, offset,
+ flags, iobref, fop_attr);
+
+ ret = 0;
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ GF_FREE(gio);
+ /*
+ * If there is any error condition check after the frame
+ * creation, we have to destroy the frame root.
+ */
+ glfs_subvol_done(glfd->fs, subvol);
+ }
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ if (iobuf)
+ iobuf_unref(iobuf);
+ if (iobref)
+ iobref_unref(iobref);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_pwritev_async34, glfs_pwritev_async, 3.4.0)
+int
+pub_glfs_pwritev_async34(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags, glfs_io_cbk34 fn,
+ void *data)
+{
+ return glfs_pwritev_async_common(glfd, iovec, count, offset, flags,
+ _gf_true, (void *)fn, data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwritev_async, 6.0)
+int
+pub_glfs_pwritev_async(struct glfs_fd *glfd, const struct iovec *iovec,
+ int count, off_t offset, int flags, glfs_io_cbk fn,
+ void *data)
+{
+ return glfs_pwritev_async_common(glfd, iovec, count, offset, flags,
+ _gf_false, fn, data);
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_write_async34, glfs_write_async, 3.4.0)
+int
+pub_glfs_write_async34(struct glfs_fd *glfd, const void *buf, size_t count,
+ int flags, glfs_io_cbk34 fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_pwritev_async_common(glfd, &iov, 1, glfd->offset, flags,
+ _gf_true, (void *)fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_write_async, 6.0)
+int
+pub_glfs_write_async(struct glfs_fd *glfd, const void *buf, size_t count,
+ int flags, glfs_io_cbk fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_pwritev_async_common(glfd, &iov, 1, glfd->offset, flags,
+ _gf_false, fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_pwrite_async34, glfs_pwrite_async, 3.4.0)
+int
+pub_glfs_pwrite_async34(struct glfs_fd *glfd, const void *buf, int count,
+ off_t offset, int flags, glfs_io_cbk34 fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_pwritev_async_common(glfd, &iov, 1, offset, flags, _gf_true,
+ (void *)fn, data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_pwrite_async, 6.0)
+int
+pub_glfs_pwrite_async(struct glfs_fd *glfd, const void *buf, int count,
+ off_t offset, int flags, glfs_io_cbk fn, void *data)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_pwritev_async_common(glfd, &iov, 1, offset, flags, _gf_false, fn,
+ data);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_writev_async34, glfs_writev_async, 3.4.0)
+int
+pub_glfs_writev_async34(struct glfs_fd *glfd, const struct iovec *iov,
+ int count, int flags, glfs_io_cbk34 fn, void *data)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = glfs_pwritev_async_common(glfd, iov, count, glfd->offset, flags,
+ _gf_true, (void *)fn, data);
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_writev_async, 6.0)
+int
+pub_glfs_writev_async(struct glfs_fd *glfd, const struct iovec *iov, int count,
+ int flags, glfs_io_cbk fn, void *data)
+{
+ ssize_t ret = 0;
+
+ if (glfd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ ret = glfs_pwritev_async_common(glfd, iov, count, glfd->offset, flags,
+ _gf_false, fn, data);
+ return ret;
+}
+
+static int
+glfs_fsync_common(struct glfs_fd *glfd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct iatt preiatt =
+ {
+ 0,
+ },
+ postiatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_fsync(subvol, fd, 0, &preiatt, &postiatt, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0) {
+ if (prestat)
+ glfs_iatt_to_statx(glfd->fs, &preiatt, prestat);
+ if (poststat)
+ glfs_iatt_to_statx(glfd->fs, &postiatt, poststat);
+ }
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_fsync34, glfs_fsync, 3.4.0)
+int
+pub_glfs_fsync34(struct glfs_fd *glfd)
+{
+ return glfs_fsync_common(glfd, NULL, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsync, 6.0)
+int
+pub_glfs_fsync(struct glfs_fd *glfd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ return glfs_fsync_common(glfd, prestat, poststat);
+}
+
+static int
+glfs_fsync_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, NULL, 0, prebuf,
+ postbuf);
+
+ return 0;
+}
+
+static int
+glfs_fsync_async_common(struct glfs_fd *glfd, gf_boolean_t oldcb,
+ glfs_io_cbk fn, void *data, int dataonly)
+{
+ struct glfs_io *gio = NULL;
+ int ret = 0;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ gio->op = GF_FOP_FSYNC;
+ gio->glfd = glfd;
+ gio->flags = dataonly;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+
+ frame->local = gio;
+
+ STACK_WIND_COOKIE(frame, glfs_fsync_async_cbk, subvol, subvol,
+ subvol->fops->fsync, fd, dataonly, NULL);
+
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ GF_REF_PUT(glfd);
+ GF_FREE(gio);
+ if (frame)
+ STACK_DESTROY(frame->root);
+ glfs_subvol_done(glfd->fs, subvol);
+ }
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_fsync_async34, glfs_fsync_async, 3.4.0)
+int
+pub_glfs_fsync_async34(struct glfs_fd *glfd, glfs_io_cbk34 fn, void *data)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ ret = glfs_fsync_async_common(glfd, _gf_true, (void *)fn, data, 0);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsync_async, 6.0)
+int
+pub_glfs_fsync_async(struct glfs_fd *glfd, glfs_io_cbk fn, void *data)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ ret = glfs_fsync_async_common(glfd, _gf_false, fn, data, 0);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+static int
+glfs_fdatasync_common(struct glfs_fd *glfd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct iatt preiatt =
+ {
+ 0,
+ },
+ postiatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_fsync(subvol, fd, 1, &preiatt, &postiatt, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0) {
+ if (prestat)
+ glfs_iatt_to_statx(glfd->fs, &preiatt, prestat);
+ if (poststat)
+ glfs_iatt_to_statx(glfd->fs, &postiatt, poststat);
+ }
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_fdatasync34, glfs_fdatasync, 3.4.0)
+int
+pub_glfs_fdatasync34(struct glfs_fd *glfd)
+{
+ return glfs_fdatasync_common(glfd, NULL, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fdatasync, 6.0)
+int
+pub_glfs_fdatasync(struct glfs_fd *glfd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat)
+{
+ return glfs_fdatasync_common(glfd, prestat, poststat);
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_fdatasync_async34, glfs_fdatasync_async, 3.4.0)
+int
+pub_glfs_fdatasync_async34(struct glfs_fd *glfd, glfs_io_cbk34 fn, void *data)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ ret = glfs_fsync_async_common(glfd, _gf_true, (void *)fn, data, 1);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fdatasync_async, 6.0)
+int
+pub_glfs_fdatasync_async(struct glfs_fd *glfd, glfs_io_cbk fn, void *data)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ ret = glfs_fsync_async_common(glfd, _gf_false, fn, data, 1);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+static int
+glfs_ftruncate_common(struct glfs_fd *glfd, off_t offset,
+ struct glfs_stat *prestat, struct glfs_stat *poststat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct iatt preiatt =
+ {
+ 0,
+ },
+ postiatt = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_ftruncate(subvol, fd, offset, &preiatt, &postiatt, fop_attr,
+ NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret >= 0) {
+ if (prestat)
+ glfs_iatt_to_statx(glfd->fs, &preiatt, prestat);
+ if (poststat)
+ glfs_iatt_to_statx(glfd->fs, &postiatt, poststat);
+ }
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_ftruncate34, glfs_ftruncate, 3.4.0)
+int
+pub_glfs_ftruncate34(struct glfs_fd *glfd, off_t offset)
+{
+ return glfs_ftruncate_common(glfd, offset, NULL, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_ftruncate, 6.0)
+int
+pub_glfs_ftruncate(struct glfs_fd *glfd, off_t offset,
+ struct glfs_stat *prestat, struct glfs_stat *poststat)
+{
+ return glfs_ftruncate_common(glfd, offset, prestat, poststat);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_truncate, 3.7.15)
+int
+pub_glfs_truncate(struct glfs *fs, const char *path, off_t length)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_truncate(subvol, &loc, length, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+static int
+glfs_ftruncate_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno, struct iatt *prebuf,
+ struct iatt *postbuf, dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, NULL, 0, prebuf,
+ postbuf);
+
+ return 0;
+}
+
+static int
+glfs_ftruncate_async_common(struct glfs_fd *glfd, off_t offset,
+ gf_boolean_t oldcb, glfs_io_cbk fn, void *data)
+{
+ struct glfs_io *gio = NULL;
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->op = GF_FOP_FTRUNCATE;
+ gio->glfd = glfd;
+ gio->offset = offset;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+
+ frame->local = gio;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ STACK_WIND_COOKIE(frame, glfs_ftruncate_async_cbk, subvol, subvol,
+ subvol->fops->ftruncate, fd, offset, fop_attr);
+
+ ret = 0;
+
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ GF_FREE(gio);
+ if (frame)
+ STACK_DESTROY(frame->root);
+ glfs_subvol_done(glfd->fs, subvol);
+ }
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_ftruncate_async34, glfs_ftruncate_async, 3.4.0)
+int
+pub_glfs_ftruncate_async34(struct glfs_fd *glfd, off_t offset, glfs_io_cbk34 fn,
+ void *data)
+{
+ return glfs_ftruncate_async_common(glfd, offset, _gf_true, (void *)fn,
+ data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_ftruncate_async, 6.0)
+int
+pub_glfs_ftruncate_async(struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn,
+ void *data)
+{
+ return glfs_ftruncate_async_common(glfd, offset, _gf_false, fn, data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_access, 3.4.0)
+int
+pub_glfs_access(struct glfs *fs, const char *path, int mode)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_access(subvol, &loc, mode, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_symlink, 3.4.0)
+int
+pub_glfs_symlink(struct glfs *fs, const char *data, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (loc.inode) {
+ errno = EEXIST;
+ ret = -1;
+ goto out;
+ }
+
+ if (ret == -1 && errno != ENOENT)
+ /* Any other type of error is fatal */
+ goto out;
+
+ if (ret == -1 && errno == ENOENT && !loc.parent)
+ /* The parent directory or an ancestor even
+ higher does not exist
+ */
+ goto out;
+
+ /* ret == -1 && errno == ENOENT */
+ loc.inode = inode_new(loc.parent->table);
+ if (!loc.inode) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_symlink(subvol, &loc, data, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_link(&loc, &iatt);
+out:
+ loc_wipe(&loc);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readlink, 3.4.0)
+int
+pub_glfs_readlink(struct glfs *fs, const char *path, char *buf, size_t bufsiz)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+ char *linkval = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (iatt.ia_type != IA_IFLNK) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ ret = syncop_readlink(subvol, &loc, &linkval, bufsiz, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret > 0) {
+ memcpy(buf, linkval, ret);
+ GF_FREE(linkval);
+ }
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_mknod, 3.4.0)
+int
+pub_glfs_mknod(struct glfs *fs, const char *path, mode_t mode, dev_t dev)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (loc.inode) {
+ errno = EEXIST;
+ ret = -1;
+ goto out;
+ }
+
+ if (ret == -1 && errno != ENOENT)
+ /* Any other type of error is fatal */
+ goto out;
+
+ if (ret == -1 && errno == ENOENT && !loc.parent)
+ /* The parent directory or an ancestor even
+ higher does not exist
+ */
+ goto out;
+
+ /* ret == -1 && errno == ENOENT */
+ loc.inode = inode_new(loc.parent->table);
+ if (!loc.inode) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_mknod(subvol, &loc, mode, dev, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_link(&loc, &iatt);
+out:
+ loc_wipe(&loc);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_mkdir, 3.4.0)
+int
+pub_glfs_mkdir(struct glfs *fs, const char *path, mode_t mode)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (loc.inode) {
+ errno = EEXIST;
+ ret = -1;
+ goto out;
+ }
+
+ if (ret == -1 && errno != ENOENT)
+ /* Any other type of error is fatal */
+ goto out;
+
+ if (ret == -1 && errno == ENOENT && !loc.parent)
+ /* The parent directory or an ancestor even
+ higher does not exist
+ */
+ goto out;
+
+ /* ret == -1 && errno == ENOENT */
+ loc.inode = inode_new(loc.parent->table);
+ if (!loc.inode) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_mkdir(subvol, &loc, mode, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_link(&loc, &iatt);
+out:
+ loc_wipe(&loc);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_unlink, 3.4.0)
+int
+pub_glfs_unlink(struct glfs *fs, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (iatt.ia_type == IA_IFDIR) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ /* TODO: Add leaseid */
+ ret = syncop_unlink(subvol, &loc, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_unlink(&loc);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_rmdir, 3.4.0)
+int
+pub_glfs_rmdir(struct glfs *fs, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (iatt.ia_type != IA_IFDIR) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ ret = syncop_rmdir(subvol, &loc, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret == 0)
+ ret = glfs_loc_unlink(&loc);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_rename, 3.4.0)
+int
+pub_glfs_rename(struct glfs *fs, const char *oldpath, const char *newpath)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t oldloc = {
+ 0,
+ };
+ loc_t newloc = {
+ 0,
+ };
+ struct iatt oldiatt = {
+ 0,
+ };
+ struct iatt newiatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, oldpath, &oldloc, &oldiatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &oldloc, retry);
+
+ if (ret)
+ goto out;
+retrynew:
+ ret = glfs_lresolve(fs, subvol, newpath, &newloc, &newiatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &newloc, retrynew);
+
+ if (ret && errno != ENOENT && newloc.parent)
+ goto out;
+
+ if (newiatt.ia_type != IA_INVAL) {
+ if ((oldiatt.ia_type == IA_IFDIR) != (newiatt.ia_type == IA_IFDIR)) {
+ /* Either both old and new must be dirs,
+ * or both must be non-dirs. Else, fail.
+ */
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+ }
+
+ /* TODO: - check if new or old is a prefix of the other, and fail EINVAL
+ * - Add leaseid */
+
+ ret = syncop_rename(subvol, &oldloc, &newloc, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret == -1 && errno == ESTALE) {
+ if (reval < DEFAULT_REVAL_COUNT) {
+ reval++;
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+ goto retry;
+ }
+ }
+
+ if (ret == 0) {
+ inode_rename(oldloc.parent->table, oldloc.parent, oldloc.name,
+ newloc.parent, newloc.name, oldloc.inode, &oldiatt);
+
+ if (newloc.inode && !inode_has_dentry(newloc.inode))
+ inode_forget(newloc.inode, 0);
+ }
+out:
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_link, 3.4.0)
+int
+pub_glfs_link(struct glfs *fs, const char *oldpath, const char *newpath)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t oldloc = {
+ 0,
+ };
+ loc_t newloc = {
+ 0,
+ };
+ struct iatt oldiatt = {
+ 0,
+ };
+ struct iatt newiatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_lresolve(fs, subvol, oldpath, &oldloc, &oldiatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &oldloc, retry);
+
+ if (ret)
+ goto out;
+retrynew:
+ ret = glfs_lresolve(fs, subvol, newpath, &newloc, &newiatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &newloc, retrynew);
+
+ if (ret == 0) {
+ ret = -1;
+ errno = EEXIST;
+ goto out;
+ }
+
+ if (oldiatt.ia_type == IA_IFDIR) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ /* Filling the inode of the hard link to be same as that of the
+ original file
+ */
+ if (newloc.inode) {
+ inode_unref(newloc.inode);
+ newloc.inode = NULL;
+ }
+ newloc.inode = inode_ref(oldloc.inode);
+
+ ret = syncop_link(subvol, &oldloc, &newloc, &newiatt, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret == -1 && errno == ESTALE) {
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+ if (reval--)
+ goto retry;
+ }
+
+ if (ret == 0)
+ ret = glfs_loc_link(&newloc, &newiatt);
+out:
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_opendir, 3.4.0)
+struct glfs_fd *
+pub_glfs_opendir(struct glfs *fs, const char *path)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd)
+ goto out;
+
+ INIT_LIST_HEAD(&glfd->entries);
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (!IA_ISDIR(iatt.ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ if (glfd->fd) {
+ /* Retry. Safe to touch glfd->fd as we
+ still have not glfs_fd_bind() yet.
+ */
+ fd_unref(glfd->fd);
+ glfd->fd = NULL;
+ }
+
+ glfd->fd = fd_create(loc.inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_opendir(subvol, &loc, glfd->fd, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ glfd = NULL;
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return glfd;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_closedir, 3.4.0)
+int
+pub_glfs_closedir(struct glfs_fd *glfd)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ gf_dirent_free(list_entry(&glfd->entries, gf_dirent_t, list));
+
+ glfs_mark_glfd_for_deletion(glfd);
+
+ __GLFS_EXIT_FS;
+
+ ret = 0;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_telldir, 3.4.0)
+long
+pub_glfs_telldir(struct glfs_fd *fd)
+{
+ if (fd == NULL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ return fd->offset;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_seekdir, 3.4.0)
+void
+pub_glfs_seekdir(struct glfs_fd *fd, long offset)
+{
+ gf_dirent_t *entry = NULL;
+ gf_dirent_t *tmp = NULL;
+
+ if (fd == NULL) {
+ errno = EBADF;
+ return;
+ }
+
+ if (fd->offset == offset)
+ return;
+
+ fd->offset = offset;
+ fd->next = NULL;
+
+ list_for_each_entry_safe(entry, tmp, &fd->entries, list)
+ {
+ if (entry->d_off != offset)
+ continue;
+
+ if (&tmp->list != &fd->entries) {
+ /* found! */
+ fd->next = tmp;
+ return;
+ }
+ }
+ /* could not find entry at requested offset in the cache.
+ next readdir_r() will result in glfd_entry_refresh()
+ */
+}
+
+static int
+glfs_discard_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno,
+ struct iatt *preop_stbuf, struct iatt *postop_stbuf,
+ dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, NULL, 0, preop_stbuf,
+ postop_stbuf);
+
+ return 0;
+}
+
+static int
+glfs_discard_async_common(struct glfs_fd *glfd, off_t offset, size_t len,
+ gf_boolean_t oldcb, glfs_io_cbk fn, void *data)
+{
+ struct glfs_io *gio = NULL;
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->op = GF_FOP_DISCARD;
+ gio->glfd = glfd;
+ gio->offset = offset;
+ gio->count = len;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+
+ frame->local = gio;
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ STACK_WIND_COOKIE(frame, glfs_discard_async_cbk, subvol, subvol,
+ subvol->fops->discard, fd, offset, len, fop_attr);
+
+ ret = 0;
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ GF_FREE(gio);
+ if (frame)
+ STACK_DESTROY(frame->root);
+ glfs_subvol_done(glfd->fs, subvol);
+ }
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_discard_async35, glfs_discard_async, 3.5.0)
+int
+pub_glfs_discard_async35(struct glfs_fd *glfd, off_t offset, size_t len,
+ glfs_io_cbk34 fn, void *data)
+{
+ return glfs_discard_async_common(glfd, offset, len, _gf_true, (void *)fn,
+ data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_discard_async, 6.0)
+int
+pub_glfs_discard_async(struct glfs_fd *glfd, off_t offset, size_t len,
+ glfs_io_cbk fn, void *data)
+{
+ return glfs_discard_async_common(glfd, offset, len, _gf_false, fn, data);
+}
+
+static int
+glfs_zerofill_async_cbk(call_frame_t *frame, void *cookie, xlator_t *this,
+ int32_t op_ret, int32_t op_errno,
+ struct iatt *preop_stbuf, struct iatt *postop_stbuf,
+ dict_t *xdata)
+{
+ glfs_io_async_cbk(op_ret, op_errno, frame, cookie, NULL, 0, preop_stbuf,
+ postop_stbuf);
+
+ return 0;
+}
+
+static int
+glfs_zerofill_async_common(struct glfs_fd *glfd, off_t offset, off_t len,
+ gf_boolean_t oldcb, glfs_io_cbk fn, void *data)
+{
+ struct glfs_io *gio = NULL;
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ frame = syncop_create_frame(THIS);
+ if (!frame) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio = GF_CALLOC(1, sizeof(*gio), glfs_mt_glfs_io_t);
+ if (!gio) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gio->op = GF_FOP_ZEROFILL;
+ gio->glfd = glfd;
+ gio->offset = offset;
+ gio->count = len;
+ gio->oldcb = oldcb;
+ gio->fn = fn;
+ gio->data = data;
+
+ frame->local = gio;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ STACK_WIND_COOKIE(frame, glfs_zerofill_async_cbk, subvol, subvol,
+ subvol->fops->zerofill, fd, offset, len, fop_attr);
+ ret = 0;
+out:
+ if (ret) {
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ GF_FREE(gio);
+ if (frame)
+ STACK_DESTROY(frame->root);
+ glfs_subvol_done(glfd->fs, subvol);
+ }
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_zerofill_async35, glfs_zerofill_async, 3.5.0)
+int
+pub_glfs_zerofill_async35(struct glfs_fd *glfd, off_t offset, off_t len,
+ glfs_io_cbk34 fn, void *data)
+{
+ return glfs_zerofill_async_common(glfd, offset, len, _gf_true, (void *)fn,
+ data);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_zerofill_async, 6.0)
+int
+pub_glfs_zerofill_async(struct glfs_fd *glfd, off_t offset, off_t len,
+ glfs_io_cbk fn, void *data)
+{
+ return glfs_zerofill_async_common(glfd, offset, len, _gf_false, fn, data);
+}
+
+void
+gf_dirent_to_dirent(gf_dirent_t *gf_dirent, struct dirent *dirent)
+{
+ dirent->d_ino = gf_dirent->d_ino;
+
+#ifdef _DIRENT_HAVE_D_OFF
+ dirent->d_off = gf_dirent->d_off;
+#endif
+
+#ifdef _DIRENT_HAVE_D_TYPE
+ dirent->d_type = gf_dirent->d_type;
+#endif
+
+#ifdef _DIRENT_HAVE_D_NAMLEN
+ dirent->d_namlen = strlen(gf_dirent->d_name);
+#endif
+
+ snprintf(dirent->d_name, NAME_MAX + 1, "%s", gf_dirent->d_name);
+}
+
+int
+glfd_entry_refresh(struct glfs_fd *glfd, int plus)
+{
+ xlator_t *subvol = NULL;
+ gf_dirent_t entries;
+ gf_dirent_t old;
+ gf_dirent_t *entry = NULL;
+ int ret = -1;
+ fd_t *fd = NULL;
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ if (fd->inode->ia_type != IA_IFDIR) {
+ ret = -1;
+ errno = EBADF;
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&entries.list);
+ INIT_LIST_HEAD(&old.list);
+
+ if (plus)
+ ret = syncop_readdirp(subvol, fd, 131072, glfd->offset, &entries, NULL,
+ NULL);
+ else
+ ret = syncop_readdir(subvol, fd, 131072, glfd->offset, &entries, NULL,
+ NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret >= 0) {
+ if (plus) {
+ list_for_each_entry(entry, &entries.list, list)
+ {
+ if ((!entry->inode && (!IA_ISDIR(entry->d_stat.ia_type))) ||
+ ((entry->d_stat.ia_ctime == 0) &&
+ strcmp(entry->d_name, ".") &&
+ strcmp(entry->d_name, ".."))) {
+ /* entry->inode for directories will be
+ * always set to null to force a lookup
+ * on the dentry. Hence to not degrade
+ * readdir performance, we skip lookups
+ * for directory entries. Also we will have
+ * proper stat if directory present on
+ * hashed subvolume.
+ *
+ * In addition, if the stat is invalid, force
+ * lookup to fetch proper stat.
+ */
+ gf_fill_iatt_for_dirent(entry, fd->inode, subvol);
+ }
+ }
+
+ gf_link_inodes_from_dirent(THIS, fd->inode, &entries);
+ }
+
+ list_splice_init(&glfd->entries, &old.list);
+ list_splice_init(&entries.list, &glfd->entries);
+
+ /* spurious errno is dangerous for glfd_entry_next() */
+ errno = 0;
+ }
+
+ if (ret > 0)
+ glfd->next = list_entry(glfd->entries.next, gf_dirent_t, list);
+
+ gf_dirent_free(&old);
+out:
+ if (fd)
+ fd_unref(fd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ return ret;
+}
+
+gf_dirent_t *
+glfd_entry_next(struct glfs_fd *glfd, int plus)
+{
+ gf_dirent_t *entry = NULL;
+ int ret = -1;
+
+ if (!glfd->offset || !glfd->next) {
+ ret = glfd_entry_refresh(glfd, plus);
+ if (ret < 0)
+ return NULL;
+ }
+
+ entry = glfd->next;
+ if (!entry)
+ return NULL;
+
+ if (&entry->next->list == &glfd->entries)
+ glfd->next = NULL;
+ else
+ glfd->next = entry->next;
+
+ glfd->offset = entry->d_off;
+
+ return entry;
+}
+
+struct dirent *
+glfs_readdirbuf_get(struct glfs_fd *glfd)
+{
+ struct dirent *buf = NULL;
+
+ LOCK(&glfd->fd->lock);
+ {
+ buf = glfd->readdirbuf;
+ if (buf) {
+ memset(buf, 0, READDIRBUF_SIZE);
+ goto unlock;
+ }
+
+ buf = GF_CALLOC(1, READDIRBUF_SIZE, glfs_mt_readdirbuf_t);
+ if (!buf) {
+ errno = ENOMEM;
+ goto unlock;
+ }
+
+ glfd->readdirbuf = buf;
+ }
+unlock:
+ UNLOCK(&glfd->fd->lock);
+
+ return buf;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readdirplus_r, 3.4.0)
+int
+pub_glfs_readdirplus_r(struct glfs_fd *glfd, struct stat *stat,
+ struct dirent *ext, struct dirent **res)
+{
+ int ret = 0;
+ gf_dirent_t *entry = NULL;
+ struct dirent *buf = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ errno = 0;
+
+ if (ext)
+ buf = ext;
+ else
+ buf = glfs_readdirbuf_get(glfd);
+
+ if (!buf) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ entry = glfd_entry_next(glfd, !!stat);
+ if (errno)
+ ret = -1;
+
+ if (res) {
+ if (entry)
+ *res = buf;
+ else
+ *res = NULL;
+ }
+
+ if (entry) {
+ gf_dirent_to_dirent(entry, buf);
+ if (stat)
+ glfs_iatt_to_stat(glfd->fs, &entry->d_stat, stat);
+ }
+
+out:
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ __GLFS_EXIT_FS;
+
+ return ret;
+
+invalid_fs:
+ return -1;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readdir_r, 3.4.0)
+int
+pub_glfs_readdir_r(struct glfs_fd *glfd, struct dirent *buf,
+ struct dirent **res)
+{
+ return pub_glfs_readdirplus_r(glfd, 0, buf, res);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readdirplus, 3.5.0)
+struct dirent *
+pub_glfs_readdirplus(struct glfs_fd *glfd, struct stat *stat)
+{
+ struct dirent *res = NULL;
+ int ret = -1;
+
+ ret = pub_glfs_readdirplus_r(glfd, stat, NULL, &res);
+ if (ret)
+ return NULL;
+
+ return res;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_readdir, 3.5.0)
+struct dirent *
+pub_glfs_readdir(struct glfs_fd *glfd)
+{
+ return pub_glfs_readdirplus(glfd, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_statvfs, 3.4.0)
+int
+pub_glfs_statvfs(struct glfs *fs, const char *path, struct statvfs *buf)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_statfs(subvol, &loc, buf, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setattr, 6.0)
+int
+pub_glfs_setattr(struct glfs *fs, const char *path, struct glfs_stat *stat,
+ int follow)
+{
+ int ret = -1;
+ int glvalid;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt riatt = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ GF_VALIDATE_OR_GOTO("glfs_setattr", stat, out);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ if (follow)
+ ret = glfs_resolve(fs, subvol, path, &loc, &riatt, reval);
+ else
+ ret = glfs_lresolve(fs, subvol, path, &loc, &riatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ glfs_iatt_from_statx(&iatt, stat);
+ glfsflags_from_gfapiflags(stat, &glvalid);
+
+ /* TODO : Add leaseid */
+ ret = syncop_setattr(subvol, &loc, &iatt, glvalid, 0, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsetattr, 6.0)
+int
+pub_glfs_fsetattr(struct glfs_fd *glfd, struct glfs_stat *stat)
+{
+ int ret = -1;
+ int glvalid;
+ struct iatt iatt = {
+ 0,
+ };
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ GF_VALIDATE_OR_GOTO("glfs_fsetattr", stat, out);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ glfs_iatt_from_statx(&iatt, stat);
+ glfsflags_from_gfapiflags(stat, &glvalid);
+
+ /* TODO : Add leaseid */
+ ret = syncop_fsetattr(subvol, fd, &iatt, glvalid, 0, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_chmod, 3.4.0)
+int
+pub_glfs_chmod(struct glfs *fs, const char *path, mode_t mode)
+{
+ int ret = -1;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ stat.glfs_st_mode = mode;
+ stat.glfs_st_mask = GLFS_STAT_MODE;
+
+ ret = glfs_setattr(fs, path, &stat, 1);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fchmod, 3.4.0)
+int
+pub_glfs_fchmod(struct glfs_fd *glfd, mode_t mode)
+{
+ int ret = -1;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ stat.glfs_st_mode = mode;
+ stat.glfs_st_mask = GLFS_STAT_MODE;
+
+ ret = glfs_fsetattr(glfd, &stat);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_chown, 3.4.0)
+int
+pub_glfs_chown(struct glfs *fs, const char *path, uid_t uid, gid_t gid)
+{
+ int ret = 0;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ if (uid != (uid_t)-1) {
+ stat.glfs_st_uid = uid;
+ stat.glfs_st_mask = GLFS_STAT_UID;
+ }
+
+ if (gid != (uid_t)-1) {
+ stat.glfs_st_gid = gid;
+ stat.glfs_st_mask = stat.glfs_st_mask | GLFS_STAT_GID;
+ }
+
+ if (stat.glfs_st_mask)
+ ret = glfs_setattr(fs, path, &stat, 1);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lchown, 3.4.0)
+int
+pub_glfs_lchown(struct glfs *fs, const char *path, uid_t uid, gid_t gid)
+{
+ int ret = 0;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ if (uid != (uid_t)-1) {
+ stat.glfs_st_uid = uid;
+ stat.glfs_st_mask = GLFS_STAT_UID;
+ }
+
+ if (gid != (uid_t)-1) {
+ stat.glfs_st_gid = gid;
+ stat.glfs_st_mask = stat.glfs_st_mask | GLFS_STAT_GID;
+ }
+
+ if (stat.glfs_st_mask)
+ ret = glfs_setattr(fs, path, &stat, 0);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fchown, 3.4.0)
+int
+pub_glfs_fchown(struct glfs_fd *glfd, uid_t uid, gid_t gid)
+{
+ int ret = 0;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ if (uid != (uid_t)-1) {
+ stat.glfs_st_uid = uid;
+ stat.glfs_st_mask = GLFS_STAT_UID;
+ }
+
+ if (gid != (uid_t)-1) {
+ stat.glfs_st_gid = gid;
+ stat.glfs_st_mask = stat.glfs_st_mask | GLFS_STAT_GID;
+ }
+
+ if (stat.glfs_st_mask)
+ ret = glfs_fsetattr(glfd, &stat);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_utimens, 3.4.0)
+int
+pub_glfs_utimens(struct glfs *fs, const char *path,
+ const struct timespec times[2])
+{
+ int ret = -1;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ stat.glfs_st_atime = times[0];
+ stat.glfs_st_mtime = times[1];
+
+ stat.glfs_st_mask = GLFS_STAT_ATIME | GLFS_STAT_MTIME;
+
+ ret = glfs_setattr(fs, path, &stat, 1);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lutimens, 3.4.0)
+int
+pub_glfs_lutimens(struct glfs *fs, const char *path,
+ const struct timespec times[2])
+{
+ int ret = -1;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ stat.glfs_st_atime = times[0];
+ stat.glfs_st_mtime = times[1];
+
+ stat.glfs_st_mask = GLFS_STAT_ATIME | GLFS_STAT_MTIME;
+
+ ret = glfs_setattr(fs, path, &stat, 0);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_futimens, 3.4.0)
+int
+pub_glfs_futimens(struct glfs_fd *glfd, const struct timespec times[2])
+{
+ int ret = -1;
+ struct glfs_stat stat = {
+ 0,
+ };
+
+ stat.glfs_st_atime = times[0];
+ stat.glfs_st_mtime = times[1];
+
+ stat.glfs_st_mask = GLFS_STAT_ATIME | GLFS_STAT_MTIME;
+
+ ret = glfs_fsetattr(glfd, &stat);
+
+ return ret;
+}
+
+int
+glfs_getxattr_process(void *value, size_t size, dict_t *xattr, const char *name)
+{
+ data_t *data = NULL;
+ int ret = -1;
+
+ data = dict_get(xattr, (char *)name);
+ if (!data) {
+ errno = ENODATA;
+ ret = -1;
+ goto out;
+ }
+
+ ret = data->len;
+ if (!value || !size)
+ goto out;
+
+ if (size < ret) {
+ ret = -1;
+ errno = ERANGE;
+ goto out;
+ }
+
+ memcpy(value, data->data, ret);
+out:
+ return ret;
+}
+
+ssize_t
+glfs_getxattr_common(struct glfs *fs, const char *path, const char *name,
+ void *value, size_t size, int follow)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ dict_t *xattr = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (!name || *name == '\0') {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ ret = -1;
+ errno = ENAMETOOLONG;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+retry:
+ if (follow)
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+ else
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_getxattr(subvol, &loc, &xattr, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = glfs_getxattr_process(value, size, xattr, name);
+out:
+ loc_wipe(&loc);
+
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_getxattr, 3.4.0)
+ssize_t
+pub_glfs_getxattr(struct glfs *fs, const char *path, const char *name,
+ void *value, size_t size)
+{
+ return glfs_getxattr_common(fs, path, name, value, size, 1);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lgetxattr, 3.4.0)
+ssize_t
+pub_glfs_lgetxattr(struct glfs *fs, const char *path, const char *name,
+ void *value, size_t size)
+{
+ return glfs_getxattr_common(fs, path, name, value, size, 0);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fgetxattr, 3.4.0)
+ssize_t
+pub_glfs_fgetxattr(struct glfs_fd *glfd, const char *name, void *value,
+ size_t size)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ dict_t *xattr = NULL;
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ if (!name || *name == '\0') {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ ret = -1;
+ errno = ENAMETOOLONG;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = syncop_fgetxattr(subvol, fd, &xattr, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret)
+ goto out;
+
+ ret = glfs_getxattr_process(value, size, xattr, name);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_listxattr_process(void *value, size_t size, dict_t *xattr)
+{
+ int ret = -1;
+
+ if (!xattr)
+ goto out;
+
+ ret = dict_keys_join(NULL, 0, xattr, NULL);
+
+ if (!value || !size)
+ goto out;
+
+ if (size < ret) {
+ ret = -1;
+ errno = ERANGE;
+ } else {
+ dict_keys_join(value, size, xattr, NULL);
+ }
+
+out:
+ return ret;
+}
+
+ssize_t
+glfs_listxattr_common(struct glfs *fs, const char *path, void *value,
+ size_t size, int follow)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ dict_t *xattr = NULL;
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+retry:
+ if (follow)
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+ else
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_getxattr(subvol, &loc, &xattr, NULL, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = glfs_listxattr_process(value, size, xattr);
+out:
+ loc_wipe(&loc);
+
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_listxattr, 3.4.0)
+ssize_t
+pub_glfs_listxattr(struct glfs *fs, const char *path, void *value, size_t size)
+{
+ return glfs_listxattr_common(fs, path, value, size, 1);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_llistxattr, 3.4.0)
+ssize_t
+pub_glfs_llistxattr(struct glfs *fs, const char *path, void *value, size_t size)
+{
+ return glfs_listxattr_common(fs, path, value, size, 0);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_flistxattr, 3.4.0)
+ssize_t
+pub_glfs_flistxattr(struct glfs_fd *glfd, void *value, size_t size)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ dict_t *xattr = NULL;
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = syncop_fgetxattr(subvol, fd, &xattr, NULL, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret)
+ goto out;
+
+ ret = glfs_listxattr_process(value, size, xattr);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_setxattr_common(struct glfs *fs, const char *path, const char *name,
+ const void *value, size_t size, int flags, int follow)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ dict_t *xattr = NULL;
+ int reval = 0;
+ void *value_cp = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (!name || *name == '\0') {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ ret = -1;
+ errno = ENAMETOOLONG;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+retry:
+ if (follow)
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+ else
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ value_cp = gf_memdup(value, size);
+ GF_CHECK_ALLOC_AND_LOG(subvol->name, value_cp, ret,
+ "Failed to"
+ " duplicate setxattr value",
+ out);
+
+ xattr = dict_for_key_value(name, value_cp, size, _gf_false);
+ if (!xattr) {
+ GF_FREE(value_cp);
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_setxattr(subvol, &loc, xattr, flags, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setxattr, 3.4.0)
+int
+pub_glfs_setxattr(struct glfs *fs, const char *path, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return glfs_setxattr_common(fs, path, name, value, size, flags, 1);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lsetxattr, 3.4.0)
+int
+pub_glfs_lsetxattr(struct glfs *fs, const char *path, const char *name,
+ const void *value, size_t size, int flags)
+{
+ return glfs_setxattr_common(fs, path, name, value, size, flags, 0);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fsetxattr, 3.4.0)
+int
+pub_glfs_fsetxattr(struct glfs_fd *glfd, const char *name, const void *value,
+ size_t size, int flags)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ dict_t *xattr = NULL;
+ fd_t *fd = NULL;
+ void *value_cp = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ if (!name || *name == '\0') {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ ret = -1;
+ errno = ENAMETOOLONG;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ value_cp = gf_memdup(value, size);
+ GF_CHECK_ALLOC_AND_LOG(subvol->name, value_cp, ret,
+ "Failed to"
+ " duplicate setxattr value",
+ out);
+
+ xattr = dict_for_key_value(name, value_cp, size, _gf_false);
+ if (!xattr) {
+ GF_FREE(value_cp);
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_fsetxattr(subvol, fd, xattr, flags, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (xattr)
+ dict_unref(xattr);
+
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_removexattr_common(struct glfs *fs, const char *path, const char *name,
+ int follow)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ if (follow)
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+ else
+ ret = glfs_lresolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ ret = syncop_removexattr(subvol, &loc, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_removexattr, 3.4.0)
+int
+pub_glfs_removexattr(struct glfs *fs, const char *path, const char *name)
+{
+ return glfs_removexattr_common(fs, path, name, 1);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lremovexattr, 3.4.0)
+int
+pub_glfs_lremovexattr(struct glfs *fs, const char *path, const char *name)
+{
+ return glfs_removexattr_common(fs, path, name, 0);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fremovexattr, 3.4.0)
+int
+pub_glfs_fremovexattr(struct glfs_fd *glfd, const char *name)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = syncop_fremovexattr(subvol, fd, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fallocate, 3.5.0)
+int
+pub_glfs_fallocate(struct glfs_fd *glfd, int keep_size, off_t offset,
+ size_t len)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_fallocate(subvol, fd, keep_size, offset, len, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_discard, 3.5.0)
+int
+pub_glfs_discard(struct glfs_fd *glfd, off_t offset, size_t len)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_discard(subvol, fd, offset, len, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_zerofill, 3.5.0)
+int
+pub_glfs_zerofill(struct glfs_fd *glfd, off_t offset, off_t len)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ dict_t *fop_attr = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_zerofill(subvol, fd, offset, len, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_chdir, 3.4.0)
+int
+pub_glfs_chdir(struct glfs *fs, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (!IA_ISDIR(iatt.ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ glfs_cwd_set(fs, loc.inode);
+
+out:
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fchdir, 3.4.0)
+int
+pub_glfs_fchdir(struct glfs_fd *glfd)
+{
+ int ret = -1;
+ inode_t *inode = NULL;
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ inode = fd->inode;
+
+ if (!IA_ISDIR(inode->ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ glfs_cwd_set(glfd->fs, inode);
+ ret = 0;
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+static gf_boolean_t warn_realpath = _gf_true; /* log once */
+
+static char *
+glfs_realpath_common(struct glfs *fs, const char *path, char *resolved_path,
+ gf_boolean_t warn_deprecated)
+{
+ int ret = -1;
+ char *retpath = NULL;
+ char *allocpath = NULL;
+ xlator_t *subvol = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int reval = 0;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (resolved_path)
+ retpath = resolved_path;
+ else if (warn_deprecated) {
+ retpath = allocpath = malloc(PATH_MAX + 1);
+ if (warn_realpath) {
+ warn_realpath = _gf_false;
+ gf_log(THIS->name, GF_LOG_WARNING,
+ "this application "
+ "is compiled against an old version of "
+ "libgfapi, it should use glfs_free() to "
+ "release the path returned by "
+ "glfs_realpath()");
+ }
+ } else {
+ retpath = allocpath = GLFS_CALLOC(1, PATH_MAX + 1, NULL,
+ glfs_mt_realpath_t);
+ }
+
+ if (!retpath) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+retry:
+ ret = glfs_resolve(fs, subvol, path, &loc, &iatt, reval);
+
+ ESTALE_RETRY(ret, errno, reval, &loc, retry);
+
+ if (ret)
+ goto out;
+
+ if (loc.path) {
+ snprintf(retpath, PATH_MAX + 1, "%s", loc.path);
+ }
+
+out:
+ loc_wipe(&loc);
+
+ if (ret == -1) {
+ if (warn_deprecated && allocpath)
+ free(allocpath);
+ else if (allocpath)
+ GLFS_FREE(allocpath);
+ retpath = NULL;
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return retpath;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_realpath34, glfs_realpath, 3.4.0)
+char *
+pub_glfs_realpath34(struct glfs *fs, const char *path, char *resolved_path)
+{
+ return glfs_realpath_common(fs, path, resolved_path, _gf_true);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_realpath, 3.7.17)
+char *
+pub_glfs_realpath(struct glfs *fs, const char *path, char *resolved_path)
+{
+ return glfs_realpath_common(fs, path, resolved_path, _gf_false);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_getcwd, 3.4.0)
+char *
+pub_glfs_getcwd(struct glfs *fs, char *buf, size_t n)
+{
+ int ret = -1;
+ inode_t *inode = NULL;
+ char *path = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (!buf || n < 2) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ inode = glfs_cwd_get(fs);
+
+ if (!inode) {
+ strncpy(buf, "/", n);
+ ret = 0;
+ goto out;
+ }
+
+ ret = inode_path(inode, 0, &path);
+ if (n <= ret) {
+ ret = -1;
+ errno = ERANGE;
+ goto out;
+ }
+
+ strncpy(buf, path, n);
+ ret = 0;
+out:
+ GF_FREE(path);
+
+ if (inode)
+ inode_unref(inode);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ if (ret < 0)
+ return NULL;
+
+ return buf;
+}
+
+static void
+gf_flock_to_flock(struct gf_flock *gf_flock, struct flock *flock)
+{
+ flock->l_type = gf_flock->l_type;
+ flock->l_whence = gf_flock->l_whence;
+ flock->l_start = gf_flock->l_start;
+ flock->l_len = gf_flock->l_len;
+ flock->l_pid = gf_flock->l_pid;
+}
+
+static void
+gf_flock_from_flock(struct gf_flock *gf_flock, struct flock *flock)
+{
+ gf_flock->l_type = flock->l_type;
+ gf_flock->l_whence = flock->l_whence;
+ gf_flock->l_start = flock->l_start;
+ gf_flock->l_len = flock->l_len;
+ gf_flock->l_pid = flock->l_pid;
+}
+
+static int
+glfs_lock_common(struct glfs_fd *glfd, int cmd, struct flock *flock,
+ dict_t *xdata)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ struct gf_flock gf_flock = {
+ 0,
+ };
+ struct gf_flock saved_flock = {
+ 0,
+ };
+ fd_t *fd = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ if (!flock) {
+ errno = EINVAL;
+ goto out;
+ }
+
+ GF_REF_GET(glfd);
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ /* Generate glusterfs flock structure from client flock
+ * structure to be processed by server */
+ gf_flock_from_flock(&gf_flock, flock);
+
+ /* Keep another copy of flock for split/merge of locks
+ * at client side */
+ gf_flock_from_flock(&saved_flock, flock);
+
+ if (glfd->lk_owner.len != 0) {
+ ret = syncopctx_setfslkowner(&glfd->lk_owner);
+
+ if (ret)
+ goto out;
+ }
+
+ ret = get_fop_attr_thrd_key(&xdata);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_lk(subvol, fd, cmd, &gf_flock, xdata, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* Convert back from gf_flock to flock as expected by application */
+ gf_flock_to_flock(&gf_flock, flock);
+
+ if (ret == 0 && (cmd == F_SETLK || cmd == F_SETLKW)) {
+ ret = fd_lk_insert_and_merge(fd, cmd, &saved_flock);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, 0,
+ API_MSG_LOCK_INSERT_MERGE_FAILED, "gfid=%s",
+ uuid_utoa(fd->inode->gfid), NULL);
+ ret = 0;
+ }
+ }
+
+out:
+ if (fd)
+ fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_file_lock, 4.0.0)
+int
+pub_glfs_file_lock(struct glfs_fd *glfd, int cmd, struct flock *flock,
+ glfs_lock_mode_t lk_mode)
+{
+ int ret = -1;
+ dict_t *xdata_in = NULL;
+
+ if (lk_mode == GLFS_LK_MANDATORY) {
+ /* Create a new dictionary */
+ xdata_in = dict_new();
+ if (xdata_in == NULL) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ /* Set GF_LK_MANDATORY internally within dictionary to map
+ * GLFS_LK_MANDATORY */
+ ret = dict_set_uint32(xdata_in, GF_LOCK_MODE, GF_LK_MANDATORY);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, 0,
+ API_MSG_SETTING_LOCK_TYPE_FAILED, NULL);
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ ret = glfs_lock_common(glfd, cmd, flock, xdata_in);
+out:
+ if (xdata_in)
+ dict_unref(xdata_in);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_posix_lock, 3.4.0)
+int
+pub_glfs_posix_lock(struct glfs_fd *glfd, int cmd, struct flock *flock)
+{
+ return glfs_lock_common(glfd, cmd, flock, NULL);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fd_set_lkowner, 3.10.7)
+int
+pub_glfs_fd_set_lkowner(struct glfs_fd *glfd, void *data, int len)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ if (!GF_REF_GET(glfd)) {
+ goto invalid_fs;
+ }
+
+ GF_VALIDATE_OR_GOTO(THIS->name, data, out);
+
+ if ((len <= 0) || (len > GFAPI_MAX_LOCK_OWNER_LEN)) {
+ errno = EINVAL;
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ARG,
+ "lk_owner len=%d", len, NULL);
+ goto out;
+ }
+
+ glfd->lk_owner.len = len;
+
+ memcpy(glfd->lk_owner.data, data, len);
+
+ ret = 0;
+out:
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_dup, 3.4.0)
+struct glfs_fd *
+pub_glfs_dup(struct glfs_fd *glfd)
+{
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct glfs_fd *dupfd = NULL;
+ struct glfs *fs = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ fs = glfd->fs;
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(fs, subvol, glfd);
+ if (!fd) {
+ errno = EBADFD;
+ goto out;
+ }
+
+ dupfd = glfs_fd_new(fs);
+ if (!dupfd) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ dupfd->fd = fd_ref(fd);
+ dupfd->state = glfd->state;
+out:
+ if (fd)
+ fd_unref(fd);
+ if (dupfd)
+ glfs_fd_bind(dupfd);
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return dupfd;
+}
+
+static void
+glfs_enqueue_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
+{
+ int ret = -1;
+ upcall_entry *u_list = NULL;
+
+ if (!fs || !upcall_data)
+ goto out;
+
+ u_list = GF_CALLOC(1, sizeof(*u_list), glfs_mt_upcall_entry_t);
+
+ if (!u_list) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ INIT_LIST_HEAD(&u_list->upcall_list);
+
+ gf_uuid_copy(u_list->upcall_data.gfid, upcall_data->gfid);
+ u_list->upcall_data.event_type = upcall_data->event_type;
+
+ switch (upcall_data->event_type) {
+ case GF_UPCALL_CACHE_INVALIDATION:
+ ret = glfs_get_upcall_cache_invalidation(&u_list->upcall_data,
+ upcall_data);
+ break;
+ case GF_UPCALL_RECALL_LEASE:
+ ret = glfs_get_upcall_lease(&u_list->upcall_data, upcall_data);
+ break;
+ default:
+ break;
+ }
+
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ENTRY, NULL);
+ goto out;
+ }
+
+ pthread_mutex_lock(&fs->upcall_list_mutex);
+ {
+ list_add_tail(&u_list->upcall_list, &fs->upcall_list);
+ }
+ pthread_mutex_unlock(&fs->upcall_list_mutex);
+
+ ret = 0;
+
+out:
+ if (ret && u_list) {
+ GF_FREE(u_list->upcall_data.data);
+ GF_FREE(u_list);
+ }
+}
+
+static void
+glfs_free_upcall_lease(void *to_free)
+{
+ struct glfs_upcall_lease *arg = to_free;
+
+ if (!arg)
+ return;
+
+ if (arg->object)
+ glfs_h_close(arg->object);
+
+ GF_FREE(arg);
+}
+
+int
+glfs_recall_lease_fd(struct glfs *fs, struct gf_upcall *up_data)
+{
+ struct gf_upcall_recall_lease *recall_lease = NULL;
+ xlator_t *subvol = NULL;
+ int ret = 0;
+ inode_t *inode = NULL;
+ struct glfs_fd *glfd = NULL;
+ struct glfs_fd *tmp = NULL;
+ struct list_head glfd_list;
+ fd_t *fd = NULL;
+ uint64_t value = 0;
+ struct glfs_lease lease = {
+ 0,
+ };
+
+ GF_VALIDATE_OR_GOTO("gfapi", up_data, out);
+ GF_VALIDATE_OR_GOTO("gfapi", fs, out);
+
+ recall_lease = up_data->data;
+ GF_VALIDATE_OR_GOTO("gfapi", recall_lease, out);
+
+ INIT_LIST_HEAD(&glfd_list);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ gf_msg_debug(THIS->name, 0, "Recall lease received for gfid:%s",
+ uuid_utoa(up_data->gfid));
+
+ inode = inode_find(subvol->itable, up_data->gfid);
+ if (!inode) {
+ ret = -1;
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INODE_FIND_FAILED,
+ "gfid=%s", uuid_utoa(up_data->gfid), "graph_id=%d",
+ subvol->graph->id, NULL);
+ goto out;
+ }
+
+ LOCK(&inode->lock);
+ {
+ list_for_each_entry(fd, &inode->fd_list, inode_list)
+ {
+ ret = fd_ctx_get(fd, subvol, &value);
+ glfd = (struct glfs_fd *)(uintptr_t)value;
+ if (glfd) {
+ gf_msg_trace(THIS->name, 0, "glfd (%p) has held lease", glfd);
+ GF_REF_GET(glfd);
+ list_add_tail(&glfd->list, &glfd_list);
+ }
+ }
+ }
+ UNLOCK(&inode->lock);
+
+ if (!list_empty(&glfd_list)) {
+ list_for_each_entry_safe(glfd, tmp, &glfd_list, list)
+ {
+ LOCK(&glfd->lock);
+ {
+ if (glfd->state != GLFD_CLOSE) {
+ gf_msg_trace(THIS->name, 0,
+ "glfd (%p) has held lease, "
+ "calling recall cbk",
+ glfd);
+ glfd->cbk(lease, glfd->cookie);
+ }
+ }
+ UNLOCK(&glfd->lock);
+
+ list_del_init(&glfd->list);
+ GF_REF_PUT(glfd);
+ }
+ }
+
+out:
+ return ret;
+}
+
+static int
+glfs_recall_lease_upcall(struct glfs *fs, struct glfs_upcall *up_arg,
+ struct gf_upcall *up_data)
+{
+ struct gf_upcall_recall_lease *recall_lease = NULL;
+ struct glfs_object *object = NULL;
+ xlator_t *subvol = NULL;
+ int ret = -1;
+ struct glfs_upcall_lease *up_lease_arg = NULL;
+
+ GF_VALIDATE_OR_GOTO("gfapi", up_data, out);
+ GF_VALIDATE_OR_GOTO("gfapi", fs, out);
+
+ recall_lease = up_data->data;
+ GF_VALIDATE_OR_GOTO("gfapi", recall_lease, out);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ gf_msg_debug(THIS->name, 0, "Recall lease received for gfid:%s",
+ uuid_utoa(up_data->gfid));
+
+ object = glfs_h_find_handle(fs, up_data->gfid, GFAPI_HANDLE_LENGTH);
+ if (!object) {
+ /* The reason handle creation will fail is because we
+ * couldn't find the inode in the gfapi inode table.
+ *
+ * But since application would have taken inode_ref, the
+ * only case when this can happen is when it has closed
+ * the handle and hence will no more be interested in
+ * the upcall for this particular gfid.
+ */
+ gf_smsg(THIS->name, GF_LOG_DEBUG, errno, API_MSG_CREATE_HANDLE_FAILED,
+ "gfid=%s", uuid_utoa(up_data->gfid), NULL);
+ errno = ESTALE;
+ goto out;
+ }
+
+ up_lease_arg = GF_CALLOC(1, sizeof(struct glfs_upcall_lease),
+ glfs_mt_upcall_inode_t);
+ up_lease_arg->object = object;
+
+ GF_VALIDATE_OR_GOTO("glfs_recall_lease", up_lease_arg, out);
+
+ up_lease_arg->lease_type = recall_lease->lease_type;
+
+ up_arg->reason = GLFS_UPCALL_RECALL_LEASE;
+ up_arg->event = up_lease_arg;
+ up_arg->free_event = glfs_free_upcall_lease;
+
+ ret = 0;
+
+out:
+ if (ret) {
+ /* Close p_object and oldp_object as well if being referenced.*/
+ if (object)
+ glfs_h_close(object);
+
+ /* Set reason to prevent applications from using ->event */
+ up_arg->reason = GF_UPCALL_EVENT_NULL;
+ }
+ return ret;
+}
+
+static int
+upcall_syncop_args_free(struct upcall_syncop_args *args)
+{
+ dict_t *dict = NULL;
+ struct gf_upcall *upcall_data = NULL;
+
+ if (args) {
+ upcall_data = &args->upcall_data;
+ switch (upcall_data->event_type) {
+ case GF_UPCALL_CACHE_INVALIDATION:
+ dict = ((struct gf_upcall_cache_invalidation *)(upcall_data
+ ->data))
+ ->dict;
+ break;
+ case GF_UPCALL_RECALL_LEASE:
+ dict = ((struct gf_upcall_recall_lease *)(upcall_data->data))
+ ->dict;
+ break;
+ }
+ if (dict)
+ dict_unref(dict);
+
+ GF_FREE(upcall_data->client_uid);
+ GF_FREE(upcall_data->data);
+ }
+ GF_FREE(args);
+ return 0;
+}
+
+static int
+glfs_upcall_syncop_cbk(int ret, call_frame_t *frame, void *opaque)
+{
+ struct upcall_syncop_args *args = opaque;
+
+ (void)upcall_syncop_args_free(args);
+
+ return 0;
+}
+
+static int
+glfs_cbk_upcall_syncop(void *opaque)
+{
+ struct upcall_syncop_args *args = opaque;
+ struct gf_upcall *upcall_data = NULL;
+ struct glfs_upcall *up_arg = NULL;
+ struct glfs *fs;
+ int ret = -1;
+
+ fs = args->fs;
+ upcall_data = &args->upcall_data;
+
+ if (!upcall_data) {
+ goto out;
+ }
+
+ up_arg = GLFS_CALLOC(1, sizeof(struct gf_upcall), glfs_release_upcall,
+ glfs_mt_upcall_entry_t);
+ if (!up_arg) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ switch (upcall_data->event_type) {
+ case GF_UPCALL_CACHE_INVALIDATION:
+ ret = glfs_h_poll_cache_invalidation(fs, up_arg, upcall_data);
+ break;
+ case GF_UPCALL_RECALL_LEASE:
+ ret = glfs_recall_lease_upcall(fs, up_arg, upcall_data);
+ break;
+ default:
+ errno = EINVAL;
+ }
+
+ /* It could so happen that the file which got
+ * upcall notification may have got deleted by
+ * the same client. In such cases up_arg->reason
+ * is set to GLFS_UPCALL_EVENT_NULL. No need to
+ * send upcall then
+ */
+ if (up_arg->reason == GLFS_UPCALL_EVENT_NULL) {
+ gf_smsg(THIS->name, GF_LOG_DEBUG, errno,
+ API_MSG_UPCALL_EVENT_NULL_RECEIVED, NULL);
+ ret = 0;
+ GLFS_FREE(up_arg);
+ goto out;
+ } else if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ENTRY, NULL);
+ GLFS_FREE(up_arg);
+ goto out;
+ }
+
+ if (fs->up_cbk && up_arg)
+ (fs->up_cbk)(up_arg, fs->up_data);
+
+ /* application takes care of calling glfs_free on up_arg post
+ * their processing */
+
+out:
+ return ret;
+}
+
+static struct gf_upcall_cache_invalidation *
+gf_copy_cache_invalidation(struct gf_upcall_cache_invalidation *src)
+{
+ struct gf_upcall_cache_invalidation *dst = NULL;
+
+ if (!src)
+ goto out;
+
+ dst = GF_CALLOC(1, sizeof(struct gf_upcall_cache_invalidation),
+ glfs_mt_upcall_entry_t);
+
+ if (!dst) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ dst->flags = src->flags;
+ dst->expire_time_attr = src->expire_time_attr;
+ dst->stat = src->stat;
+ dst->p_stat = src->p_stat;
+ dst->oldp_stat = src->oldp_stat;
+
+ if (src->dict)
+ dst->dict = dict_copy_with_ref(src->dict, NULL);
+
+ return dst;
+out:
+ return NULL;
+}
+
+static struct gf_upcall_recall_lease *
+gf_copy_recall_lease(struct gf_upcall_recall_lease *src)
+{
+ struct gf_upcall_recall_lease *dst = NULL;
+
+ if (!src)
+ goto out;
+
+ dst = GF_CALLOC(1, sizeof(struct gf_upcall_recall_lease),
+ glfs_mt_upcall_entry_t);
+
+ if (!dst) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED, "entry",
+ NULL);
+ goto out;
+ }
+
+ dst->lease_type = src->lease_type;
+ memcpy(dst->tid, src->tid, 16);
+
+ if (src->dict)
+ dst->dict = dict_copy_with_ref(src->dict, NULL);
+
+ return dst;
+out:
+ return NULL;
+}
+
+static struct upcall_syncop_args *
+upcall_syncop_args_init(struct glfs *fs, struct gf_upcall *upcall_data)
+{
+ struct upcall_syncop_args *args = NULL;
+ int ret = -1;
+ struct gf_upcall *t_data = NULL;
+
+ if (!fs || !upcall_data)
+ goto out;
+
+ args = GF_CALLOC(1, sizeof(struct upcall_syncop_args),
+ glfs_mt_upcall_entry_t);
+ if (!args) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_ALLOC_FAILED,
+ "syncop args", NULL);
+ goto out;
+ }
+
+ /* Note: we are not taking any ref on fs here.
+ * Ideally applications have to unregister for upcall events
+ * or stop polling for upcall events before performing
+ * glfs_fini. And as for outstanding synctasks created, we wait
+ * for all syncenv threads to finish tasks before cleaning up the
+ * fs->ctx. Hence it seems safe to process these callback
+ * notification without taking any lock/ref.
+ */
+ args->fs = fs;
+ t_data = &(args->upcall_data);
+ t_data->client_uid = gf_strdup(upcall_data->client_uid);
+
+ gf_uuid_copy(t_data->gfid, upcall_data->gfid);
+ t_data->event_type = upcall_data->event_type;
+
+ switch (t_data->event_type) {
+ case GF_UPCALL_CACHE_INVALIDATION:
+ t_data->data = gf_copy_cache_invalidation(
+ (struct gf_upcall_cache_invalidation *)upcall_data->data);
+ break;
+ case GF_UPCALL_RECALL_LEASE:
+ t_data->data = gf_copy_recall_lease(
+ (struct gf_upcall_recall_lease *)upcall_data->data);
+ break;
+ }
+
+ if (!t_data->data)
+ goto out;
+
+ return args;
+out:
+ if (ret) {
+ if (args) {
+ GF_FREE(args->upcall_data.client_uid);
+ GF_FREE(args);
+ }
+ }
+
+ return NULL;
+}
+
+static void
+glfs_cbk_upcall_data(struct glfs *fs, struct gf_upcall *upcall_data)
+{
+ struct upcall_syncop_args *args = NULL;
+ int ret = -1;
+
+ if (!fs || !upcall_data)
+ goto out;
+
+ if (!(fs->upcall_events & upcall_data->event_type)) {
+ /* ignore events which application hasn't registered*/
+ goto out;
+ }
+
+ args = upcall_syncop_args_init(fs, upcall_data);
+
+ if (!args)
+ goto out;
+
+ ret = synctask_new(THIS->ctx->env, glfs_cbk_upcall_syncop,
+ glfs_upcall_syncop_cbk, NULL, args);
+ /* should we retry incase of failure? */
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_UPCALL_SYNCOP_FAILED,
+ "event_type=%d", upcall_data->event_type, "gfid=%s",
+ (char *)(upcall_data->gfid), NULL);
+ upcall_syncop_args_free(args);
+ }
+
+out:
+ return;
+}
+
+/*
+ * This routine is called in case of any notification received
+ * from the server. All the upcall events are queued up in a list
+ * to be read by the applications.
+ *
+ * In case if the application registers a cbk function, that shall
+ * be called by this routine in case of any event received.
+ * The cbk fn is responsible for notifying the
+ * applications the way it desires for each event queued (for eg.,
+ * can raise a signal or broadcast a cond variable etc.)
+ *
+ * Otherwise all the upcall events are queued up in a list
+ * to be read/polled by the applications.
+ */
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_process_upcall_event, 3.7.0)
+void
+priv_glfs_process_upcall_event(struct glfs *fs, void *data)
+{
+ glusterfs_ctx_t *ctx = NULL;
+ struct gf_upcall *upcall_data = NULL;
+
+ DECLARE_OLD_THIS;
+
+ gf_msg_debug(THIS->name, 0, "Upcall gfapi callback is called");
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, err);
+
+ if (!data)
+ goto out;
+
+ /* Unlike in I/O path, "glfs_fini" would not have freed
+ * 'fs' by the time we take lock as it waits for all epoll
+ * threads to exit including this
+ */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ ctx = fs->ctx;
+
+ /* if we're not interested in upcalls (anymore), skip them */
+ if (ctx->cleanup_started || !fs->cache_upcalls) {
+ pthread_mutex_unlock(&fs->mutex);
+ goto out;
+ }
+
+ fs->pin_refcnt++;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ upcall_data = (struct gf_upcall *)data;
+
+ gf_msg_trace(THIS->name, 0, "Upcall gfapi gfid = %s",
+ (char *)(upcall_data->gfid));
+
+ /* *
+ * TODO: RECALL LEASE for each glfd
+ *
+ * In case of RECALL_LEASE, we could associate separate
+ * cbk function for each glfd either by
+ * - extending pub_glfs_lease to accept new args (recall_cbk_fn, cookie)
+ * - or by defining new API "glfs_register_recall_cbk_fn (glfd,
+ * recall_cbk_fn, cookie) . In such cases, flag it and instead of calling
+ * below upcall functions, define a new one to go through the glfd list and
+ * invoke each of theirs recall_cbk_fn.
+ * */
+
+ if (fs->up_cbk) { /* upcall cbk registered */
+ (void)glfs_cbk_upcall_data(fs, upcall_data);
+ } else {
+ (void)glfs_enqueue_upcall_data(fs, upcall_data);
+ }
+
+ pthread_mutex_lock(&fs->mutex);
+ {
+ fs->pin_refcnt--;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+out:
+ __GLFS_EXIT_FS;
+err:
+ return;
+}
+
+ssize_t
+glfs_anonymous_pwritev(struct glfs *fs, struct glfs_object *object,
+ const struct iovec *iovec, int iovcnt, off_t offset,
+ int flags)
+{
+ xlator_t *subvol = NULL;
+ struct iobref *iobref = NULL;
+ struct iobuf *iobuf = NULL;
+ struct iovec iov = {
+ 0,
+ };
+ inode_t *inode = NULL;
+ fd_t *fd = NULL;
+ int ret = -1;
+ size_t size = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ ret = -1;
+ errno = ESTALE;
+ goto out;
+ }
+
+ fd = fd_anonymous(inode);
+ if (!fd) {
+ ret = -1;
+ gf_smsg("gfapi", GF_LOG_ERROR, ENOMEM, API_MSG_FDCREATE_FAILED, NULL);
+ errno = ENOMEM;
+ goto out;
+ }
+
+ size = iov_length(iovec, iovcnt);
+
+ iobuf = iobuf_get2(subvol->ctx->iobuf_pool, size);
+ if (!iobuf) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ iobref = iobref_new();
+ if (!iobref) {
+ iobuf_unref(iobuf);
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ ret = iobref_add(iobref, iobuf);
+ if (ret) {
+ iobuf_unref(iobuf);
+ iobref_unref(iobref);
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ iov_unload(iobuf_ptr(iobuf), iovec, iovcnt);
+
+ iov.iov_base = iobuf_ptr(iobuf);
+ iov.iov_len = size;
+
+ /* TODO : set leaseid */
+ ret = syncop_writev(subvol, fd, &iov, 1, offset, iobref, flags, NULL, NULL,
+ NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ iobuf_unref(iobuf);
+ iobref_unref(iobref);
+
+ if (ret <= 0)
+ goto out;
+
+out:
+
+ if (fd)
+ fd_unref(fd);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+ssize_t
+glfs_anonymous_preadv(struct glfs *fs, struct glfs_object *object,
+ const struct iovec *iovec, int iovcnt, off_t offset,
+ int flags)
+{
+ xlator_t *subvol = NULL;
+ struct iovec *iov = NULL;
+ struct iobref *iobref = NULL;
+ inode_t *inode = NULL;
+ fd_t *fd = NULL;
+ int cnt = 0;
+ ssize_t ret = -1;
+ ssize_t size = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ ret = -1;
+ errno = ESTALE;
+ goto out;
+ }
+
+ fd = fd_anonymous(inode);
+ if (!fd) {
+ ret = -1;
+ gf_smsg("gfapi", GF_LOG_ERROR, ENOMEM, API_MSG_FDCREATE_FAILED, NULL);
+ errno = ENOMEM;
+ goto out;
+ }
+
+ size = iov_length(iovec, iovcnt);
+
+ /* TODO : set leaseid */
+ ret = syncop_readv(subvol, fd, size, offset, flags, &iov, &cnt, &iobref,
+ NULL, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret <= 0)
+ goto out;
+
+ size = iov_copy(iovec, iovcnt, iov, cnt);
+
+ ret = size;
+out:
+ if (iov)
+ GF_FREE(iov);
+ if (iobref)
+ iobref_unref(iobref);
+ if (fd)
+ fd_unref(fd);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+static void
+glfs_release_xreaddirp_stat(void *ptr)
+{
+ struct glfs_xreaddirp_stat *to_free = ptr;
+
+ if (to_free->object)
+ glfs_h_close(to_free->object);
+}
+
+/*
+ * Given glfd of a directory, this function does readdirp and returns
+ * xstat along with dirents.
+ */
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_xreaddirplus_r, 3.11.0)
+int
+pub_glfs_xreaddirplus_r(struct glfs_fd *glfd, uint32_t flags,
+ struct glfs_xreaddirp_stat **xstat_p,
+ struct dirent *ext, struct dirent **res)
+{
+ int ret = -1;
+ gf_dirent_t *entry = NULL;
+ struct dirent *buf = NULL;
+ struct glfs_xreaddirp_stat *xstat = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ GF_VALIDATE_OR_GOTO(THIS->name, xstat_p, out);
+ GF_VALIDATE_OR_GOTO(THIS->name, res, out);
+
+ errno = 0;
+
+ if (ext)
+ buf = ext;
+ else
+ buf = glfs_readdirbuf_get(glfd);
+
+ if (!buf)
+ goto out;
+
+ xstat = GLFS_CALLOC(1, sizeof(struct glfs_xreaddirp_stat),
+ glfs_release_xreaddirp_stat, glfs_mt_xreaddirp_stat_t);
+
+ if (!xstat)
+ goto out;
+
+ /* this is readdirplus operation */
+ entry = glfd_entry_next(glfd, 1);
+
+ /* XXX: Ideally when we reach EOD, errno should have been
+ * set to ENOENT. But that doesn't seem to be the case.
+ *
+ * The only way to confirm if its EOD at this point is that
+ * errno == 0 and entry == NULL
+ */
+ if (errno)
+ goto out;
+
+ if (!entry) {
+ /* reached EOD, ret = 0 */
+ ret = 0;
+ *res = NULL;
+ *xstat_p = NULL;
+
+ /* free xstat as applications shall not be using it */
+ GLFS_FREE(xstat);
+
+ goto out;
+ }
+
+ *res = buf;
+ gf_dirent_to_dirent(entry, buf);
+
+ if (flags & GFAPI_XREADDIRP_STAT) {
+ glfs_iatt_to_stat(glfd->fs, &entry->d_stat, &xstat->st);
+ xstat->flags_handled |= GFAPI_XREADDIRP_STAT;
+ }
+
+ if ((flags & GFAPI_XREADDIRP_HANDLE) &&
+ /* skip . and .. */
+ strcmp(buf->d_name, ".") && strcmp(buf->d_name, "..")) {
+ /* Now create object.
+ * We can use "glfs_h_find_handle" as well as inodes would have
+ * already got linked as part of 'gf_link_inodes_from_dirent' */
+ xstat->object = glfs_h_create_from_handle(
+ glfd->fs, entry->d_stat.ia_gfid, GFAPI_HANDLE_LENGTH, NULL);
+
+ if (xstat->object) { /* success */
+ /* note: xstat->object->inode->ref is taken
+ * This shall be unref'ed when application does
+ * glfs_free(xstat) */
+ xstat->flags_handled |= GFAPI_XREADDIRP_HANDLE;
+ }
+ }
+
+ ret = xstat->flags_handled;
+ *xstat_p = xstat;
+
+ gf_msg_debug(THIS->name, 0,
+ "xreaddirp- requested_flags (%x) , processed_flags (%x)",
+ flags, xstat->flags_handled);
+
+out:
+ GF_REF_PUT(glfd);
+
+ if (ret < 0) {
+ gf_smsg(THIS->name, GF_LOG_WARNING, errno, API_MSG_XREADDIRP_R_FAILED,
+ "reason=%s", strerror(errno), NULL);
+
+ if (xstat)
+ GLFS_FREE(xstat);
+ }
+
+ __GLFS_EXIT_FS;
+
+ return ret;
+
+invalid_fs:
+ return -1;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_xreaddirplus_get_stat, 3.11.0)
+struct stat *
+pub_glfs_xreaddirplus_get_stat(struct glfs_xreaddirp_stat *xstat)
+{
+ GF_VALIDATE_OR_GOTO("glfs_xreaddirplus_get_stat", xstat, out);
+
+ if (!xstat->flags_handled & GFAPI_XREADDIRP_STAT)
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_FLAGS_HANDLE,
+ "GFAPI_XREADDIRP_STAT"
+ "xstat=%p",
+ xstat, "handles=%x", xstat->flags_handled, NULL);
+ return &xstat->st;
+
+out:
+ return NULL;
+}
+
+void
+gf_lease_to_glfs_lease(struct gf_lease *gf_lease, struct glfs_lease *lease)
+{
+ u_int lease_type = gf_lease->lease_type;
+ lease->cmd = gf_lease->cmd;
+ lease->lease_type = lease_type;
+ memcpy(lease->lease_id, gf_lease->lease_id, LEASE_ID_SIZE);
+}
+
+void
+glfs_lease_to_gf_lease(struct glfs_lease *lease, struct gf_lease *gf_lease)
+{
+ u_int lease_type = lease->lease_type;
+ gf_lease->cmd = lease->cmd;
+ gf_lease->lease_type = lease_type;
+ memcpy(gf_lease->lease_id, lease->lease_id, LEASE_ID_SIZE);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_lease, 4.0.0)
+int
+pub_glfs_lease(struct glfs_fd *glfd, struct glfs_lease *lease,
+ glfs_recall_cbk fn, void *data)
+{
+ int ret = -1;
+ loc_t loc = {
+ 0,
+ };
+ xlator_t *subvol = NULL;
+ fd_t *fd = NULL;
+ struct gf_lease gf_lease = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FD(glfd, invalid_fs);
+
+ GF_REF_GET(glfd);
+
+ if (!is_valid_lease_id(lease->lease_id)) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ subvol = glfs_active_subvol(glfd->fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ fd = glfs_resolve_fd(glfd->fs, subvol, glfd);
+ if (!fd) {
+ ret = -1;
+ errno = EBADFD;
+ goto out;
+ }
+
+ switch (lease->lease_type) {
+ case GLFS_RD_LEASE:
+ if ((fd->flags != O_RDONLY) && !(fd->flags & O_RDWR)) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+ break;
+ case GLFS_RW_LEASE:
+ if (!((fd->flags & O_WRONLY) || (fd->flags & O_RDWR))) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+ break;
+ default:
+ if (lease->cmd != GLFS_GET_LEASE) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+ break;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(fd->inode, loc, out);
+
+ glfs_lease_to_gf_lease(lease, &gf_lease);
+
+ ret = syncop_lease(subvol, &loc, &gf_lease, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ gf_lease_to_glfs_lease(&gf_lease, lease);
+
+ /* TODO: Add leases for client replay
+ if (ret == 0 && (cmd == F_SETLK || cmd == F_SETLKW))
+ fd_lk_insert_and_merge (fd, cmd, &saved_flock);
+ */
+ if (ret == 0) {
+ ret = fd_ctx_set(glfd->fd, subvol, (uint64_t)(long)glfd);
+ if (ret) {
+ gf_smsg(subvol->name, GF_LOG_ERROR, ENOMEM,
+ API_MSG_FDCTX_SET_FAILED, "fd=%p", glfd->fd, NULL);
+ goto out;
+ }
+ glfd->cbk = fn;
+ glfd->cookie = data;
+ }
+
+out:
+
+ if (glfd)
+ GF_REF_PUT(glfd);
+
+ if (subvol)
+ glfs_subvol_done(glfd->fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
new file mode 100644
index 00000000000..53c2ee896f9
--- /dev/null
+++ b/api/src/glfs-handleops.c
@@ -0,0 +1,2655 @@
+/*
+ * Copyright (c) 2013-2018 Red Hat, Inc. <http://www.redhat.com>
+ * This file is part of GlusterFS.
+ *
+ * This file is licensed to you under your choice of the GNU Lesser
+ * General Public License, version 3 or any later version (LGPLv3 or
+ * later), or the GNU General Public License, version 2 (GPLv2), in all
+ * cases as published by the Free Software Foundation.
+ */
+
+#include "glfs-internal.h"
+#include "glfs-mem-types.h"
+#include <glusterfs/syncop.h>
+#include "glfs.h"
+#include "glfs-handles.h"
+#include "gfapi-messages.h"
+
+int
+glfs_listxattr_process(void *value, size_t size, dict_t *xattr);
+
+void
+glfs_iatt_from_stat(struct stat *stat, int valid, struct iatt *iatt,
+ int *glvalid)
+{
+ /* validate in args */
+ if ((stat == NULL) || (iatt == NULL) || (glvalid == NULL)) {
+ errno = EINVAL;
+ return;
+ }
+
+ *glvalid = 0;
+
+ if (valid & GFAPI_SET_ATTR_MODE) {
+ iatt->ia_prot = ia_prot_from_st_mode(stat->st_mode);
+ *glvalid |= GF_SET_ATTR_MODE;
+ }
+
+ if (valid & GFAPI_SET_ATTR_UID) {
+ iatt->ia_uid = stat->st_uid;
+ *glvalid |= GF_SET_ATTR_UID;
+ }
+
+ if (valid & GFAPI_SET_ATTR_GID) {
+ iatt->ia_gid = stat->st_gid;
+ *glvalid |= GF_SET_ATTR_GID;
+ }
+
+ if (valid & GFAPI_SET_ATTR_ATIME) {
+ iatt->ia_atime = stat->st_atime;
+ iatt->ia_atime_nsec = ST_ATIM_NSEC(stat);
+ *glvalid |= GF_SET_ATTR_ATIME;
+ }
+
+ if (valid & GFAPI_SET_ATTR_MTIME) {
+ iatt->ia_mtime = stat->st_mtime;
+ iatt->ia_mtime_nsec = ST_MTIM_NSEC(stat);
+ *glvalid |= GF_SET_ATTR_MTIME;
+ }
+
+ return;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_lookupat, 3.7.4)
+struct glfs_object *
+pub_glfs_h_lookupat(struct glfs *fs, struct glfs_object *parent,
+ const char *path, struct stat *stat, int follow)
+{
+ int ret = 0;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ struct iatt iatt = {
+ 0,
+ };
+ struct glfs_object *object = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if (path == NULL) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ if (parent) {
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+ }
+
+ /* fop/op */
+ ret = glfs_resolve_at(fs, subvol, inode, path, &loc, &iatt, follow, 0);
+
+ /* populate out args */
+ if (!ret) {
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC(glfs_h_lookupat34, glfs_h_lookupat, 3.4.2)
+struct glfs_object *
+pub_glfs_h_lookupat34(struct glfs *fs, struct glfs_object *parent,
+ const char *path, struct stat *stat)
+{
+ return pub_glfs_h_lookupat(fs, parent, path, stat, 0);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_statfs, 3.7.0)
+int
+pub_glfs_h_statfs(struct glfs *fs, struct glfs_object *object,
+ struct statvfs *statvfs)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL || statvfs == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_statfs(subvol, &loc, statvfs, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ loc_wipe(&loc);
+
+out:
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_stat, 3.4.2)
+int
+pub_glfs_h_stat(struct glfs *fs, struct glfs_object *object, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_stat(subvol, &loc, &iatt, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (!ret && stat) {
+ glfs_iatt_to_stat(fs, &iatt, stat);
+ }
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_getattrs, 3.4.2)
+int
+pub_glfs_h_getattrs(struct glfs *fs, struct glfs_object *object,
+ struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ struct iatt iatt = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ ret = 0;
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* fop/op */
+ ret = glfs_resolve_base(fs, subvol, inode, &iatt);
+
+ /* populate out args */
+ if (!ret && stat) {
+ glfs_iatt_to_stat(fs, &iatt, stat);
+ }
+
+out:
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_h_getxattrs_common(struct glfs *fs, struct glfs_object *object,
+ dict_t **xattr, const char *name,
+ gf_boolean_t is_listxattr)
+{
+ int ret = 0;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!is_listxattr) {
+ if (!name || *name == '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+ }
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ ret = syncop_getxattr(subvol, &loc, xattr, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_getxattrs, 3.5.1)
+int
+pub_glfs_h_getxattrs(struct glfs *fs, struct glfs_object *object,
+ const char *name, void *value, size_t size)
+{
+ int ret = -1;
+ dict_t *xattr = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ ret = glfs_h_getxattrs_common(fs, object, &xattr, name, (name == NULL));
+ if (ret)
+ goto out;
+
+ /* If @name is NULL, means get all the xattrs (i.e listxattr). */
+ if (name)
+ ret = glfs_getxattr_process(value, size, xattr, name);
+ else
+ ret = glfs_listxattr_process(value, size, xattr);
+
+out:
+ if (xattr)
+ dict_unref(xattr);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_setattrs, 3.4.2)
+int
+pub_glfs_h_setattrs(struct glfs *fs, struct glfs_object *object,
+ struct stat *stat, int valid)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ int glvalid = 0;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL) || (stat == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* map valid masks from in args */
+ glfs_iatt_from_stat(stat, valid, &iatt, &glvalid);
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_setattr(subvol, &loc, &iatt, glvalid, 0, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_setxattrs, 3.5.0)
+int
+pub_glfs_h_setxattrs(struct glfs *fs, struct glfs_object *object,
+ const char *name, const void *value, size_t size,
+ int flags)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ dict_t *xattr = NULL;
+ void *value_cp = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL) || (name == NULL) || (value == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (!name || *name == '\0') {
+ errno = EINVAL;
+ return -1;
+ }
+
+ if (strlen(name) > GF_XATTR_NAME_MAX) {
+ errno = ENAMETOOLONG;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ value_cp = gf_memdup(value, size);
+ GF_CHECK_ALLOC_AND_LOG(subvol->name, value_cp, ret,
+ "Failed to"
+ " duplicate setxattr value",
+ out);
+
+ xattr = dict_for_key_value(name, value_cp, size, _gf_false);
+ if (!xattr) {
+ GF_FREE(value_cp);
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_setxattr(subvol, &loc, xattr, flags, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (xattr)
+ dict_unref(xattr);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_removexattrs, 3.5.1)
+int
+pub_glfs_h_removexattrs(struct glfs *fs, struct glfs_object *object,
+ const char *name)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL) || (name == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_removexattr(subvol, &loc, name, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_open, 3.4.2)
+struct glfs_fd *
+pub_glfs_h_open(struct glfs *fs, struct glfs_object *object, int flags)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ dict_t *fop_attr = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* check types to open */
+ if (IA_ISDIR(inode->ia_type)) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ if (!IA_ISREG(inode->ia_type)) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ glfd->fd = fd_create(inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ glfd->fd->flags = flags;
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ ret = syncop_open(subvol, &loc, flags, glfd->fd, fop_attr, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ glfd->fd->flags = flags;
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ glfd = NULL;
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return glfd;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat, 3.4.2)
+struct glfs_object *
+pub_glfs_h_creat(struct glfs *fs, struct glfs_object *parent, const char *path,
+ int flags, mode_t mode, struct stat *stat)
+{
+ int ret = -1;
+ fd_t *fd = NULL;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ struct glfs_object *object = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ ret = -1;
+ errno = ESTALE;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
+
+ fd = fd_create(loc.inode, getpid());
+ if (!fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ fd->flags = flags;
+
+ /* fop/op */
+ ret = syncop_create(subvol, &loc, flags, mode, fd, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0) {
+ ret = glfs_loc_link(&loc, &iatt);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+
+out:
+ if (ret && object != NULL) {
+ /* Release the held reference */
+ glfs_h_close(object);
+ object = NULL;
+ }
+
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ if (fd)
+ fd_unref(fd);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_creat_open, 6.6)
+struct glfs_object *
+pub_glfs_h_creat_open(struct glfs *fs, struct glfs_object *parent,
+ const char *path, int flags, mode_t mode,
+ struct stat *stat, struct glfs_fd **out_fd)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ struct glfs_object *object = NULL;
+ dict_t *fop_attr = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (parent == NULL) || (path == NULL) ||
+ (out_fd == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ ret = -1;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ glfd->fd = fd_create(loc.inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+ glfd->fd->flags = flags;
+
+ ret = get_fop_attr_thrd_key(&fop_attr);
+ if (ret)
+ gf_msg_debug("gfapi", 0, "Getting leaseid from thread failed");
+
+ /* fop/op */
+ ret = syncop_create(subvol, &loc, flags, mode, glfd->fd, &iatt, xattr_req,
+ NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0) {
+ glfd->fd->flags = flags;
+
+ ret = glfs_loc_link(&loc, &iatt);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+
+out:
+ if (ret && object != NULL) {
+ /* Release the held reference */
+ glfs_h_close(object);
+ object = NULL;
+ }
+
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (fop_attr)
+ dict_unref(fop_attr);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ *out_fd = glfd;
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_mkdir, 3.4.2)
+struct glfs_object *
+pub_glfs_h_mkdir(struct glfs *fs, struct glfs_object *parent, const char *path,
+ mode_t mode, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ struct glfs_object *object = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
+
+ /* fop/op */
+ ret = syncop_mkdir(subvol, &loc, mode, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0) {
+ ret = glfs_loc_link(&loc, &iatt);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+
+out:
+ if (ret && object != NULL) {
+ glfs_h_close(object);
+ object = NULL;
+ }
+
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_mknod, 3.4.2)
+struct glfs_object *
+pub_glfs_h_mknod(struct glfs *fs, struct glfs_object *parent, const char *path,
+ mode_t mode, dev_t dev, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ struct glfs_object *object = NULL;
+
+ /* validate in args */
+ if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, path);
+
+ /* fop/op */
+ ret = syncop_mknod(subvol, &loc, mode, dev, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0) {
+ ret = glfs_loc_link(&loc, &iatt);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+out:
+ if (ret && object != NULL) {
+ glfs_h_close(object);
+ object = NULL;
+ }
+
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_unlink, 3.4.2)
+int
+pub_glfs_h_unlink(struct glfs *fs, struct glfs_object *parent, const char *path)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (parent == NULL) || (path == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ ret = glfs_resolve_at(fs, subvol, inode, path, &loc, NULL, 0, 0);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (!IA_ISDIR(loc.inode->ia_type)) {
+ ret = syncop_unlink(subvol, &loc, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret != 0) {
+ goto out;
+ }
+ } else {
+ ret = syncop_rmdir(subvol, &loc, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret != 0) {
+ goto out;
+ }
+ }
+
+ if (ret == 0)
+ ret = glfs_loc_unlink(&loc);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_opendir, 3.4.2)
+struct glfs_fd *
+pub_glfs_h_opendir(struct glfs *fs, struct glfs_object *object)
+{
+ int ret = -1;
+ struct glfs_fd *glfd = NULL;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ if (!IA_ISDIR(inode->ia_type)) {
+ ret = -1;
+ errno = ENOTDIR;
+ goto out;
+ }
+
+ glfd = glfs_fd_new(fs);
+ if (!glfd)
+ goto out;
+
+ INIT_LIST_HEAD(&glfd->entries);
+
+ glfd->fd = fd_create(inode, getpid());
+ if (!glfd->fd) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_opendir(subvol, &loc, glfd->fd, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (ret && glfd) {
+ GF_REF_PUT(glfd);
+ glfd = NULL;
+ } else if (glfd) {
+ glfd_set_state_bind(glfd);
+ }
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return glfd;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_access, 3.6.0)
+int
+pub_glfs_h_access(struct glfs *fs, struct glfs_object *object, int mask)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return ret;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+
+ ret = syncop_access(subvol, &loc, mask, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_extract_handle, 3.4.2)
+ssize_t
+pub_glfs_h_extract_handle(struct glfs_object *object, unsigned char *handle,
+ int len)
+{
+ ssize_t ret = -1;
+
+ /* validate in args */
+ if (object == NULL) {
+ errno = EINVAL;
+ goto out;
+ }
+
+ if (!handle || !len) {
+ ret = GFAPI_HANDLE_LENGTH;
+ goto out;
+ }
+
+ if (len < GFAPI_HANDLE_LENGTH) {
+ errno = ERANGE;
+ goto out;
+ }
+
+ memcpy(handle, object->gfid, GFAPI_HANDLE_LENGTH);
+
+ ret = GFAPI_HANDLE_LENGTH;
+
+out:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_create_from_handle, 3.4.2)
+struct glfs_object *
+pub_glfs_h_create_from_handle(struct glfs *fs, unsigned char *handle, int len,
+ struct stat *stat)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ struct iatt iatt = {
+ 0,
+ };
+ inode_t *newinode = NULL;
+ xlator_t *subvol = NULL;
+ struct glfs_object *object = NULL;
+ uint64_t ctx_value = LOOKUP_NOT_NEEDED;
+ gf_boolean_t lookup_needed = _gf_false;
+
+ /* validate in args */
+ if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ memcpy(loc.gfid, handle, GFAPI_HANDLE_LENGTH);
+
+ /* make sure the gfid received is valid */
+ GF_VALIDATE_OR_GOTO("glfs_h_create_from_handle",
+ !(gf_uuid_is_null(loc.gfid)), out);
+
+ newinode = inode_find(subvol->itable, loc.gfid);
+ if (newinode) {
+ if (!stat) /* No need of lookup */
+ goto found;
+
+ lookup_needed = inode_needs_lookup(newinode, THIS);
+ if (lookup_needed) {
+ loc.inode = newinode;
+ } else {
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(newinode, loc, fill_out);
+
+ /* fop/op */
+ ret = syncop_stat(subvol, &loc, &iatt, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret) {
+ fill_out:
+ /* Drop the reference hold in inode_find */
+ inode_unref(newinode);
+ goto out;
+ }
+
+ glfs_iatt_to_stat(fs, &iatt, stat);
+ goto found;
+ }
+ } else {
+ loc.inode = inode_new(subvol->itable);
+ if (!loc.inode) {
+ errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ ret = syncop_lookup(subvol, &loc, &iatt, 0, 0, 0);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret) {
+ gf_smsg(subvol->name, GF_LOG_WARNING, errno,
+ API_MSG_INODE_REFRESH_FAILED, "gfid=%s", uuid_utoa(loc.gfid),
+ "error=%s", strerror(errno), NULL);
+ goto out;
+ }
+
+ newinode = inode_link(loc.inode, 0, 0, &iatt);
+ if (newinode) {
+ if (newinode == loc.inode) {
+ inode_ctx_set(newinode, THIS, &ctx_value);
+ }
+ inode_lookup(newinode);
+ } else {
+ gf_smsg(subvol->name, GF_LOG_WARNING, errno, API_MSG_INODE_LINK_FAILED,
+ "gfid=%s", uuid_utoa(loc.gfid), NULL);
+ goto out;
+ }
+
+ /* populate stat */
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+found:
+ object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
+ if (object == NULL) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ /* populate the return object */
+ object->inode = newinode;
+ gf_uuid_copy(object->gfid, object->inode->gfid);
+
+out:
+ /* TODO: Check where the inode ref is being held? */
+ loc_wipe(&loc);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_close, 3.4.2)
+int
+pub_glfs_h_close(struct glfs_object *object)
+{
+ /* since glfs_h_* objects hold a reference to inode
+ * it is safe to keep lookup count to '0' */
+ inode_forget(object->inode, 0);
+ inode_unref(object->inode);
+ GF_FREE(object);
+
+ return 0;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_truncate, 3.4.2)
+int
+pub_glfs_h_truncate(struct glfs *fs, struct glfs_object *object, off_t offset)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if (object == NULL) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_truncate(subvol, &loc, (off_t)offset, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0)
+ ret = glfs_loc_unlink(&loc);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_symlink, 3.4.2)
+struct glfs_object *
+pub_glfs_h_symlink(struct glfs *fs, struct glfs_object *parent,
+ const char *name, const char *data, struct stat *stat)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ struct glfs_object *object = NULL;
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((parent == NULL) || (name == NULL) || (data == NULL)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, parent);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_PINODE(inode, loc, ret, errno, out, name);
+
+ /* fop/op */
+ ret = syncop_symlink(subvol, &loc, data, &iatt, xattr_req, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret == 0) {
+ ret = glfs_loc_link(&loc, &iatt);
+ if (ret != 0) {
+ goto out;
+ }
+
+ if (stat)
+ glfs_iatt_to_stat(fs, &iatt, stat);
+
+ ret = glfs_create_object(&loc, &object);
+ }
+
+out:
+ if (ret && object != NULL) {
+ pub_glfs_h_close(object);
+ object = NULL;
+ }
+
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (xattr_req)
+ dict_unref(xattr_req);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_readlink, 3.4.2)
+int
+pub_glfs_h_readlink(struct glfs *fs, struct glfs_object *object, char *buf,
+ size_t bufsiz)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ char *linkval = NULL;
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((object == NULL) || (buf == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ /* fop/op */
+ ret = syncop_readlink(subvol, &loc, &linkval, bufsiz, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ /* populate out args */
+ if (ret > 0)
+ memcpy(buf, linkval, ret);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (linkval)
+ GF_FREE(linkval);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_link, 3.4.2)
+int
+pub_glfs_h_link(struct glfs *fs, struct glfs_object *linksrc,
+ struct glfs_object *parent, const char *name)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ inode_t *pinode = NULL;
+ loc_t oldloc = {
+ 0,
+ };
+ loc_t newloc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((linksrc == NULL) || (parent == NULL) || (name == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, linksrc);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ if (inode->ia_type == IA_IFDIR) {
+ ret = -1;
+ errno = EISDIR;
+ goto out;
+ }
+
+ GLFS_LOC_FILL_INODE(inode, oldloc, out);
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ pinode = glfs_resolve_inode(fs, subvol, parent);
+ if (!pinode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* setup newloc based on parent */
+ newloc.parent = inode_ref(pinode);
+ newloc.name = name;
+ ret = glfs_loc_touchup(&newloc);
+ if (ret != 0) {
+ errno = EINVAL;
+ goto out;
+ }
+
+ /* Filling the inode of the hard link to be same as that of the
+ * original file
+ */
+ newloc.inode = inode_ref(inode);
+
+ /* fop/op */
+ ret = syncop_link(subvol, &oldloc, &newloc, &iatt, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret == 0)
+ ret = glfs_loc_link(&newloc, &iatt);
+out:
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+
+ if (inode)
+ inode_unref(inode);
+
+ if (pinode)
+ inode_unref(pinode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_rename, 3.4.2)
+int
+pub_glfs_h_rename(struct glfs *fs, struct glfs_object *olddir,
+ const char *oldname, struct glfs_object *newdir,
+ const char *newname)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *oldpinode = NULL;
+ inode_t *newpinode = NULL;
+ loc_t oldloc = {
+ 0,
+ };
+ loc_t newloc = {
+ 0,
+ };
+ struct iatt oldiatt = {
+ 0,
+ };
+ struct iatt newiatt = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+
+ /* validate in args */
+ if ((olddir == NULL) || (oldname == NULL) || (newdir == NULL) ||
+ (newname == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ oldpinode = glfs_resolve_inode(fs, subvol, olddir);
+ if (!oldpinode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ ret = glfs_resolve_at(fs, subvol, oldpinode, oldname, &oldloc, &oldiatt, 0,
+ 0);
+ if (ret != 0) {
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ newpinode = glfs_resolve_inode(fs, subvol, newdir);
+ if (!newpinode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ ret = glfs_resolve_at(fs, subvol, newpinode, newname, &newloc, &newiatt, 0,
+ 0);
+
+ if (ret && errno != ENOENT && newloc.parent)
+ goto out;
+
+ if (newiatt.ia_type != IA_INVAL) {
+ if ((oldiatt.ia_type == IA_IFDIR) != (newiatt.ia_type == IA_IFDIR)) {
+ /* Either both old and new must be dirs,
+ * or both must be non-dirs. Else, fail.
+ */
+ ret = -1;
+ errno = EEXIST;
+ goto out;
+ }
+ }
+
+ /* TODO: check if new or old is a prefix of the other, and fail EINVAL */
+
+ ret = syncop_rename(subvol, &oldloc, &newloc, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret == 0) {
+ inode_rename(oldloc.parent->table, oldloc.parent, oldloc.name,
+ newloc.parent, newloc.name, oldloc.inode, &oldiatt);
+
+ if (newloc.inode && !inode_has_dentry(newloc.inode))
+ inode_forget(newloc.inode, 0);
+ }
+
+out:
+ loc_wipe(&oldloc);
+ loc_wipe(&newloc);
+
+ if (oldpinode)
+ inode_unref(oldpinode);
+
+ if (newpinode)
+ inode_unref(newpinode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+/*
+ * Given a handle/gfid, find if the corresponding inode is present in
+ * the inode table. If yes create and return the corresponding glfs_object.
+ */
+struct glfs_object *
+glfs_h_find_handle(struct glfs *fs, unsigned char *handle, int len)
+{
+ inode_t *newinode = NULL;
+ xlator_t *subvol = NULL;
+ struct glfs_object *object = NULL;
+ uuid_t gfid;
+
+ /* validate in args */
+ if ((fs == NULL) || (handle == NULL) || (len != GFAPI_HANDLE_LENGTH)) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto out;
+ }
+
+ memcpy(gfid, handle, GFAPI_HANDLE_LENGTH);
+
+ /* make sure the gfid received is valid */
+ GF_VALIDATE_OR_GOTO("glfs_h_find_handle", !(gf_uuid_is_null(gfid)), out);
+
+ newinode = inode_find(subvol->itable, gfid);
+ if (!newinode) {
+ goto out;
+ }
+
+ object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
+ if (object == NULL) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ /* populate the return object. The ref taken here
+ * is un'refed when the application does glfs_h_close() */
+ object->inode = inode_ref(newinode);
+ gf_uuid_copy(object->gfid, object->inode->gfid);
+
+out:
+ /* inode_find takes a reference. Unref it. */
+ if (newinode)
+ inode_unref(newinode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return object;
+}
+
+static void
+glfs_free_upcall_inode(void *to_free)
+{
+ struct glfs_upcall_inode *arg = to_free;
+
+ if (!arg)
+ return;
+
+ if (arg->object)
+ glfs_h_close(arg->object);
+ if (arg->p_object)
+ glfs_h_close(arg->p_object);
+ if (arg->oldp_object)
+ glfs_h_close(arg->oldp_object);
+
+ GF_FREE(arg);
+}
+
+int
+glfs_h_poll_cache_invalidation(struct glfs *fs, struct glfs_upcall *up_arg,
+ struct gf_upcall *upcall_data)
+{
+ int ret = -1;
+ struct glfs_object *p_object = NULL;
+ struct glfs_object *oldp_object = NULL;
+ struct glfs_object *object = NULL;
+ struct gf_upcall_cache_invalidation *ca_data = NULL;
+ struct glfs_upcall_inode *up_inode_arg = NULL;
+
+ ca_data = upcall_data->data;
+ GF_VALIDATE_OR_GOTO("glfs_h_poll_cache_invalidation", ca_data, out);
+
+ object = glfs_h_find_handle(fs, upcall_data->gfid, GFAPI_HANDLE_LENGTH);
+ if (!object) {
+ /* The reason handle creation will fail is because we
+ * couldn't find the inode in the gfapi inode table.
+ *
+ * But since application would have taken inode_ref, the
+ * only case when this can happen is when it has closed
+ * the handle and hence will no more be interested in
+ * the upcall for this particular gfid.
+ */
+ gf_smsg(THIS->name, GF_LOG_DEBUG, errno, API_MSG_CREATE_HANDLE_FAILED,
+ "gfid=%s", uuid_utoa(upcall_data->gfid), NULL);
+ errno = ESTALE;
+ goto out;
+ }
+
+ up_inode_arg = GF_CALLOC(1, sizeof(struct glfs_upcall_inode),
+ glfs_mt_upcall_inode_t);
+ GF_VALIDATE_OR_GOTO("glfs_h_poll_cache_invalidation", up_inode_arg, out);
+
+ up_inode_arg->object = object;
+ up_inode_arg->flags = ca_data->flags;
+ up_inode_arg->expire_time_attr = ca_data->expire_time_attr;
+
+ /* XXX: Update stat as well in case of UP_*_TIMES.
+ * This will be addressed as part of INODE_UPDATE */
+ if (ca_data->flags & GFAPI_INODE_UPDATE_FLAGS) {
+ glfs_iatt_to_stat(fs, &ca_data->stat, &up_inode_arg->buf);
+ }
+
+ if (ca_data->flags & GFAPI_UP_PARENT_TIMES) {
+ p_object = glfs_h_find_handle(fs, ca_data->p_stat.ia_gfid,
+ GFAPI_HANDLE_LENGTH);
+ if (!p_object) {
+ gf_smsg(THIS->name, GF_LOG_DEBUG, errno,
+ API_MSG_CREATE_HANDLE_FAILED, "gfid=%s",
+ uuid_utoa(ca_data->p_stat.ia_gfid), NULL);
+ errno = ESTALE;
+ goto out;
+ }
+
+ glfs_iatt_to_stat(fs, &ca_data->p_stat, &up_inode_arg->p_buf);
+ }
+ up_inode_arg->p_object = p_object;
+
+ /* In case of RENAME, update old parent as well */
+ if (ca_data->flags & GFAPI_UP_RENAME) {
+ oldp_object = glfs_h_find_handle(fs, ca_data->oldp_stat.ia_gfid,
+ GFAPI_HANDLE_LENGTH);
+ if (!oldp_object) {
+ gf_smsg(THIS->name, GF_LOG_DEBUG, errno,
+ API_MSG_CREATE_HANDLE_FAILED, "gfid=%s",
+ uuid_utoa(ca_data->oldp_stat.ia_gfid), NULL);
+ errno = ESTALE;
+ /* By the time we receive upcall old parent_dir may
+ * have got removed. We still need to send upcall
+ * for the file/dir and current parent handles. */
+ up_inode_arg->oldp_object = NULL;
+ ret = 0;
+ }
+
+ glfs_iatt_to_stat(fs, &ca_data->oldp_stat, &up_inode_arg->oldp_buf);
+ }
+ up_inode_arg->oldp_object = oldp_object;
+
+ up_arg->reason = GLFS_UPCALL_INODE_INVALIDATE;
+ up_arg->event = up_inode_arg;
+ up_arg->free_event = glfs_free_upcall_inode;
+
+ ret = 0;
+
+out:
+ if (ret) {
+ /* Close p_object and oldp_object as well if being referenced.*/
+ if (object)
+ glfs_h_close(object);
+
+ /* Set reason to prevent applications from using ->event */
+ up_arg->reason = GLFS_UPCALL_EVENT_NULL;
+ GF_FREE(up_inode_arg);
+ }
+ return ret;
+}
+
+void
+glfs_release_upcall(void *ptr)
+{
+ struct glfs_upcall *to_free = ptr;
+
+ if (to_free->event)
+ to_free->free_event(to_free->event);
+}
+
+/*
+ * This API is used to poll for upcall events stored in the upcall list.
+ * Current users of this API is NFS-Ganesha. In case of any event received, it
+ * will be mapped appropriately into 'glfs_upcall' along with the handle object
+ * to be passed to NFS-Ganesha.
+ *
+ * On success, applications need to check if up_arg is not-NULL or errno is not
+ * ENOENT. glfs_upcall_get_reason() can be used to decide what kind of event
+ * has been received.
+ *
+ * Current supported upcall_events:
+ * GLFS_UPCALL_INODE_INVALIDATE
+ *
+ * After processing the event, applications need to free 'up_arg' by calling
+ * glfs_free().
+ *
+ * Also similar to I/Os, the application should ideally stop polling before
+ * calling glfs_fini(..). Hence making an assumption that 'fs' & ctx structures
+ * cannot be freed while in this routine.
+ */
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_poll_upcall, 3.7.16)
+int
+pub_glfs_h_poll_upcall(struct glfs *fs, struct glfs_upcall **up_arg)
+{
+ upcall_entry *u_list = NULL;
+ upcall_entry *tmp = NULL;
+ xlator_t *subvol = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ int ret = -1;
+ struct gf_upcall *upcall_data = NULL;
+
+ DECLARE_OLD_THIS;
+
+ if (!up_arg) {
+ errno = EINVAL;
+ goto err;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, err);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ errno = EIO;
+ goto restore;
+ }
+
+ /* Ideally applications should stop polling before calling
+ * 'glfs_fini'. Yet cross check if cleanup has started. */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ ctx = fs->ctx;
+
+ if (ctx->cleanup_started) {
+ pthread_mutex_unlock(&fs->mutex);
+ goto out;
+ }
+
+ fs->pin_refcnt++;
+
+ /* once we call this function, the applications seems to be
+ * interested in events, enable caching them */
+ fs->cache_upcalls = _gf_true;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ pthread_mutex_lock(&fs->upcall_list_mutex);
+ {
+ list_for_each_entry_safe(u_list, tmp, &fs->upcall_list, upcall_list)
+ {
+ list_del_init(&u_list->upcall_list);
+ upcall_data = &u_list->upcall_data;
+ break;
+ }
+ }
+ /* No other thread can delete this entry. So unlock it */
+ pthread_mutex_unlock(&fs->upcall_list_mutex);
+
+ if (upcall_data) {
+ switch (upcall_data->event_type) {
+ case GF_UPCALL_CACHE_INVALIDATION:
+ *up_arg = GLFS_CALLOC(1, sizeof(struct gf_upcall),
+ glfs_release_upcall,
+ glfs_mt_upcall_entry_t);
+ if (!*up_arg) {
+ errno = ENOMEM;
+ break; /* goto free u_list */
+ }
+
+ /* XXX: Need to revisit this to support
+ * GLFS_UPCALL_INODE_UPDATE if required. */
+ ret = glfs_h_poll_cache_invalidation(fs, *up_arg, upcall_data);
+ if (ret || (*up_arg)->reason == GLFS_UPCALL_EVENT_NULL) {
+ /* It could so happen that the file which got
+ * upcall notification may have got deleted by
+ * the same client. Irrespective of the error,
+ * return with an error or success+ENOENT. */
+ if ((*up_arg)->reason == GLFS_UPCALL_EVENT_NULL)
+ errno = ENOENT;
+
+ GLFS_FREE(*up_arg);
+ *up_arg = NULL;
+ }
+ break;
+ case GF_UPCALL_RECALL_LEASE:
+ gf_log("glfs_h_poll_upcall", GF_LOG_DEBUG,
+ "UPCALL_RECALL_LEASE is not implemented yet");
+ /* fallthrough till we support leases */
+ case GF_UPCALL_EVENT_NULL:
+ /* no 'default:' label, to force handling all upcall events */
+ errno = ENOENT;
+ break;
+ }
+
+ GF_FREE(u_list->upcall_data.data);
+ GF_FREE(u_list);
+ } else {
+ /* fs->upcall_list was empty, no upcall events cached */
+ errno = ENOENT;
+ }
+
+ ret = 0;
+
+out:
+ pthread_mutex_lock(&fs->mutex);
+ {
+ fs->pin_refcnt--;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ glfs_subvol_done(fs, subvol);
+
+restore:
+ __GLFS_EXIT_FS;
+err:
+ return ret;
+}
+
+static gf_boolean_t log_upcall370 = _gf_true; /* log once */
+
+/* The old glfs_h_poll_upcall interface requires intimate knowledge of the
+ * structures that are returned to the calling application. This is not
+ * recommended, as the returned structures need to returned correctly (handles
+ * closed, memory free'd with the unavailable GF_FREE(), and possibly more.)
+ *
+ * To the best of our knowledge, only NFS-Ganesha uses the upcall events
+ * through gfapi. We keep this backwards compatibility function around so that
+ * applications using the existing implementation do not break.
+ *
+ * WARNING: this function will be removed in the future.
+ */
+GFAPI_SYMVER_PUBLIC(glfs_h_poll_upcall370, glfs_h_poll_upcall, 3.7.0)
+int
+pub_glfs_h_poll_upcall370(struct glfs *fs, struct glfs_callback_arg *up_arg)
+{
+ struct glfs_upcall *upcall = NULL;
+ int ret = -1;
+
+ if (log_upcall370) {
+ log_upcall370 = _gf_false;
+ gf_log(THIS->name, GF_LOG_WARNING,
+ "this application is "
+ "compiled against an old version of libgfapi, it "
+ "should use glfs_free() to release the structure "
+ "returned by glfs_h_poll_upcall() - for more details, "
+ "see http://review.gluster.org/14701");
+ }
+
+ ret = pub_glfs_h_poll_upcall(fs, &upcall);
+ if (ret == 0) {
+ up_arg->fs = fs;
+ if ((errno == ENOENT) || !upcall || !upcall->event) {
+ up_arg->reason = GLFS_UPCALL_EVENT_NULL;
+ goto out;
+ }
+
+ up_arg->reason = upcall->reason;
+
+ if (upcall->reason == GLFS_UPCALL_INODE_INVALIDATE) {
+ struct glfs_callback_inode_arg *cb_inode = NULL;
+ struct glfs_upcall_inode *up_inode = NULL;
+
+ cb_inode = GF_CALLOC(1, sizeof(struct glfs_callback_inode_arg),
+ glfs_mt_upcall_inode_t);
+ if (!cb_inode) {
+ errno = ENOMEM;
+ ret = -1;
+ goto out;
+ }
+
+ up_inode = upcall->event;
+
+ /* copy attributes one by one, the memory layout might
+ * be different between the old glfs_callback_inode_arg
+ * and new glfs_upcall_inode */
+ cb_inode->object = up_inode->object;
+ cb_inode->flags = up_inode->flags;
+ memcpy(&cb_inode->buf, &up_inode->buf, sizeof(struct stat));
+ cb_inode->expire_time_attr = up_inode->expire_time_attr;
+ cb_inode->p_object = up_inode->p_object;
+ memcpy(&cb_inode->p_buf, &up_inode->p_buf, sizeof(struct stat));
+ cb_inode->oldp_object = up_inode->oldp_object;
+ memcpy(&cb_inode->oldp_buf, &up_inode->oldp_buf,
+ sizeof(struct stat));
+
+ up_arg->event_arg = cb_inode;
+ }
+ }
+
+out:
+ if (upcall) {
+ /* we can not use glfs_free() here, objects need to stay */
+ GF_FREE(upcall->event);
+ GF_FREE(upcall);
+ }
+
+ return ret;
+}
+
+#ifdef HAVE_ACL_LIBACL_H
+#include <glusterfs/glusterfs-acl.h>
+#include <acl/libacl.h>
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_set, 3.7.0)
+int
+pub_glfs_h_acl_set(struct glfs *fs, struct glfs_object *object,
+ const acl_type_t type, const acl_t acl)
+{
+ int ret = -1;
+ char *acl_s = NULL;
+ const char *acl_key = NULL;
+ struct glfs_object *new_object = NULL;
+
+ DECLARE_OLD_THIS;
+
+ if (!object || !acl) {
+ errno = EINVAL;
+ return ret;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ acl_key = gf_posix_acl_get_key(type);
+ if (!acl_key)
+ goto out;
+
+ acl_s = acl_to_any_text(acl, NULL, ',', TEXT_ABBREVIATE | TEXT_NUMERIC_IDS);
+ if (!acl_s)
+ goto out;
+
+ if (IA_ISLNK(object->inode->ia_type)) {
+ new_object = glfs_h_resolve_symlink(fs, object);
+ if (new_object == NULL)
+ goto out;
+ } else
+ new_object = object;
+
+ ret = pub_glfs_h_setxattrs(fs, new_object, acl_key, acl_s,
+ strlen(acl_s) + 1, 0);
+
+ acl_free(acl_s);
+
+out:
+ if (IA_ISLNK(object->inode->ia_type) && new_object)
+ glfs_h_close(new_object);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_get, 3.7.0)
+acl_t
+pub_glfs_h_acl_get(struct glfs *fs, struct glfs_object *object,
+ const acl_type_t type)
+{
+ int ret = 0;
+ acl_t acl = NULL;
+ char *acl_s = NULL;
+ dict_t *xattr = NULL;
+ const char *acl_key = NULL;
+ struct glfs_object *new_object = NULL;
+
+ DECLARE_OLD_THIS;
+
+ if (!object) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ acl_key = gf_posix_acl_get_key(type);
+ if (!acl_key)
+ goto out;
+
+ if (IA_ISLNK(object->inode->ia_type)) {
+ new_object = glfs_h_resolve_symlink(fs, object);
+ if (new_object == NULL)
+ goto out;
+ } else
+ new_object = object;
+
+ ret = glfs_h_getxattrs_common(fs, new_object, &xattr, acl_key, _gf_false);
+ if (ret)
+ goto out;
+
+ ret = dict_get_str(xattr, (char *)acl_key, &acl_s);
+ if (ret)
+ goto out;
+
+ acl = acl_from_text(acl_s);
+
+out:
+ if (xattr)
+ dict_unref(xattr);
+
+ if (IA_ISLNK(object->inode->ia_type) && new_object)
+ glfs_h_close(new_object);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return acl;
+}
+#else /* !HAVE_ACL_LIBACL_H */
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_get, 3.7.0)
+acl_t
+pub_glfs_h_acl_get(struct glfs *fs, struct glfs_object *object,
+ const acl_type_t type)
+{
+ errno = ENOTSUP;
+ return NULL;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_acl_set, 3.7.0)
+int
+pub_glfs_h_acl_set(struct glfs *fs, struct glfs_object *object,
+ const acl_type_t type, const acl_t acl)
+{
+ errno = ENOTSUP;
+ return -1;
+}
+#endif
+
+/* The API to perform read using anonymous fd */
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_anonymous_read, 3.7.0)
+ssize_t
+pub_glfs_h_anonymous_read(struct glfs *fs, struct glfs_object *object,
+ const void *buf, size_t count, off_t offset)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_anonymous_preadv(fs, object, &iov, 1, offset, 0);
+
+ return ret;
+}
+
+/* The API to perform write using anonymous fd */
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_anonymous_write, 3.7.0)
+ssize_t
+pub_glfs_h_anonymous_write(struct glfs *fs, struct glfs_object *object,
+ const void *buf, size_t count, off_t offset)
+{
+ struct iovec iov = {
+ 0,
+ };
+ ssize_t ret = 0;
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ iov.iov_base = (void *)buf;
+ iov.iov_len = count;
+
+ ret = glfs_anonymous_pwritev(fs, object, &iov, 1, offset, 0);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_object_copy, 3.11.0)
+struct glfs_object *
+pub_glfs_object_copy(struct glfs_object *src)
+{
+ struct glfs_object *object = NULL;
+
+ GF_VALIDATE_OR_GOTO("glfs_dup_object", src, out);
+
+ object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
+ if (object == NULL) {
+ errno = ENOMEM;
+ gf_smsg(THIS->name, GF_LOG_WARNING, errno, API_MSG_CREATE_HANDLE_FAILED,
+ "glfs_dup_object gfid=%s", uuid_utoa(src->inode->gfid), NULL);
+ return NULL;
+ }
+
+ object->inode = inode_ref(src->inode);
+ gf_uuid_copy(object->gfid, src->inode->gfid);
+
+out:
+ return object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_xreaddirplus_get_object, 3.11.0)
+struct glfs_object *
+pub_glfs_xreaddirplus_get_object(struct glfs_xreaddirp_stat *xstat)
+{
+ GF_VALIDATE_OR_GOTO("glfs_xreaddirplus_get_object", xstat, out);
+
+ if (!(xstat->flags_handled & GFAPI_XREADDIRP_HANDLE))
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_HANDLE_NOT_SET,
+ "GFAPI_XREADDIRP_HANDLE xstat=%p", xstat, "handle=%x",
+ xstat->flags_handled, NULL);
+
+ return xstat->object;
+
+out:
+ return NULL;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_h_lease, 4.0.0)
+int
+pub_glfs_h_lease(struct glfs *fs, struct glfs_object *object,
+ struct glfs_lease *lease)
+{
+ int ret = -1;
+ xlator_t *subvol = NULL;
+ inode_t *inode = NULL;
+ loc_t loc = {
+ 0,
+ };
+ struct gf_lease gf_lease = {
+ 0,
+ };
+
+ /* validate in args */
+ if ((fs == NULL) || (object == NULL)) {
+ errno = EINVAL;
+ return -1;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* get the active volume */
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ /* get/refresh the in arg objects inode in correlation to the xlator */
+ inode = glfs_resolve_inode(fs, subvol, object);
+ if (!inode) {
+ errno = ESTALE;
+ goto out;
+ }
+
+ /* populate loc */
+ GLFS_LOC_FILL_INODE(inode, loc, out);
+
+ glfs_lease_to_gf_lease(lease, &gf_lease);
+
+ ret = syncop_lease(subvol, &loc, &gf_lease, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ gf_lease_to_glfs_lease(&gf_lease, lease);
+
+out:
+ loc_wipe(&loc);
+
+ if (inode)
+ inode_unref(inode);
+
+ glfs_subvol_done(fs, subvol);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h
new file mode 100644
index 00000000000..4d039b9c76b
--- /dev/null
+++ b/api/src/glfs-handles.h
@@ -0,0 +1,355 @@
+/*
+ Copyright (c) 2013-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _GLFS_HANDLES_H
+#define _GLFS_HANDLES_H
+
+#include "glfs.h"
+
+/* GLFS OBJECT BASED OPERATIONS
+ *
+ * The following APIs are introduced to provide an API framework that can work
+ * with gluster objects (files and directories), instead of absolute paths.
+ *
+ * The following API set can be related to the POSIX *at interfaces (like
+ * openat (2)). The intention of these APIs is to be able to operate based
+ * on parent object and looking up or creating child objects within, OR to be
+ * used on the actual object thus looked up or created, and retrieve information
+ * regarding the same.
+ *
+ * The APIs also provide for generating an opaque invariant handle to the
+ * object, that can later be used to lookup the object, instead of the regular
+ * glfs_h_* variants. The APIs that provide this behaviour are,
+ * glfs_h_extract_handle and glfs_h_create_from_handle.
+ *
+ * The object handles can be transitioned to fd based operations as supported
+ * by glfs.h calls, using the glfs_h_open call. This provides a way to move
+ * from objects to fd's akin to moving from path to fd for required operations.
+ *
+ * NOTE: The opaque invariant handle is the GFID of the object in reality, but
+ * maintained as an opaque data value, for potential internal changes to the
+ * same without impacting the caller.
+ *
+ * NOTE: Currently looking up an object can create multiple object handles to
+ * the same, i.e distinct glfs_object *. Hence each such looked up or received
+ * handle from other calls, would need to be closed. In the future, for a given
+ * object these pointers would be the same, and an ease of use API to forget all
+ * instances of this bject would be provided (instead of a per lookup close).
+ * This should not change the APIs in their current form.
+ *
+ */
+
+/* Handle length for object handles returned from glfs_h_extract_handle or
+ * glfs_h_create_from_handle */
+#define GFAPI_HANDLE_LENGTH 16
+
+/* These flags should be in sync to the ones defined in upcall.h */
+#define GFAPI_UP_NLINK 0x00000001 /* update nlink */
+#define GFAPI_UP_MODE 0x00000002 /* update mode and ctime */
+#define GFAPI_UP_OWN 0x00000004 /* update mode,uid,gid and ctime */
+#define GFAPI_UP_SIZE 0x00000008 /* update fsize */
+#define GFAPI_UP_TIMES 0x00000010 /* update all times */
+#define GFAPI_UP_ATIME 0x00000020 /* update atime only */
+#define GFAPI_UP_PERM \
+ 0x00000040 /* update fields needed for \
+ permission checking */
+#define GFAPI_UP_RENAME \
+ 0x00000080 /* this is a rename op - \
+ delete the cache entry */
+#define GFAPI_UP_FORGET \
+ 0x00000100 /* inode_forget on server side - \
+ invalidate the cache entry */
+#define GFAPI_UP_PARENT_TIMES 0x00000200 /* update parent dir times */
+
+#define GFAPI_INODE_UPDATE_FLAGS \
+ (GFAPI_UP_NLINK | GFAPI_UP_MODE | GFAPI_UP_OWN | GFAPI_UP_SIZE | \
+ GFAPI_UP_TIMES | GFAPI_UP_ATIME)
+
+/* Portability non glibc c++ build systems */
+#ifndef __THROW
+#if defined __cplusplus
+#define __THROW throw()
+#else
+#define __THROW
+#endif
+#endif
+
+__BEGIN_DECLS
+
+/*
+ * Notes:
+ *
+ * The file object handle. One per looked up, created file/directory
+ *
+ * This had been introduced to facilitate gfid/inode based gfapi
+ * - a requirement introduced by nfs-ganesha
+ */
+struct glfs_object;
+typedef struct glfs_object glfs_object_t;
+
+/* Functions for getting details about the glfs_upcall_inode
+ *
+ * None of the pointers returned by the below functions should be free()'d,
+ * glfs_free()'d or glfs_h_close()'d by the application.
+ *
+ * Releasing of the structures is done by passing the glfs_upcall pointer
+ * to glfs_free().
+ */
+struct glfs_upcall_inode;
+typedef struct glfs_upcall_inode glfs_upcall_inode_t;
+
+glfs_object_t *
+glfs_upcall_inode_get_object(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_object, 3.7.16);
+
+uint64_t
+glfs_upcall_inode_get_flags(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_flags, 3.7.16);
+
+struct stat *
+glfs_upcall_inode_get_stat(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_stat, 3.7.16);
+
+uint64_t
+glfs_upcall_inode_get_expire(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_expire, 3.7.16);
+
+glfs_object_t *
+glfs_upcall_inode_get_pobject(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_pobject, 3.7.16);
+
+struct stat *
+glfs_upcall_inode_get_pstat(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_pstat, 3.7.16);
+
+glfs_object_t *
+glfs_upcall_inode_get_oldpobject(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_oldpobject, 3.7.16);
+
+struct stat *
+glfs_upcall_inode_get_oldpstat(glfs_upcall_inode_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_inode_get_oldpstat, 3.7.16);
+
+/* Handle based operations */
+/* Operations that generate handles */
+glfs_object_t *
+glfs_h_lookupat(glfs_t *fs, glfs_object_t *parent, const char *path,
+ struct stat *stat, int follow) __THROW
+ GFAPI_PUBLIC(glfs_h_lookupat, 3.7.4);
+
+glfs_object_t *
+glfs_h_creat(glfs_t *fs, glfs_object_t *parent, const char *path, int flags,
+ mode_t mode, struct stat *sb) __THROW
+ GFAPI_PUBLIC(glfs_h_creat, 3.4.2);
+
+glfs_object_t *
+glfs_h_mkdir(glfs_t *fs, glfs_object_t *parent, const char *path, mode_t flags,
+ struct stat *sb) __THROW GFAPI_PUBLIC(glfs_h_mkdir, 3.4.2);
+
+glfs_object_t *
+glfs_h_mknod(glfs_t *fs, glfs_object_t *parent, const char *path, mode_t mode,
+ dev_t dev, struct stat *sb) __THROW
+ GFAPI_PUBLIC(glfs_h_mknod, 3.4.2);
+
+glfs_object_t *
+glfs_h_symlink(glfs_t *fs, glfs_object_t *parent, const char *name,
+ const char *data, struct stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_h_symlink, 3.4.2);
+
+/* Operations on the actual objects */
+int
+glfs_h_unlink(glfs_t *fs, glfs_object_t *parent, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_h_unlink, 3.4.2);
+
+int
+glfs_h_close(glfs_object_t *object) __THROW GFAPI_PUBLIC(glfs_h_close, 3.4.2);
+
+int
+glfs_caller_specific_init(void *uid_caller_key, void *gid_caller_key,
+ void *future) __THROW
+ GFAPI_PUBLIC(glfs_caller_specific_init, 3.5.0);
+
+int
+glfs_h_truncate(glfs_t *fs, glfs_object_t *object, off_t offset) __THROW
+ GFAPI_PUBLIC(glfs_h_truncate, 3.4.2);
+
+int
+glfs_h_stat(glfs_t *fs, glfs_object_t *object, struct stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_h_stat, 3.4.2);
+
+int
+glfs_h_statfs(glfs_t *fs, glfs_object_t *object, struct statvfs *stat) __THROW
+ GFAPI_PUBLIC(glfs_h_statfs, 3.7.0);
+
+int
+glfs_h_getattrs(glfs_t *fs, glfs_object_t *object, struct stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_h_getattrs, 3.4.2);
+
+int
+glfs_h_getxattrs(glfs_t *fs, glfs_object_t *object, const char *name,
+ void *value, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_h_getxattrs, 3.5.1);
+
+int
+glfs_h_setattrs(glfs_t *fs, glfs_object_t *object, struct stat *sb,
+ int valid) __THROW GFAPI_PUBLIC(glfs_h_setattrs, 3.4.2);
+
+int
+glfs_h_setxattrs(glfs_t *fs, glfs_object_t *object, const char *name,
+ const void *value, size_t size, int flags) __THROW
+ GFAPI_PUBLIC(glfs_h_setxattrs, 3.5.0);
+
+int
+glfs_h_readlink(glfs_t *fs, glfs_object_t *object, char *buf,
+ size_t bufsiz) __THROW GFAPI_PUBLIC(glfs_h_readlink, 3.4.2);
+
+int
+glfs_h_link(glfs_t *fs, glfs_object_t *linktgt, glfs_object_t *parent,
+ const char *name) __THROW GFAPI_PUBLIC(glfs_h_link, 3.4.2);
+
+int
+glfs_h_rename(glfs_t *fs, glfs_object_t *olddir, const char *oldname,
+ glfs_object_t *newdir, const char *newname) __THROW
+ GFAPI_PUBLIC(glfs_h_rename, 3.4.2);
+
+int
+glfs_h_removexattrs(glfs_t *fs, glfs_object_t *object, const char *name) __THROW
+ GFAPI_PUBLIC(glfs_h_removexattrs, 3.5.1);
+
+/* Operations enabling opaque invariant handle to object transitions */
+ssize_t
+glfs_h_extract_handle(glfs_object_t *object, unsigned char *handle,
+ int len) __THROW
+ GFAPI_PUBLIC(glfs_h_extract_handle, 3.4.2);
+
+/* Given a handle, looks up the inode and creates glfs_object.
+ * In addition, if provided 'stat', copies the inode attributes
+ */
+glfs_object_t *
+glfs_h_create_from_handle(glfs_t *fs, unsigned char *handle, int len,
+ struct stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_h_create_from_handle, 3.4.2);
+
+/* Operations enabling object handles to fd transitions */
+glfs_fd_t *
+glfs_h_opendir(glfs_t *fs, glfs_object_t *object) __THROW
+ GFAPI_PUBLIC(glfs_h_opendir, 3.4.2);
+
+glfs_fd_t *
+glfs_h_open(glfs_t *fs, glfs_object_t *object, int flags) __THROW
+ GFAPI_PUBLIC(glfs_h_open, 3.4.2);
+
+int
+glfs_h_access(glfs_t *fs, glfs_object_t *object, int mask) __THROW
+ GFAPI_PUBLIC(glfs_h_access, 3.6.0);
+
+struct glfs_object *
+glfs_h_creat_open(struct glfs *fs, struct glfs_object *parent, const char *path,
+ int flags, mode_t mode, struct stat *stat,
+ struct glfs_fd **out_fd) __THROW
+ GFAPI_PUBLIC(glfs_h_creat_open, 6.6);
+/*
+ SYNOPSIS
+
+ glfs_h_poll_upcall: Poll for upcall events given a 'glfs' object.
+
+ DESCRIPTION
+
+ This API is used to poll for upcall events stored in the
+ upcall list. Current users of this API is NFS-Ganesha.
+ In case of any event received, it will be mapped appropriately
+ into 'glfs_upcall' along with the handle('glfs_object') to be
+ passed to NFS-Ganesha.
+
+ In case of success, applications need to check the value of
+ cbk->handle to be NON NULL before processing the upcall
+ events.
+
+ PARAMETERS
+
+ @fs: glfs object to poll the upcall events for
+ @cbk: Pointer that will contain an upcall event for use by the application.
+ Application is responsible for free'ing the structure with glfs_free().
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Error condition, mostly due to out of memory.
+
+*/
+
+int
+glfs_h_poll_upcall(glfs_t *fs, glfs_upcall_t **cbk) __THROW
+ GFAPI_PUBLIC(glfs_h_poll_upcall, 3.7.16);
+
+int
+glfs_h_acl_set(glfs_t *fs, glfs_object_t *object, const acl_type_t type,
+ const acl_t acl) __THROW GFAPI_PUBLIC(glfs_h_acl_set, 3.7.0);
+
+acl_t
+glfs_h_acl_get(glfs_t *fs, glfs_object_t *object, const acl_type_t type) __THROW
+ GFAPI_PUBLIC(glfs_h_acl_get, 3.7.0);
+
+size_t
+glfs_h_anonymous_write(glfs_t *fs, glfs_object_t *object, const void *buf,
+ size_t count, off_t offset) __THROW
+ GFAPI_PUBLIC(glfs_h_anonymous_write, 3.7.0);
+
+ssize_t
+glfs_h_anonymous_read(glfs_t *fs, glfs_object_t *object, const void *buf,
+ size_t count, off_t offset) __THROW
+ GFAPI_PUBLIC(glfs_h_anonymous_read, 3.7.0);
+
+/*
+ * Caution: The object returned by this object gets freed as part
+ * of 'glfs_free(xstat)'. Make sure to have a copy using 'glfs_object_copy()'
+ * to use post that.
+ */
+glfs_object_t *
+glfs_xreaddirplus_get_object(struct glfs_xreaddirp_stat *xstat) __THROW
+ GFAPI_PUBLIC(glfs_xreaddirplus_get_object, 3.11.0);
+
+/* Applications should close the object returned by this routine
+ * explicitly using 'glfs_h_close()'
+ */
+glfs_object_t *
+glfs_object_copy(glfs_object_t *src) __THROW
+ GFAPI_PUBLIC(glfs_object_copy, 3.11.0);
+
+int
+glfs_h_lease(glfs_t *fs, glfs_object_t *object, glfs_lease_t *lease) __THROW
+ GFAPI_PUBLIC(glfs_h_lease, 4.0.0);
+
+glfs_object_t *
+glfs_h_find_handle(glfs_t *fs, unsigned char *handle, int len) __THROW
+ GFAPI_PUBLIC(glfs_h_lease, 4.0.0);
+
+/* Functions for getting details about the glfs_upcall_lease
+ *
+ * None of the pointers returned by the below functions should be free()'d,
+ * glfs_free()'d or glfs_h_close()'d by the application.
+ *
+ * Releasing of the structures is done by passing the glfs_upcall pointer
+ * to glfs_free().
+ */
+struct glfs_upcall_lease;
+typedef struct glfs_upcall_lease glfs_upcall_lease_t;
+
+glfs_object_t *
+glfs_upcall_lease_get_object(glfs_upcall_lease_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_lease_get_object, 4.1.6);
+
+uint32_t
+glfs_upcall_lease_get_lease_type(glfs_upcall_lease_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_lease_get_lease_type, 4.1.6);
+
+__END_DECLS
+
+#endif /* !_GLFS_HANDLES_H */
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
new file mode 100644
index 00000000000..7cc3b18a104
--- /dev/null
+++ b/api/src/glfs-internal.h
@@ -0,0 +1,756 @@
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _GLFS_INTERNAL_H
+#define _GLFS_INTERNAL_H
+
+#include <glusterfs/xlator.h>
+#include <glusterfs/glusterfs.h>
+#include <glusterfs/upcall-utils.h>
+#include "glfs-handles.h"
+#include <glusterfs/refcount.h>
+#include <glusterfs/syncop.h>
+
+#define GLFS_SYMLINK_MAX_FOLLOW 2048
+
+#define DEFAULT_REVAL_COUNT 1
+
+/*
+ * According to pthread mutex and conditional variable ( cond,
+ * child_down_count, upcall mutex and mutex) initialization of struct glfs
+ * members, below GLFS_INIT_* flags are set in 'pthread_flags' member of struct
+ * glfs. The flags are set from glfs_init() and glfs_new_from_ctx() functions
+ * as part of fs inititialization.
+ *
+ * These flag bits are validated in glfs_fini() to destroy all or partially
+ * initialized mutex and conditional variables of glfs object.
+ * If you introduce new pthread mutex or conditional variable in glfs object,
+ * please make sure you have a flag bit intorduced here for proper cleanup
+ * in glfs_fini().
+ *
+ */
+
+#define PTHREAD_MUTEX_INIT(mutex, attr, flags, mask, label) \
+ do { \
+ int __ret = -1; \
+ __ret = pthread_mutex_init(mutex, attr); \
+ if (__ret == 0) \
+ flags |= mask; \
+ else \
+ goto label; \
+ } while (0)
+
+#define PTHREAD_MUTEX_DESTROY(mutex, flags, mask) \
+ do { \
+ if (flags & mask) \
+ (void)pthread_mutex_destroy(mutex); \
+ } while (0)
+
+#define PTHREAD_COND_INIT(cond, attr, flags, mask, label) \
+ do { \
+ int __ret = -1; \
+ __ret = pthread_cond_init(cond, attr); \
+ if (__ret == 0) \
+ flags |= mask; \
+ else \
+ goto label; \
+ } while (0)
+
+#define PTHREAD_COND_DESTROY(cond, flags, mask) \
+ do { \
+ if (flags & mask) \
+ (void)pthread_cond_destroy(cond); \
+ } while (0)
+
+#define GLFS_INIT_MUTEX 0x00000001 /* pthread_mutex_flag */
+#define GLFS_INIT_COND 0x00000002 /* pthread_cond_flag */
+#define GLFS_INIT_COND_CHILD 0x00000004 /* pthread_cond_child_down_flag */
+#define GLFS_INIT_MUTEX_UPCALL 0x00000008 /* pthread_mutex_upcall_flag */
+
+#ifndef GF_DARWIN_HOST_OS
+#ifndef GFAPI_PUBLIC
+#define GFAPI_PUBLIC(sym, ver) /**/
+#endif
+#ifndef GFAPI_PRIVATE
+#define GFAPI_PRIVATE(sym, ver) /**/
+#endif
+#if __GNUC__ >= 10
+#define GFAPI_SYMVER_PUBLIC_DEFAULT(fn, ver) \
+ __attribute__((__symver__(STR(fn) "@@GFAPI_" STR(ver))))
+
+#define GFAPI_SYMVER_PRIVATE_DEFAULT(fn, ver) \
+ __attribute__((__symver__(STR(fn) "@@GFAPI_PRIVATE_" STR(ver))))
+
+#define GFAPI_SYMVER_PUBLIC(fn1, fn2, ver) \
+ __attribute__((__symver__(STR(fn2) "@GFAPI_" STR(ver))))
+
+#define GFAPI_SYMVER_PRIVATE(fn1, fn2, ver) \
+ __attribute__((__symver__(STR(fn2) "@GFAPI_PRIVATE_" STR(ver))))
+
+#else
+#define GFAPI_SYMVER_PUBLIC_DEFAULT(fn, ver) \
+ asm(".symver pub_" STR(fn) ", " STR(fn) "@@GFAPI_" STR(ver));
+
+#define GFAPI_SYMVER_PRIVATE_DEFAULT(fn, ver) \
+ asm(".symver priv_" STR(fn) ", " STR(fn) "@@GFAPI_PRIVATE_" STR(ver));
+
+#define GFAPI_SYMVER_PUBLIC(fn1, fn2, ver) \
+ asm(".symver pub_" STR(fn1) ", " STR(fn2) "@GFAPI_" STR(ver));
+
+#define GFAPI_SYMVER_PRIVATE(fn1, fn2, ver) \
+ asm(".symver priv_" STR(fn1) ", " STR(fn2) "@GFAPI_PRIVATE_" STR(ver));
+#endif
+#define STR(str) #str
+#else
+#ifndef GFAPI_PUBLIC
+#define GFAPI_PUBLIC(sym, ver) __asm("_" __STRING(sym) "$GFAPI_" __STRING(ver));
+#endif
+#ifndef GFAPI_PRIVATE
+#define GFAPI_PRIVATE(sym, ver) \
+ __asm("_" __STRING(sym) "$GFAPI_PRIVATE_" __STRING(ver));
+#endif
+#define GFAPI_SYMVER_PUBLIC_DEFAULT(fn, dotver) /**/
+#define GFAPI_SYMVER_PRIVATE_DEFAULT(fn, dotver) /**/
+#define GFAPI_SYMVER_PUBLIC(fn1, fn2, dotver) /**/
+#define GFAPI_SYMVER_PRIVATE(fn1, fn2, dotver) /**/
+#endif
+
+#define ESTALE_RETRY(ret, errno, reval, loc, label) \
+ do { \
+ if (ret == -1 && errno == ESTALE) { \
+ if (reval < DEFAULT_REVAL_COUNT) { \
+ reval++; \
+ loc_wipe(loc); \
+ goto label; \
+ } \
+ } \
+ } while (0)
+
+#define GLFS_LOC_FILL_INODE(oinode, loc, label) \
+ do { \
+ loc.inode = inode_ref(oinode); \
+ gf_uuid_copy(loc.gfid, oinode->gfid); \
+ ret = glfs_loc_touchup(&loc); \
+ if (ret != 0) { \
+ errno = EINVAL; \
+ goto label; \
+ } \
+ } while (0)
+
+#define GLFS_LOC_FILL_PINODE(pinode, loc, ret, errno, label, path) \
+ do { \
+ loc.inode = inode_new(pinode->table); \
+ if (!loc.inode) { \
+ ret = -1; \
+ errno = ENOMEM; \
+ goto label; \
+ } \
+ loc.parent = inode_ref(pinode); \
+ loc.name = path; \
+ ret = glfs_loc_touchup(&loc); \
+ if (ret != 0) { \
+ errno = EINVAL; \
+ goto label; \
+ } \
+ } while (0)
+
+struct glfs;
+
+struct _upcall_entry {
+ struct list_head upcall_list;
+ struct gf_upcall upcall_data;
+};
+typedef struct _upcall_entry upcall_entry;
+
+typedef int (*glfs_init_cbk)(struct glfs *fs, int ret);
+
+struct glfs {
+ char *volname;
+ uuid_t vol_uuid;
+
+ glusterfs_ctx_t *ctx;
+
+ pthread_t poller;
+
+ glfs_init_cbk init_cbk;
+ pthread_mutex_t mutex;
+ pthread_cond_t cond;
+ pthread_cond_t child_down_cond; /* for broadcasting CHILD_DOWN */
+ int init;
+ int ret;
+ int err;
+
+ xlator_t *active_subvol; /* active graph */
+ xlator_t *mip_subvol; /* graph for which migration is in
+ * progress */
+ xlator_t *next_subvol; /* Any new graph is put to
+ * next_subvol, the graph in
+ * next_subvol can either be moved
+ * to mip_subvol (if any IO picks it
+ * up for migration), or be
+ * destroyed (if there is a new
+ * graph, and this was never picked
+ * for migration) */
+ xlator_t *old_subvol;
+
+ char *oldvolfile;
+ ssize_t oldvollen;
+
+ inode_t *cwd;
+
+ uint32_t dev_id; /* Used to fill st_dev in struct stat */
+
+ struct list_head openfds;
+
+ gf_boolean_t migration_in_progress;
+
+ gf_boolean_t cache_upcalls; /* add upcalls to the upcall_list? */
+ struct list_head upcall_list;
+ pthread_mutex_t upcall_list_mutex; /* mutex for upcall entry list */
+
+ uint32_t pin_refcnt;
+ uint32_t pthread_flags; /* GLFS_INIT_* # defines set this flag */
+
+ uint32_t upcall_events; /* Mask of upcall events application
+ * is interested in */
+ glfs_upcall_cbk up_cbk; /* upcall cbk function to be registered */
+ void *up_data; /* Opaque data provided by application
+ * during upcall registration */
+ struct list_head waitq; /* waiting synctasks */
+};
+
+/* This enum is used to maintain the state of glfd. In case of async fops
+ * fd might be closed before the actual fop is complete. Therefore we need
+ * to track whether the fd is closed or not, instead actually closing it.*/
+enum glfs_fd_state { GLFD_INIT, GLFD_OPEN, GLFD_CLOSE };
+
+struct glfs_fd {
+ struct list_head openfds;
+ struct list_head list;
+ GF_REF_DECL;
+ struct glfs *fs;
+ enum glfs_fd_state state;
+ off_t offset;
+ fd_t *fd; /* Currently guared by @fs->mutex. TODO: per-glfd lock */
+ struct list_head entries;
+ gf_dirent_t *next;
+ struct dirent *readdirbuf;
+ gf_lkowner_t lk_owner;
+ glfs_leaseid_t lease_id; /* Stores lease_id of client in glfd */
+ gf_lock_t lock; /* lock taken before updating fd state */
+ glfs_recall_cbk cbk;
+ void *cookie;
+};
+
+/* glfs object handle introduced for the alternate gfapi implementation based
+ on glfs handles/gfid/inode
+*/
+struct glfs_object {
+ inode_t *inode;
+ uuid_t gfid;
+};
+
+struct glfs_upcall {
+ struct glfs *fs; /* glfs object */
+ enum glfs_upcall_reason reason; /* Upcall event type */
+ void *event; /* changes based in the event type */
+ void (*free_event)(void *); /* free event after the usage */
+};
+
+struct glfs_upcall_inode {
+ struct glfs_object *object; /* Object which need to be acted upon */
+ int flags; /* Cache UPDATE/INVALIDATE flags */
+ struct stat buf; /* Latest stat of this entry */
+ unsigned int expire_time_attr; /* the amount of time for which
+ * the application need to cache
+ * this entry */
+ struct glfs_object *p_object; /* parent Object to be updated */
+ struct stat p_buf; /* Latest stat of parent dir handle */
+ struct glfs_object *oldp_object; /* Old parent Object to be updated */
+ struct stat oldp_buf; /* Latest stat of old parent dir handle */
+};
+
+struct glfs_upcall_lease {
+ struct glfs_object *object; /* Object which need to be acted upon */
+ uint32_t lease_type; /* Lease type to which client can downgrade to*/
+};
+
+struct glfs_upcall_lease_fd {
+ uint32_t lease_type; /* Lease type to which client can downgrade to*/
+ void *fd_cookie; /* Object which need to be acted upon */
+};
+
+struct glfs_xreaddirp_stat {
+ struct stat
+ st; /* Stat for that dirent - corresponds to GFAPI_XREADDIRP_STAT */
+ struct glfs_object *object; /* handled for GFAPI_XREADDIRP_HANDLE */
+ uint32_t flags_handled; /* final set of flags successfulyy handled */
+};
+
+#define DEFAULT_EVENT_POOL_SIZE 16384
+#define GF_MEMPOOL_COUNT_OF_DICT_T 4096
+#define GF_MEMPOOL_COUNT_OF_DATA_T (GF_MEMPOOL_COUNT_OF_DICT_T * 4)
+#define GF_MEMPOOL_COUNT_OF_DATA_PAIR_T (GF_MEMPOOL_COUNT_OF_DICT_T * 4)
+
+#define GF_MEMPOOL_COUNT_OF_LRU_BUF_T 256
+
+typedef void(glfs_mem_release_t)(void *ptr);
+
+struct glfs_mem_header {
+ uint32_t magic;
+ size_t nmemb;
+ size_t size;
+ glfs_mem_release_t *release;
+};
+
+#define GLFS_MEM_HEADER_SIZE (sizeof(struct glfs_mem_header))
+#define GLFS_MEM_HEADER_MAGIC 0x20170830
+
+static inline void *
+__glfs_calloc(size_t nmemb, size_t size, glfs_mem_release_t release,
+ uint32_t type, const char *typestr)
+{
+ struct glfs_mem_header *header = NULL;
+
+ header = __gf_calloc(nmemb, (size + GLFS_MEM_HEADER_SIZE), type, typestr);
+ if (!header)
+ return NULL;
+
+ header->magic = GLFS_MEM_HEADER_MAGIC;
+ header->nmemb = nmemb;
+ header->size = size;
+ header->release = release;
+
+ return header + 1;
+}
+
+static inline void *
+__glfs_malloc(size_t size, glfs_mem_release_t release, uint32_t type,
+ const char *typestr)
+{
+ struct glfs_mem_header *header = NULL;
+
+ header = __gf_malloc((size + GLFS_MEM_HEADER_SIZE), type, typestr);
+ if (!header)
+ return NULL;
+
+ header->magic = GLFS_MEM_HEADER_MAGIC;
+ header->nmemb = 1;
+ header->size = size;
+ header->release = release;
+
+ return header + 1;
+}
+
+static inline void *
+__glfs_realloc(void *ptr, size_t size)
+{
+ struct glfs_mem_header *old_header = NULL;
+ struct glfs_mem_header *new_header = NULL;
+ struct glfs_mem_header tmp_header;
+ void *new_ptr = NULL;
+
+ GF_ASSERT(NULL != ptr);
+
+ old_header = (struct glfs_mem_header *)(ptr - GLFS_MEM_HEADER_SIZE);
+ GF_ASSERT(old_header->magic == GLFS_MEM_HEADER_MAGIC);
+ tmp_header = *old_header;
+
+ new_ptr = __gf_realloc(old_header, (size + GLFS_MEM_HEADER_SIZE));
+ if (!new_ptr)
+ return NULL;
+
+ new_header = (struct glfs_mem_header *)new_ptr;
+ *new_header = tmp_header;
+ new_header->size = size;
+
+ return new_header + 1;
+}
+
+static inline void
+__glfs_free(void *free_ptr)
+{
+ struct glfs_mem_header *header = NULL;
+ void *release_ptr = NULL;
+ int i = 0;
+
+ if (!free_ptr)
+ return;
+
+ header = (struct glfs_mem_header *)(free_ptr - GLFS_MEM_HEADER_SIZE);
+ GF_ASSERT(header->magic == GLFS_MEM_HEADER_MAGIC);
+
+ if (header->release) {
+ release_ptr = free_ptr;
+ for (i = 0; i < header->nmemb; i++) {
+ header->release(release_ptr);
+ release_ptr += header->size;
+ }
+ }
+
+ __gf_free(header);
+}
+
+#define GLFS_CALLOC(nmemb, size, release, type) \
+ __glfs_calloc(nmemb, size, release, type, #type)
+
+#define GLFS_MALLOC(size, release, type) \
+ __glfs_malloc(size, release, type, #type)
+
+#define GLFS_REALLOC(ptr, size) __glfs_realloc(ptr, size)
+
+#define GLFS_FREE(free_ptr) __glfs_free(free_ptr)
+
+int
+glfs_mgmt_init(struct glfs *fs);
+void
+glfs_init_done(struct glfs *fs, int ret) GFAPI_PRIVATE(glfs_init_done, 3.4.0);
+int
+glfs_process_volfp(struct glfs *fs, FILE *fp);
+int
+glfs_resolve(struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc,
+ struct iatt *iatt, int reval) GFAPI_PRIVATE(glfs_resolve, 3.7.0);
+int
+glfs_lresolve(struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc,
+ struct iatt *iatt, int reval);
+fd_t *
+glfs_resolve_fd(struct glfs *fs, xlator_t *subvol, struct glfs_fd *glfd);
+
+fd_t *
+__glfs_migrate_fd(struct glfs *fs, xlator_t *subvol, struct glfs_fd *glfd);
+
+int
+glfs_first_lookup(xlator_t *subvol);
+
+void
+glfs_process_upcall_event(struct glfs *fs, void *data)
+ GFAPI_PRIVATE(glfs_process_upcall_event, 3.7.0);
+
+#define __GLFS_ENTRY_VALIDATE_FS(fs, label) \
+ do { \
+ if (!fs) { \
+ errno = EINVAL; \
+ goto label; \
+ } \
+ old_THIS = THIS; \
+ THIS = fs->ctx->master; \
+ } while (0)
+
+#define __GLFS_EXIT_FS \
+ do { \
+ THIS = old_THIS; \
+ } while (0)
+
+#define __GLFS_ENTRY_VALIDATE_FD(glfd, label) \
+ do { \
+ if (!glfd || !glfd->fd || !glfd->fd->inode || \
+ glfd->state != GLFD_OPEN) { \
+ errno = EBADF; \
+ goto label; \
+ } \
+ old_THIS = THIS; \
+ THIS = glfd->fd->inode->table->xl->ctx->master; \
+ } while (0)
+
+#define __GLFS_LOCK_WAIT(fs) \
+ do { \
+ struct synctask *task = NULL; \
+ \
+ task = synctask_get(); \
+ \
+ if (task) { \
+ list_add_tail(&task->waitq, &fs->waitq); \
+ pthread_mutex_unlock(&fs->mutex); \
+ synctask_yield(task, NULL); \
+ pthread_mutex_lock(&fs->mutex); \
+ } else { \
+ /* non-synctask */ \
+ pthread_cond_wait(&fs->cond, &fs->mutex); \
+ } \
+ } while (0)
+
+#define __GLFS_SYNCTASK_WAKE(fs) \
+ do { \
+ struct synctask *waittask = NULL; \
+ \
+ while (!list_empty(&fs->waitq)) { \
+ waittask = list_entry(fs->waitq.next, struct synctask, waitq); \
+ list_del_init(&waittask->waitq); \
+ synctask_wake(waittask); \
+ } \
+ } while (0)
+
+/*
+ By default all lock attempts from user context must
+ use glfs_lock() and glfs_unlock(). This allows
+ for a safe implementation of graph migration where
+ we can give up the mutex during syncop calls so
+ that bottom up calls (particularly CHILD_UP notify)
+ can do a mutex_lock() on @glfs without deadlocking
+ the filesystem.
+
+ All the fops should wait for graph migration to finish
+ before starting the fops. Therefore these functions should
+ call glfs_lock with wait_for_migration as true. But waiting
+ for migration to finish in call-back path can result thread
+ dead-locks. The reason for this is we only have finite
+ number of epoll threads. so if we wait on epoll threads
+ there will not be any thread left to handle outstanding
+ rpc replies.
+*/
+static inline int
+glfs_lock(struct glfs *fs, gf_boolean_t wait_for_migration)
+{
+ pthread_mutex_lock(&fs->mutex);
+
+ while (!fs->init)
+ __GLFS_LOCK_WAIT(fs);
+
+ while (wait_for_migration && fs->migration_in_progress)
+ __GLFS_LOCK_WAIT(fs);
+
+ return 0;
+}
+
+static inline void
+glfs_unlock(struct glfs *fs)
+{
+ pthread_mutex_unlock(&fs->mutex);
+}
+
+struct glfs_fd *
+glfs_fd_new(struct glfs *fs);
+void
+glfs_fd_bind(struct glfs_fd *glfd);
+void
+glfd_set_state_bind(struct glfs_fd *glfd);
+
+xlator_t *
+glfs_active_subvol(struct glfs *fs) GFAPI_PRIVATE(glfs_active_subvol, 3.4.0);
+xlator_t *
+__glfs_active_subvol(struct glfs *fs);
+void
+glfs_subvol_done(struct glfs *fs, xlator_t *subvol)
+ GFAPI_PRIVATE(glfs_subvol_done, 3.4.0);
+
+inode_t *
+glfs_refresh_inode(xlator_t *subvol, inode_t *inode);
+
+inode_t *
+glfs_cwd_get(struct glfs *fs);
+int
+glfs_cwd_set(struct glfs *fs, inode_t *inode);
+inode_t *
+glfs_resolve_inode(struct glfs *fs, xlator_t *subvol,
+ struct glfs_object *object);
+int
+glfs_create_object(loc_t *loc, struct glfs_object **retobject);
+int
+__glfs_cwd_set(struct glfs *fs, inode_t *inode);
+
+int
+glfs_resolve_base(struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ struct iatt *iatt);
+
+int
+glfs_resolve_at(struct glfs *fs, xlator_t *subvol, inode_t *at,
+ const char *origpath, loc_t *loc, struct iatt *iatt, int follow,
+ int reval) GFAPI_PRIVATE(glfs_resolve_at, 3.4.0);
+int
+glfs_loc_touchup(loc_t *loc) GFAPI_PRIVATE(glfs_loc_touchup, 3.4.0);
+void
+glfs_iatt_to_stat(struct glfs *fs, struct iatt *iatt, struct stat *stat);
+void
+glfs_iatt_from_stat(struct stat *stat, int valid, struct iatt *iatt,
+ int *gvalid);
+int
+glfs_loc_link(loc_t *loc, struct iatt *iatt);
+int
+glfs_loc_unlink(loc_t *loc);
+int
+glfs_getxattr_process(void *value, size_t size, dict_t *xattr,
+ const char *name);
+
+/* Sends RPC call to glusterd to fetch required volume info */
+int
+glfs_get_volume_info(struct glfs *fs);
+
+/*
+ SYNOPSIS
+
+ glfs_new_from_ctx: Creates a virtual mount object by taking a
+ glusterfs_ctx_t object.
+
+ DESCRIPTION
+
+ glfs_new_from_ctx() is not same as glfs_new(). It takes the
+ glusterfs_ctx_t object instead of creating one by glusterfs_ctx_new().
+ Again the usage is restricted to NFS MOUNT over UDP i.e. in
+ glfs_resolve_at() which would take fs object as input but never use
+ (purpose is not to change the ABI of glfs_resolve_at()).
+
+ PARAMETERS
+
+ @ctx: glusterfs_ctx_t object
+
+ RETURN VALUES
+
+ fs : Pointer to the newly created glfs_t object.
+ NULL : Otherwise.
+*/
+
+struct glfs *
+glfs_new_from_ctx(glusterfs_ctx_t *ctx) GFAPI_PRIVATE(glfs_new_from_ctx, 3.7.0);
+
+/*
+ SYNOPSIS
+
+ glfs_free_from_ctx: Free up the memory occupied by glfs_t object
+ created by glfs_new_from_ctx().
+
+ DESCRIPTION
+
+ The glfs_t object allocated by glfs_new_from_ctx() must be released
+ by the caller using this routine. The usage can be found
+ at glfs_fini() or NFS, MOUNT over UDP i.e.
+ __mnt3udp_get_export_subdir_inode ()
+ => glfs_resolve_at().
+
+ PARAMETERS
+
+ @fs: The glfs_t object to be deallocated.
+
+ RETURN VALUES
+
+ void
+*/
+
+void
+glfs_free_from_ctx(struct glfs *fs) GFAPI_PRIVATE(glfs_free_from_ctx, 3.7.0);
+
+int
+glfs_recall_lease_fd(struct glfs *fs, struct gf_upcall *up_data);
+
+int
+glfs_get_upcall_cache_invalidation(struct gf_upcall *to_up_data,
+ struct gf_upcall *from_up_data);
+int
+glfs_h_poll_cache_invalidation(struct glfs *fs, struct glfs_upcall *up_arg,
+ struct gf_upcall *upcall_data);
+
+ssize_t
+glfs_anonymous_preadv(struct glfs *fs, struct glfs_object *object,
+ const struct iovec *iovec, int iovcnt, off_t offset,
+ int flags);
+ssize_t
+glfs_anonymous_pwritev(struct glfs *fs, struct glfs_object *object,
+ const struct iovec *iovec, int iovcnt, off_t offset,
+ int flags);
+
+struct glfs_object *
+glfs_h_resolve_symlink(struct glfs *fs, struct glfs_object *object);
+
+/* Deprecated structures that were passed to client applications, replaced by
+ * accessor functions. Do not use these in new applications, and update older
+ * usage.
+ *
+ * See http://review.gluster.org/14701 for more details.
+ *
+ * WARNING: These structures will be removed in the future.
+ */
+struct glfs_callback_arg {
+ struct glfs *fs;
+ enum glfs_upcall_reason reason;
+ void *event_arg;
+};
+
+struct glfs_callback_inode_arg {
+ struct glfs_object *object; /* Object which need to be acted upon */
+ int flags; /* Cache UPDATE/INVALIDATE flags */
+ struct stat buf; /* Latest stat of this entry */
+ unsigned int expire_time_attr; /* the amount of time for which
+ * the application need to cache
+ * this entry
+ */
+ struct glfs_object *p_object; /* parent Object to be updated */
+ struct stat p_buf; /* Latest stat of parent dir handle */
+ struct glfs_object *oldp_object; /* Old parent Object
+ * to be updated */
+ struct stat oldp_buf; /* Latest stat of old parent
+ * dir handle */
+};
+struct dirent *
+glfs_readdirbuf_get(struct glfs_fd *glfd);
+
+gf_dirent_t *
+glfd_entry_next(struct glfs_fd *glfd, int plus);
+
+void
+gf_dirent_to_dirent(gf_dirent_t *gf_dirent, struct dirent *dirent);
+
+void
+gf_lease_to_glfs_lease(struct gf_lease *gf_lease, struct glfs_lease *lease);
+
+void
+glfs_lease_to_gf_lease(struct glfs_lease *lease, struct gf_lease *gf_lease);
+
+void
+glfs_release_upcall(void *ptr);
+
+int
+get_fop_attr_glfd(dict_t **fop_attr, struct glfs_fd *glfd);
+
+int
+set_fop_attr_glfd(struct glfs_fd *glfd);
+
+int
+get_fop_attr_thrd_key(dict_t **fop_attr);
+
+void
+unset_fop_attr(dict_t **fop_attr);
+
+/*
+ SYNOPSIS
+ glfs_statx: Fetch extended file attributes for the given path.
+
+ DESCRIPTION
+ This function fetches extended file attributes for the given path.
+
+ PARAMETERS
+ @fs: The 'virtual mount' object referencing a volume, under which file exists.
+ @path: Path of the file within the virtual mount.
+ @mask: Requested extended file attributes mask, (See mask defines above)
+
+ RETURN VALUES
+ -1 : Failure. @errno will be set with the type of failure.
+ 0 : Filled in statxbuf with appropriate masks for valid items in the
+ structure.
+
+ ERRNO VALUES
+ EINVAL: fs is invalid
+ EINVAL: mask has unsupported bits set
+ Other errors as returned by stat(2)
+ */
+
+int
+glfs_statx(struct glfs *fs, const char *path, unsigned int mask,
+ struct glfs_stat *statxbuf) GFAPI_PRIVATE(glfs_statx, 6.0);
+
+void
+glfs_iatt_from_statx(struct iatt *, const struct glfs_stat *)
+ GFAPI_PRIVATE(glfs_iatt_from_statx, 6.0);
+
+/*
+ * This API is a per thread setting, similar to glfs_setfs{u/g}id, because of
+ * the call to syncopctx_setfspid.
+ */
+int
+glfs_setfspid(struct glfs *, pid_t) GFAPI_PRIVATE(glfs_setfspid, 6.1);
+#endif /* !_GLFS_INTERNAL_H */
diff --git a/api/src/glfs-master.c b/api/src/glfs-master.c
new file mode 100644
index 00000000000..100dcc16cc0
--- /dev/null
+++ b/api/src/glfs-master.c
@@ -0,0 +1,183 @@
+/*
+ Copyright (c) 2012-2016 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <stdio.h>
+
+#include <glusterfs/glusterfs.h>
+
+#include "glfs-internal.h"
+#include "glfs-mem-types.h"
+#include "gfapi-messages.h"
+
+int
+graph_setup(struct glfs *fs, glusterfs_graph_t *graph)
+{
+ xlator_t *new_subvol = NULL;
+ xlator_t *old_subvol = NULL;
+ inode_table_t *itable = NULL;
+ int ret = -1;
+
+ new_subvol = graph->top;
+
+ /* This is called in a bottom-up context, it should specifically
+ NOT be glfs_lock()
+ */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ if (new_subvol->switched || new_subvol == fs->active_subvol ||
+ new_subvol == fs->next_subvol || new_subvol == fs->mip_subvol) {
+ /* Spurious CHILD_UP event on old graph */
+ ret = 0;
+ goto unlock;
+ }
+
+ if (!new_subvol->itable) {
+ itable = inode_table_new(131072, new_subvol);
+ if (!itable) {
+ errno = ENOMEM;
+ ret = -1;
+ goto unlock;
+ }
+
+ new_subvol->itable = itable;
+ }
+
+ old_subvol = fs->next_subvol;
+ fs->next_subvol = new_subvol;
+ fs->next_subvol->winds++; /* first ref */
+ ret = 0;
+ }
+unlock:
+ pthread_mutex_unlock(&fs->mutex);
+
+ if (old_subvol)
+ /* wasn't picked up so far, skip */
+ glfs_subvol_done(fs, old_subvol);
+
+ return ret;
+}
+
+int
+notify(xlator_t *this, int event, void *data, ...)
+{
+ glusterfs_graph_t *graph = NULL;
+ struct glfs *fs = NULL;
+
+ graph = data;
+ fs = this->private;
+
+ switch (event) {
+ case GF_EVENT_GRAPH_NEW:
+ gf_smsg(this->name, GF_LOG_INFO, 0, API_MSG_NEW_GRAPH,
+ "graph-uuid=%s",
+ uuid_utoa((unsigned char *)graph->graph_uuid), "id=%d",
+ graph->id, NULL);
+ break;
+ case GF_EVENT_CHILD_UP:
+ pthread_mutex_lock(&fs->mutex);
+ {
+ graph->used = 1;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+ graph_setup(fs, graph);
+ glfs_init_done(fs, 0);
+ break;
+ case GF_EVENT_CHILD_DOWN:
+ pthread_mutex_lock(&fs->mutex);
+ {
+ graph->used = 0;
+ pthread_cond_broadcast(&fs->child_down_cond);
+ }
+ pthread_mutex_unlock(&fs->mutex);
+ glfs_init_done(fs, 1);
+ break;
+ case GF_EVENT_CHILD_CONNECTING:
+ break;
+ case GF_EVENT_UPCALL:
+ glfs_process_upcall_event(fs, data);
+ break;
+ default:
+ gf_msg_debug(this->name, 0, "got notify event %d", event);
+ break;
+ }
+
+ return 0;
+}
+
+int
+mem_acct_init(xlator_t *this)
+{
+ int ret = -1;
+
+ if (!this)
+ return ret;
+
+ ret = xlator_mem_acct_init(this, glfs_mt_end + 1);
+ if (ret) {
+ gf_smsg(this->name, GF_LOG_ERROR, ENOMEM, API_MSG_MEM_ACCT_INIT_FAILED,
+ NULL);
+ return ret;
+ }
+
+ return 0;
+}
+
+int
+init(xlator_t *this)
+{
+ return 0;
+}
+
+void
+fini(xlator_t *this)
+{
+}
+
+/* place-holder fops */
+int
+glfs_forget(xlator_t *this, inode_t *inode)
+{
+ return 0;
+}
+
+int
+glfs_release(xlator_t *this, fd_t *fd)
+{
+ return 0;
+}
+
+int
+glfs_releasedir(xlator_t *this, fd_t *fd)
+{
+ return 0;
+}
+
+struct xlator_dumpops dumpops;
+
+struct xlator_fops fops;
+
+struct xlator_cbks cbks = {
+ .forget = glfs_forget,
+ .release = glfs_release,
+ .releasedir = glfs_releasedir,
+};
+
+xlator_api_t xlator_api = {
+ .init = init,
+ .fini = fini,
+ .notify = notify,
+ .mem_acct_init = mem_acct_init,
+ .op_version = {1},
+ .dumpops = &dumpops,
+ .fops = &fops,
+ .cbks = &cbks,
+ .identifier = "glfs-api",
+ .category = GF_MAINTAINED,
+};
diff --git a/api/src/glfs-mem-types.h b/api/src/glfs-mem-types.h
new file mode 100644
index 00000000000..bfa325a3ad9
--- /dev/null
+++ b/api/src/glfs-mem-types.h
@@ -0,0 +1,35 @@
+/*
+ Copyright (c) 2012-2017 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _GLFS_MEM_TYPES_H
+#define _GLFS_MEM_TYPES_H
+
+#include <glusterfs/mem-types.h>
+
+#define GF_MEM_TYPE_START (gf_common_mt_end + 1)
+
+enum glfs_mem_types_ {
+ glfs_mt_call_pool_t = GF_MEM_TYPE_START,
+ glfs_mt_xlator_t,
+ glfs_mt_glfs_fd_t,
+ glfs_mt_glfs_io_t,
+ glfs_mt_volfile_t,
+ glfs_mt_xlator_cmdline_option_t,
+ glfs_mt_server_cmdline_t,
+ glfs_mt_glfs_object_t,
+ glfs_mt_readdirbuf_t,
+ glfs_mt_upcall_entry_t,
+ glfs_mt_acl_t,
+ glfs_mt_upcall_inode_t,
+ glfs_mt_realpath_t,
+ glfs_mt_xreaddirp_stat_t,
+ glfs_mt_end
+};
+#endif
diff --git a/api/src/glfs-mgmt.c b/api/src/glfs-mgmt.c
new file mode 100644
index 00000000000..7c82b8cd162
--- /dev/null
+++ b/api/src/glfs-mgmt.c
@@ -0,0 +1,1049 @@
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <pthread.h>
+
+#include <glusterfs/glusterfs.h>
+#include "glfs.h"
+#include <glusterfs/dict.h>
+
+#include "rpc-clnt.h"
+#include "protocol-common.h"
+#include "xdr-generic.h"
+#include "rpc-common-xdr.h"
+
+#include <glusterfs/syncop.h>
+
+#include "glfs-internal.h"
+#include "gfapi-messages.h"
+#include <glusterfs/syscall.h>
+
+int
+glfs_volfile_fetch(struct glfs *fs);
+int32_t
+glfs_get_volume_info_rpc(call_frame_t *frame, xlator_t *this, struct glfs *fs);
+
+int
+glfs_process_volfp(struct glfs *fs, FILE *fp)
+{
+ glusterfs_graph_t *graph = NULL;
+ int ret = -1;
+ xlator_t *trav = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+
+ ctx = fs->ctx;
+ graph = glusterfs_graph_construct(fp);
+ if (!graph) {
+ gf_smsg("glfs", GF_LOG_ERROR, errno, API_MSG_GRAPH_CONSTRUCT_FAILED,
+ NULL);
+ goto out;
+ }
+
+ for (trav = graph->first; trav; trav = trav->next) {
+ if (strcmp(trav->type, "mount/api") == 0) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_API_XLATOR_ERROR,
+ NULL);
+ goto out;
+ }
+ }
+
+ ret = glusterfs_graph_prepare(graph, ctx, fs->volname);
+ if (ret) {
+ glusterfs_graph_destroy(graph);
+ goto out;
+ }
+
+ ret = glusterfs_graph_activate(graph, ctx);
+
+ if (ret) {
+ glusterfs_graph_destroy(graph);
+ goto out;
+ }
+
+ gf_log_dump_graph(fp, graph);
+
+ ret = 0;
+out:
+ if (fp)
+ fclose(fp);
+
+ if (!ctx->active) {
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int
+mgmt_cbk_spec(struct rpc_clnt *rpc, void *mydata, void *data)
+{
+ struct glfs *fs = NULL;
+ xlator_t *this = NULL;
+
+ this = mydata;
+ fs = this->private;
+
+ glfs_volfile_fetch(fs);
+
+ return 0;
+}
+
+int
+mgmt_cbk_event(struct rpc_clnt *rpc, void *mydata, void *data)
+{
+ return 0;
+}
+
+static int
+mgmt_cbk_statedump(struct rpc_clnt *rpc, void *mydata, void *data)
+{
+ struct glfs *fs = NULL;
+ xlator_t *this = NULL;
+ gf_statedump target_pid = {
+ 0,
+ };
+ struct iovec *iov = NULL;
+ int ret = -1;
+
+ this = mydata;
+ if (!this) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "mydata", NULL);
+ errno = EINVAL;
+ goto out;
+ }
+
+ fs = this->private;
+ if (!fs) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "glfs", NULL);
+ errno = EINVAL;
+ goto out;
+ }
+
+ iov = (struct iovec *)data;
+ if (!iov) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_NULL, "iovec data", NULL);
+ errno = EINVAL;
+ goto out;
+ }
+
+ ret = xdr_to_generic(*iov, &target_pid, (xdrproc_t)xdr_gf_statedump);
+ if (ret < 0) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_DECODE_XDR_FAILED, NULL);
+ goto out;
+ }
+
+ gf_msg_trace("glfs", 0, "statedump requested for pid: %d", target_pid.pid);
+
+ if ((uint64_t)getpid() == target_pid.pid) {
+ gf_msg_debug("glfs", 0, "Taking statedump for pid: %d", target_pid.pid);
+
+ ret = glfs_sysrq(fs, GLFS_SYSRQ_STATEDUMP);
+ if (ret < 0) {
+ gf_smsg("glfs", GF_LOG_INFO, 0, API_MSG_STATEDUMP_FAILED, NULL);
+ }
+ }
+out:
+ return ret;
+}
+
+static rpcclnt_cb_actor_t mgmt_cbk_actors[GF_CBK_MAXVALUE] = {
+ [GF_CBK_FETCHSPEC] = {"FETCHSPEC", mgmt_cbk_spec, GF_CBK_FETCHSPEC},
+ [GF_CBK_EVENT_NOTIFY] = {"EVENTNOTIFY", mgmt_cbk_event,
+ GF_CBK_EVENT_NOTIFY},
+ [GF_CBK_STATEDUMP] = {"STATEDUMP", mgmt_cbk_statedump, GF_CBK_STATEDUMP},
+};
+
+static struct rpcclnt_cb_program mgmt_cbk_prog = {
+ .progname = "GlusterFS Callback",
+ .prognum = GLUSTER_CBK_PROGRAM,
+ .progver = GLUSTER_CBK_VERSION,
+ .actors = mgmt_cbk_actors,
+ .numactors = GF_CBK_MAXVALUE,
+};
+
+static char *clnt_handshake_procs[GF_HNDSK_MAXVALUE] = {
+ [GF_HNDSK_NULL] = "NULL",
+ [GF_HNDSK_SETVOLUME] = "SETVOLUME",
+ [GF_HNDSK_GETSPEC] = "GETSPEC",
+ [GF_HNDSK_PING] = "PING",
+ [GF_HNDSK_EVENT_NOTIFY] = "EVENTNOTIFY",
+ [GF_HNDSK_GET_VOLUME_INFO] = "GETVOLUMEINFO",
+};
+
+static rpc_clnt_prog_t clnt_handshake_prog = {
+ .progname = "GlusterFS Handshake",
+ .prognum = GLUSTER_HNDSK_PROGRAM,
+ .progver = GLUSTER_HNDSK_VERSION,
+ .procnames = clnt_handshake_procs,
+};
+
+int
+mgmt_submit_request(void *req, call_frame_t *frame, glusterfs_ctx_t *ctx,
+ rpc_clnt_prog_t *prog, int procnum, fop_cbk_fn_t cbkfn,
+ xdrproc_t xdrproc)
+{
+ int ret = -1;
+ int count = 0;
+ struct iovec iov = {
+ 0,
+ };
+ struct iobuf *iobuf = NULL;
+ struct iobref *iobref = NULL;
+ ssize_t xdr_size = 0;
+
+ iobref = iobref_new();
+ if (!iobref) {
+ goto out;
+ }
+
+ if (req) {
+ xdr_size = xdr_sizeof(xdrproc, req);
+
+ iobuf = iobuf_get2(ctx->iobuf_pool, xdr_size);
+ if (!iobuf) {
+ goto out;
+ };
+
+ iobref_add(iobref, iobuf);
+
+ iov.iov_base = iobuf->ptr;
+ iov.iov_len = iobuf_pagesize(iobuf);
+
+ /* Create the xdr payload */
+ ret = xdr_serialize_generic(iov, req, xdrproc);
+ if (ret == -1) {
+ gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_XDR_PAYLOAD_FAILED,
+ NULL);
+ goto out;
+ }
+ iov.iov_len = ret;
+ count = 1;
+ }
+
+ /* Send the msg */
+ ret = rpc_clnt_submit(ctx->mgmt, prog, procnum, cbkfn, &iov, count, NULL, 0,
+ iobref, frame, NULL, 0, NULL, 0, NULL);
+
+out:
+ if (iobref)
+ iobref_unref(iobref);
+
+ if (iobuf)
+ iobuf_unref(iobuf);
+ return ret;
+}
+
+/*
+ * Callback routine for 'GF_HNDSK_GET_VOLUME_INFO' rpc request
+ */
+int
+mgmt_get_volinfo_cbk(struct rpc_req *req, struct iovec *iov, int count,
+ void *myframe)
+{
+ int ret = 0;
+ char *volume_id_str = NULL;
+ dict_t *dict = NULL;
+ gf_get_volume_info_rsp rsp = {
+ 0,
+ };
+ call_frame_t *frame = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ struct glfs *fs = NULL;
+ struct syncargs *args;
+
+ frame = myframe;
+ ctx = frame->this->ctx;
+ args = frame->local;
+
+ if (!ctx) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_NULL,
+ "context", NULL);
+ errno = EINVAL;
+ ret = -1;
+ goto out;
+ }
+
+ fs = ((xlator_t *)ctx->master)->private;
+
+ if (-1 == req->rpc_status) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL,
+ API_MSG_CALL_NOT_SUCCESSFUL, NULL);
+ errno = EINVAL;
+ ret = -1;
+ goto out;
+ }
+
+ ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_get_volume_info_rsp);
+
+ if (ret < 0) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, 0,
+ API_MSG_XDR_RESPONSE_DECODE_FAILED, NULL);
+ goto out;
+ }
+
+ gf_msg_debug(frame->this->name, 0,
+ "Received resp to GET_VOLUME_INFO "
+ "RPC: %d",
+ rsp.op_ret);
+
+ if (rsp.op_ret == -1) {
+ errno = rsp.op_errno;
+ ret = -1;
+ goto out;
+ }
+
+ if (!rsp.dict.dict_len) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_CALL_NOT_VALID,
+ NULL);
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ dict = dict_new();
+
+ if (!dict) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = dict_unserialize(rsp.dict.dict_val, rsp.dict.dict_len, &dict);
+
+ if (ret) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = dict_get_str_sizen(dict, "volume_id", &volume_id_str);
+ if (ret) {
+ errno = EINVAL;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ if (volume_id_str) {
+ gf_msg_debug(frame->this->name, 0, "Volume Id: %s", volume_id_str);
+ pthread_mutex_lock(&fs->mutex);
+ gf_uuid_parse(volume_id_str, fs->vol_uuid);
+ pthread_mutex_unlock(&fs->mutex);
+ }
+
+ if (ret) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, errno,
+ API_MSG_GET_VOLINFO_CBK_FAILED, "error=%s", strerror(errno),
+ NULL);
+ }
+
+ if (dict)
+ dict_unref(dict);
+
+ if (rsp.dict.dict_val)
+ free(rsp.dict.dict_val);
+
+ if (rsp.op_errstr)
+ free(rsp.op_errstr);
+
+ gf_msg_debug(frame->this->name, 0, "Returning: %d", ret);
+
+ __wake(args);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_get_volumeid, 3.5.0)
+int
+pub_glfs_get_volumeid(struct glfs *fs, char *volid, size_t size)
+{
+ /* TODO: Define a global macro to store UUID size */
+ size_t uuid_size = 16;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ pthread_mutex_lock(&fs->mutex);
+ {
+ /* check if the volume uuid is initialized */
+ if (!gf_uuid_is_null(fs->vol_uuid)) {
+ pthread_mutex_unlock(&fs->mutex);
+ goto done;
+ }
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ /* Need to fetch volume_uuid */
+ glfs_get_volume_info(fs);
+
+ if (gf_uuid_is_null(fs->vol_uuid)) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_FETCH_VOLUUID_FAILED,
+ NULL);
+ goto out;
+ }
+
+done:
+ if (!volid || !size) {
+ gf_msg_debug(THIS->name, 0, "volumeid/size is null");
+ __GLFS_EXIT_FS;
+ return uuid_size;
+ }
+
+ if (size < uuid_size) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ERANGE, API_MSG_INSUFF_SIZE, NULL);
+ errno = ERANGE;
+ goto out;
+ }
+
+ memcpy(volid, fs->vol_uuid, uuid_size);
+
+ __GLFS_EXIT_FS;
+
+ return uuid_size;
+
+out:
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return -1;
+}
+
+int
+glfs_get_volume_info(struct glfs *fs)
+{
+ call_frame_t *frame = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ struct syncargs args = {
+ 0,
+ };
+ int ret = 0;
+
+ ctx = fs->ctx;
+ frame = create_frame(THIS, ctx->pool);
+ if (!frame) {
+ gf_smsg("glfs", GF_LOG_ERROR, ENOMEM, API_MSG_FRAME_CREAT_FAILED, NULL);
+ ret = -1;
+ goto out;
+ }
+
+ frame->local = &args;
+
+ __yawn((&args));
+
+ ret = glfs_get_volume_info_rpc(frame, THIS, fs);
+ if (ret)
+ goto out;
+
+ __yield((&args));
+
+ frame->local = NULL;
+ STACK_DESTROY(frame->root);
+
+out:
+ return ret;
+}
+
+int32_t
+glfs_get_volume_info_rpc(call_frame_t *frame, xlator_t *this, struct glfs *fs)
+{
+ gf_get_volume_info_req req = {{
+ 0,
+ }};
+ int ret = 0;
+ glusterfs_ctx_t *ctx = NULL;
+ dict_t *dict = NULL;
+ int32_t flags = 0;
+
+ if (!frame || !this || !fs) {
+ ret = -1;
+ goto out;
+ }
+
+ ctx = fs->ctx;
+
+ dict = dict_new();
+ if (!dict) {
+ ret = -1;
+ goto out;
+ }
+
+ if (fs->volname) {
+ ret = dict_set_str(dict, "volname", fs->volname);
+ if (ret)
+ goto out;
+ }
+
+ // Set the flags for the fields which we are interested in
+ flags = (int32_t)GF_GET_VOLUME_UUID; // ctx->flags;
+ ret = dict_set_int32(dict, "flags", flags);
+ if (ret) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL,
+ API_MSG_DICT_SET_FAILED, "flags", NULL);
+ goto out;
+ }
+
+ ret = dict_allocate_and_serialize(dict, &req.dict.dict_val,
+ &req.dict.dict_len);
+
+ ret = mgmt_submit_request(&req, frame, ctx, &clnt_handshake_prog,
+ GF_HNDSK_GET_VOLUME_INFO, mgmt_get_volinfo_cbk,
+ (xdrproc_t)xdr_gf_get_volume_info_req);
+out:
+ if (dict) {
+ dict_unref(dict);
+ }
+
+ GF_FREE(req.dict.dict_val);
+
+ return ret;
+}
+
+static int
+glusterfs_oldvolfile_update(struct glfs *fs, char *volfile, ssize_t size)
+{
+ int ret = -1;
+
+ pthread_mutex_lock(&fs->mutex);
+
+ fs->oldvollen = size;
+ if (!fs->oldvolfile) {
+ fs->oldvolfile = CALLOC(1, size + 1);
+ } else {
+ fs->oldvolfile = REALLOC(fs->oldvolfile, size + 1);
+ }
+
+ if (!fs->oldvolfile) {
+ fs->oldvollen = 0;
+ } else {
+ memcpy(fs->oldvolfile, volfile, size);
+ fs->oldvollen = size;
+ ret = 0;
+ }
+
+ pthread_mutex_unlock(&fs->mutex);
+
+ return ret;
+}
+
+int
+glfs_mgmt_getspec_cbk(struct rpc_req *req, struct iovec *iov, int count,
+ void *myframe)
+{
+ gf_getspec_rsp rsp = {
+ 0,
+ };
+ call_frame_t *frame = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ int ret = 0;
+ ssize_t size = 0;
+ FILE *tmpfp = NULL;
+ int need_retry = 0;
+ struct glfs *fs = NULL;
+ dict_t *dict = NULL;
+ char *servers_list = NULL;
+ int tmp_fd = -1;
+ char template[] = "/tmp/gfapi.volfile.XXXXXX";
+
+ frame = myframe;
+ ctx = frame->this->ctx;
+
+ if (!ctx) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, EINVAL, API_MSG_NULL,
+ "context", NULL);
+ errno = EINVAL;
+ ret = -1;
+ goto out;
+ }
+
+ fs = ((xlator_t *)ctx->master)->private;
+
+ if (-1 == req->rpc_status) {
+ ret = -1;
+ need_retry = 1;
+ goto out;
+ }
+
+ ret = xdr_to_generic(*iov, &rsp, (xdrproc_t)xdr_gf_getspec_rsp);
+ if (ret < 0) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, 0, API_MSG_XDR_DECODE_FAILED,
+ NULL);
+ ret = -1;
+ goto out;
+ }
+
+ if (-1 == rsp.op_ret) {
+ gf_smsg(frame->this->name, GF_LOG_ERROR, rsp.op_errno,
+ API_MSG_GET_VOLFILE_FAILED, "from server", NULL);
+ ret = -1;
+ errno = rsp.op_errno;
+ goto out;
+ }
+
+ if (!rsp.xdata.xdata_len) {
+ goto volfile;
+ }
+
+ dict = dict_new();
+ if (!dict) {
+ ret = -1;
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = dict_unserialize(rsp.xdata.xdata_val, rsp.xdata.xdata_len, &dict);
+ if (ret) {
+ gf_log(frame->this->name, GF_LOG_ERROR,
+ "failed to unserialize xdata to dictionary");
+ goto out;
+ }
+ dict->extra_stdfree = rsp.xdata.xdata_val;
+
+ /* glusterd2 only */
+ ret = dict_get_str(dict, "servers-list", &servers_list);
+ if (ret) {
+ goto volfile;
+ }
+
+ gf_log(frame->this->name, GF_LOG_INFO,
+ "Received list of available volfile servers: %s", servers_list);
+
+ ret = gf_process_getspec_servers_list(&ctx->cmd_args, servers_list);
+ if (ret) {
+ gf_log(frame->this->name, GF_LOG_ERROR,
+ "Failed (%s) to process servers list: %s", strerror(errno),
+ servers_list);
+ }
+
+volfile:
+ ret = 0;
+ size = rsp.op_ret;
+
+ pthread_mutex_lock(&fs->mutex);
+ if ((size == fs->oldvollen) &&
+ (memcmp(fs->oldvolfile, rsp.spec, size) == 0)) {
+ pthread_mutex_unlock(&fs->mutex);
+ gf_smsg(frame->this->name, GF_LOG_INFO, 0, API_MSG_VOLFILE_INFO, NULL);
+ goto out;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ /* coverity[secure_temp] mkstemp uses 0600 as the mode and is safe */
+ tmp_fd = mkstemp(template);
+ if (-1 == tmp_fd) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Calling unlink so that when the file is closed or program
+ * terminates the temporary file is deleted.
+ */
+ ret = sys_unlink(template);
+ if (ret < 0) {
+ gf_smsg(frame->this->name, GF_LOG_INFO, 0, API_MSG_UNABLE_TO_DEL,
+ "template=%s", template, NULL);
+ ret = 0;
+ }
+
+ tmpfp = fdopen(tmp_fd, "w+b");
+ if (!tmpfp) {
+ ret = -1;
+ goto out;
+ }
+
+ fwrite(rsp.spec, size, 1, tmpfp);
+ fflush(tmpfp);
+ if (ferror(tmpfp)) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Check if only options have changed. No need to reload the
+ * volfile if topology hasn't changed.
+ * glusterfs_volfile_reconfigure returns 3 possible return states
+ * return 0 =======> reconfiguration of options has succeeded
+ * return 1 =======> the graph has to be reconstructed and all
+ * the xlators should be inited return -1(or -ve) =======> Some Internal
+ * Error occurred during the operation
+ */
+
+ pthread_mutex_lock(&fs->mutex);
+ ret = gf_volfile_reconfigure(fs->oldvollen, tmpfp, fs->ctx, fs->oldvolfile);
+ pthread_mutex_unlock(&fs->mutex);
+
+ if (ret == 0) {
+ gf_msg_debug("glusterfsd-mgmt", 0,
+ "No need to re-load "
+ "volfile, reconfigure done");
+ ret = glusterfs_oldvolfile_update(fs, rsp.spec, size);
+ goto out;
+ }
+
+ if (ret < 0) {
+ gf_msg_debug("glusterfsd-mgmt", 0, "Reconfigure failed !!");
+ goto out;
+ }
+
+ ret = glfs_process_volfp(fs, tmpfp);
+ /* tmpfp closed */
+ tmpfp = NULL;
+ tmp_fd = -1;
+ if (ret)
+ goto out;
+
+ ret = glusterfs_oldvolfile_update(fs, rsp.spec, size);
+out:
+ STACK_DESTROY(frame->root);
+
+ if (rsp.spec)
+ free(rsp.spec);
+
+ if (dict)
+ dict_unref(dict);
+
+ // Stop if server is running at an unsupported op-version
+ if (ENOTSUP == ret) {
+ gf_smsg("mgmt", GF_LOG_ERROR, ENOTSUP, API_MSG_WRONG_OPVERSION, NULL);
+ errno = ENOTSUP;
+ glfs_init_done(fs, -1);
+ }
+
+ if (ret && ctx && !ctx->active) {
+ /* Do it only for the first time */
+ /* Failed to get the volume file, something wrong,
+ restart the process */
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, EINVAL, API_MSG_GET_VOLFILE_FAILED,
+ "key=%s", ctx->cmd_args.volfile_id, NULL);
+ if (!need_retry) {
+ if (!errno)
+ errno = EINVAL;
+ glfs_init_done(fs, -1);
+ }
+ }
+
+ if (tmpfp)
+ fclose(tmpfp);
+ else if (tmp_fd != -1)
+ sys_close(tmp_fd);
+
+ return 0;
+}
+
+int
+glfs_volfile_fetch(struct glfs *fs)
+{
+ cmd_args_t *cmd_args = NULL;
+ gf_getspec_req req = {
+ 0,
+ };
+ int ret = -1;
+ call_frame_t *frame = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ dict_t *dict = NULL;
+
+ ctx = fs->ctx;
+ cmd_args = &ctx->cmd_args;
+
+ req.key = cmd_args->volfile_id;
+ req.flags = 0;
+
+ dict = dict_new();
+ if (!dict) {
+ goto out;
+ }
+
+ // Set the supported min and max op-versions, so glusterd can make a
+ // decision
+ ret = dict_set_int32(dict, "min-op-version", GD_OP_VERSION_MIN);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_DICT_SET_FAILED,
+ "min-op-version", NULL);
+ goto out;
+ }
+
+ ret = dict_set_int32(dict, "max-op-version", GD_OP_VERSION_MAX);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, EINVAL, API_MSG_DICT_SET_FAILED,
+ "max-op-version", NULL);
+ goto out;
+ }
+
+ /* Ask for a list of volfile (glusterd2 only) servers */
+ if (GF_CLIENT_PROCESS == ctx->process_mode) {
+ req.flags = req.flags | GF_GETSPEC_FLAG_SERVERS_LIST;
+ }
+
+ ret = dict_allocate_and_serialize(dict, &req.xdata.xdata_val,
+ &req.xdata.xdata_len);
+ if (ret < 0) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, 0, API_MSG_DICT_SERIALIZE_FAILED,
+ NULL);
+ goto out;
+ }
+
+ frame = create_frame(THIS, ctx->pool);
+ if (!frame) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = mgmt_submit_request(&req, frame, ctx, &clnt_handshake_prog,
+ GF_HNDSK_GETSPEC, glfs_mgmt_getspec_cbk,
+ (xdrproc_t)xdr_gf_getspec_req);
+out:
+ if (req.xdata.xdata_val)
+ GF_FREE(req.xdata.xdata_val);
+ if (dict)
+ dict_unref(dict);
+
+ return ret;
+}
+
+static int
+mgmt_rpc_notify(struct rpc_clnt *rpc, void *mydata, rpc_clnt_event_t event,
+ void *data)
+{
+ xlator_t *this = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ server_cmdline_t *server = NULL;
+ rpc_transport_t *rpc_trans = NULL;
+ struct glfs *fs = NULL;
+ int ret = 0;
+ struct dnscache6 *dnscache = NULL;
+
+ this = mydata;
+ rpc_trans = rpc->conn.trans;
+
+ ctx = this->ctx;
+ if (!ctx)
+ goto out;
+
+ fs = ((xlator_t *)ctx->master)->private;
+
+ switch (event) {
+ case RPC_CLNT_DISCONNECT:
+ if (!ctx->active) {
+ if (rpc_trans->connect_failed)
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, 0,
+ API_MSG_REMOTE_HOST_CONN_FAILED, "server=%s",
+ ctx->cmd_args.volfile_server, NULL);
+ else
+ gf_smsg("glfs-mgmt", GF_LOG_INFO, 0,
+ API_MSG_REMOTE_HOST_CONN_FAILED, "server=%s",
+ ctx->cmd_args.volfile_server, NULL);
+
+ if (!rpc->disabled) {
+ /*
+ * Check if dnscache is exhausted for current server
+ * and continue until cache is exhausted
+ */
+ dnscache = rpc_trans->dnscache;
+ if (dnscache && dnscache->next) {
+ break;
+ }
+ }
+ server = ctx->cmd_args.curr_server;
+ if (server->list.next == &ctx->cmd_args.volfile_servers) {
+ errno = ENOTCONN;
+ gf_smsg("glfs-mgmt", GF_LOG_INFO, ENOTCONN,
+ API_MSG_VOLFILE_SERVER_EXHAUST, NULL);
+ glfs_init_done(fs, -1);
+ break;
+ }
+ server = list_entry(server->list.next, typeof(*server), list);
+ ctx->cmd_args.curr_server = server;
+ ctx->cmd_args.volfile_server_port = server->port;
+ ctx->cmd_args.volfile_server = server->volfile_server;
+ ctx->cmd_args.volfile_server_transport = server->transport;
+
+ ret = dict_set_str(rpc_trans->options, "transport-type",
+ server->transport);
+ if (ret != 0) {
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
+ API_MSG_DICT_SET_FAILED, "transport-type=%s",
+ server->transport, NULL);
+ errno = ENOTCONN;
+ glfs_init_done(fs, -1);
+ break;
+ }
+
+ if (strcmp(server->transport, "unix") == 0) {
+ ret = dict_set_str(rpc_trans->options,
+ "transport.socket.connect-path",
+ server->volfile_server);
+ if (ret != 0) {
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
+ API_MSG_DICT_SET_FAILED,
+ "socket.connect-path=%s",
+ server->volfile_server, NULL);
+ errno = ENOTCONN;
+ glfs_init_done(fs, -1);
+ break;
+ }
+ /* delete the remote-host and remote-port keys
+ * in case they were set while looping through
+ * list of volfile servers previously
+ */
+ dict_del(rpc_trans->options, "remote-host");
+ dict_del(rpc_trans->options, "remote-port");
+ } else {
+ ret = dict_set_int32(rpc_trans->options, "remote-port",
+ server->port);
+ if (ret != 0) {
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
+ API_MSG_DICT_SET_FAILED, "remote-port=%d",
+ server->port, NULL);
+ errno = ENOTCONN;
+ glfs_init_done(fs, -1);
+ break;
+ }
+
+ ret = dict_set_str(rpc_trans->options, "remote-host",
+ server->volfile_server);
+ if (ret != 0) {
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, ENOTCONN,
+ API_MSG_DICT_SET_FAILED, "remote-host=%s",
+ server->volfile_server, NULL);
+ errno = ENOTCONN;
+ glfs_init_done(fs, -1);
+ break;
+ }
+ /* delete the "transport.socket.connect-path"
+ * key in case if it was set while looping
+ * through list of volfile servers previously
+ */
+ dict_del(rpc_trans->options,
+ "transport.socket.connect-path");
+ }
+
+ gf_smsg("glfs-mgmt", GF_LOG_INFO, 0, API_MSG_VOLFILE_CONNECTING,
+ "server=%s", server->volfile_server, "port=%d",
+ server->port, "transport=%s", server->transport, NULL);
+ }
+ break;
+ case RPC_CLNT_CONNECT:
+ ret = glfs_volfile_fetch(fs);
+ if (ret && (ctx->active == NULL)) {
+ /* Do it only for the first time */
+ /* Exit the process.. there are some wrong options */
+ gf_smsg("glfs-mgmt", GF_LOG_ERROR, EINVAL,
+ API_MSG_GET_VOLFILE_FAILED, "key=%s",
+ ctx->cmd_args.volfile_id, NULL);
+ errno = EINVAL;
+ glfs_init_done(fs, -1);
+ }
+
+ break;
+ default:
+ break;
+ }
+out:
+ return 0;
+}
+
+int
+glusterfs_mgmt_notify(int32_t op, void *data, ...)
+{
+ int ret = 0;
+
+ switch (op) {
+ case GF_EN_DEFRAG_STATUS:
+ break;
+
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+int
+glfs_mgmt_init(struct glfs *fs)
+{
+ cmd_args_t *cmd_args = NULL;
+ struct rpc_clnt *rpc = NULL;
+ dict_t *options = NULL;
+ int ret = -1;
+ int port = GF_DEFAULT_BASE_PORT;
+ char *host = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+
+ ctx = fs->ctx;
+ cmd_args = &ctx->cmd_args;
+
+ if (ctx->mgmt)
+ return 0;
+
+ options = dict_new();
+ if (!options)
+ goto out;
+
+ if (cmd_args->volfile_server_port)
+ port = cmd_args->volfile_server_port;
+
+ if (cmd_args->volfile_server) {
+ host = cmd_args->volfile_server;
+ } else if (cmd_args->volfile_server_transport &&
+ !strcmp(cmd_args->volfile_server_transport, "unix")) {
+ host = DEFAULT_GLUSTERD_SOCKFILE;
+ } else {
+ host = "localhost";
+ }
+
+ if (cmd_args->volfile_server_transport &&
+ !strcmp(cmd_args->volfile_server_transport, "unix")) {
+ ret = rpc_transport_unix_options_build(options, host, 0);
+ } else {
+ xlator_cmdline_option_t *opt = find_xlator_option_in_cmd_args_t(
+ "address-family", cmd_args);
+ ret = rpc_transport_inet_options_build(options, host, port,
+ (opt ? opt->value : NULL));
+ }
+
+ if (ret)
+ goto out;
+
+ rpc = rpc_clnt_new(options, THIS, THIS->name, 8);
+ if (!rpc) {
+ ret = -1;
+ gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_CREATE_RPC_CLIENT_FAILED,
+ NULL);
+ goto out;
+ }
+
+ ret = rpc_clnt_register_notify(rpc, mgmt_rpc_notify, THIS);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_REG_NOTIFY_FUNC_FAILED,
+ NULL);
+ goto out;
+ }
+
+ ret = rpcclnt_cbk_program_register(rpc, &mgmt_cbk_prog, THIS);
+ if (ret) {
+ gf_smsg(THIS->name, GF_LOG_WARNING, 0, API_MSG_REG_CBK_FUNC_FAILED,
+ NULL);
+ goto out;
+ }
+
+ ctx->notify = glusterfs_mgmt_notify;
+
+ /* This value should be set before doing the 'rpc_clnt_start()' as
+ the notify function uses this variable */
+ ctx->mgmt = rpc;
+
+ ret = rpc_clnt_start(rpc);
+out:
+ if (options)
+ dict_unref(options);
+ return ret;
+}
diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c
new file mode 100644
index 00000000000..8a393ecb464
--- /dev/null
+++ b/api/src/glfs-resolve.c
@@ -0,0 +1,1199 @@
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <limits.h>
+
+#include <glusterfs/glusterfs.h>
+#include <glusterfs/logging.h>
+#include <glusterfs/stack.h>
+#include <glusterfs/gf-event.h>
+#include "glfs-mem-types.h"
+#include <glusterfs/common-utils.h>
+#include <glusterfs/syncop.h>
+#include <glusterfs/call-stub.h>
+#include "gfapi-messages.h"
+#include <glusterfs/inode.h>
+#include "glfs-internal.h"
+
+#define graphid_str(subvol) \
+ (uuid_utoa((unsigned char *)subvol->graph->graph_uuid))
+int
+glfs_first_lookup_safe(xlator_t *subvol)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+
+ loc.inode = subvol->itable->root;
+ memset(loc.gfid, 0, 16);
+ loc.gfid[15] = 1;
+ loc.path = "/";
+ loc.name = "";
+
+ ret = syncop_lookup(subvol, &loc, 0, 0, 0, 0);
+ DECODE_SYNCOP_ERR(ret);
+
+ gf_msg_debug(subvol->name, 0, "first lookup complete %d", ret);
+
+ return ret;
+}
+
+int
+__glfs_first_lookup(struct glfs *fs, xlator_t *subvol)
+{
+ int ret = -1;
+
+ fs->migration_in_progress = 1;
+ pthread_mutex_unlock(&fs->mutex);
+ {
+ ret = glfs_first_lookup_safe(subvol);
+ }
+ pthread_mutex_lock(&fs->mutex);
+ fs->migration_in_progress = 0;
+ pthread_cond_broadcast(&fs->cond);
+
+ /* wake up other waiting tasks */
+ __GLFS_SYNCTASK_WAKE(fs);
+
+ return ret;
+}
+
+/**
+ * We have to check if need_lookup flag is set in both old and the new inodes.
+ * If its set in oldinode, then directly go ahead and do an explicit lookup.
+ * But if its not set in the oldinode, then check if the newinode is linked
+ * via readdirp. If so an explicit lookup is needed on the new inode, so that
+ * below xlators can set their respective contexts.
+ */
+inode_t *
+glfs_refresh_inode_safe(xlator_t *subvol, inode_t *oldinode,
+ gf_boolean_t need_lookup)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ struct iatt iatt = {
+ 0,
+ };
+ inode_t *newinode = NULL;
+ gf_boolean_t lookup_needed = _gf_false;
+ uint64_t ctx_value = LOOKUP_NOT_NEEDED;
+
+ if (!oldinode)
+ return NULL;
+
+ if (!need_lookup && oldinode->table->xl == subvol)
+ return inode_ref(oldinode);
+
+ newinode = inode_find(subvol->itable, oldinode->gfid);
+ if (!need_lookup && newinode) {
+ lookup_needed = inode_needs_lookup(newinode, THIS);
+ if (!lookup_needed)
+ return newinode;
+ }
+
+ gf_uuid_copy(loc.gfid, oldinode->gfid);
+ if (!newinode)
+ loc.inode = inode_new(subvol->itable);
+ else
+ loc.inode = newinode;
+
+ if (!loc.inode)
+ return NULL;
+
+ ret = syncop_lookup(subvol, &loc, &iatt, 0, 0, 0);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret) {
+ gf_smsg(subvol->name, GF_LOG_WARNING, errno,
+ API_MSG_INODE_REFRESH_FAILED, "gfid=%s",
+ uuid_utoa(oldinode->gfid), "err=%s", strerror(errno), NULL);
+ loc_wipe(&loc);
+ return NULL;
+ }
+
+ newinode = inode_link(loc.inode, 0, 0, &iatt);
+ if (newinode) {
+ if (newinode == loc.inode)
+ inode_ctx_set(newinode, THIS, &ctx_value);
+ inode_lookup(newinode);
+ } else {
+ gf_smsg(subvol->name, GF_LOG_WARNING, errno, API_MSG_INODE_LINK_FAILED,
+ "gfid=%s", uuid_utoa((unsigned char *)&iatt.ia_gfid), NULL);
+ }
+
+ loc_wipe(&loc);
+
+ return newinode;
+}
+
+inode_t *
+__glfs_refresh_inode(struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ gf_boolean_t need_lookup)
+{
+ inode_t *newinode = NULL;
+
+ fs->migration_in_progress = 1;
+ pthread_mutex_unlock(&fs->mutex);
+ {
+ newinode = glfs_refresh_inode_safe(subvol, inode, need_lookup);
+ }
+ pthread_mutex_lock(&fs->mutex);
+ fs->migration_in_progress = 0;
+ pthread_cond_broadcast(&fs->cond);
+
+ /* wake up other waiting tasks */
+ __GLFS_SYNCTASK_WAKE(fs);
+
+ return newinode;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_loc_touchup, 3.4.0)
+int
+priv_glfs_loc_touchup(loc_t *loc)
+{
+ int ret = 0;
+
+ ret = loc_touchup(loc, loc->name);
+ if (ret < 0) {
+ errno = -ret;
+ ret = -1;
+ }
+
+ return ret;
+}
+
+int
+glfs_resolve_symlink(struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ char **lpath)
+{
+ loc_t loc = {
+ 0,
+ };
+ char *path = NULL;
+ char *rpath = NULL;
+ int ret = -1;
+
+ loc.inode = inode_ref(inode);
+ gf_uuid_copy(loc.gfid, inode->gfid);
+ ret = inode_path(inode, NULL, &rpath);
+ if (ret < 0)
+ goto out;
+ loc.path = rpath;
+
+ ret = syncop_readlink(subvol, &loc, &path, 4096, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+
+ if (ret < 0)
+ goto out;
+
+ if (lpath)
+ *lpath = path;
+out:
+ loc_wipe(&loc);
+ return ret;
+}
+
+int
+glfs_resolve_base(struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ struct iatt *iatt)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ char *path = NULL;
+
+ loc.inode = inode_ref(inode);
+ gf_uuid_copy(loc.gfid, inode->gfid);
+
+ ret = inode_path(loc.inode, NULL, &path);
+ loc.path = path;
+ if (ret < 0)
+ goto out;
+
+ ret = syncop_lookup(subvol, &loc, iatt, NULL, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ loc_wipe(&loc);
+
+ return ret;
+}
+/*
+ * This function can be used to call named lookup on root.
+ * If you use glfs_resolve_base, that will be a nameless lookup.
+ */
+static int
+glfs_resolve_root(struct glfs *fs, xlator_t *subvol, inode_t *inode,
+ struct iatt *iatt)
+{
+ loc_t loc = {
+ 0,
+ };
+ int ret = -1;
+ char *path = NULL;
+
+ loc.inode = inode_ref(inode);
+
+ ret = inode_path(loc.inode, ".", &path);
+ loc.path = path;
+ loc.name = ".";
+ /* Having a value in loc.name will help to bypass md-cache check for
+ * nameless lookup.
+ * TODO: Re-visit on nameless lookup and md-cache.
+ * Github issue : https://github.com/gluster/glusterfs/issues/232
+ */
+ loc.parent = inode_ref(inode);
+ if (ret < 0)
+ goto out;
+
+ ret = syncop_lookup(subvol, &loc, iatt, NULL, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+out:
+ loc_wipe(&loc);
+
+ return ret;
+}
+
+inode_t *
+glfs_resolve_component(struct glfs *fs, xlator_t *subvol, inode_t *parent,
+ const char *component, struct iatt *iatt,
+ int force_lookup)
+{
+ loc_t loc = {
+ 0,
+ };
+ inode_t *inode = NULL;
+ inode_t *temp_parent = NULL;
+ int reval = 0;
+ int ret = -1;
+ int glret = -1;
+ struct iatt ciatt = {
+ 0,
+ };
+ uuid_t gfid;
+ dict_t *xattr_req = NULL;
+ uint64_t ctx_value = LOOKUP_NOT_NEEDED;
+
+ loc.parent = inode_ref(parent);
+ gf_uuid_copy(loc.pargfid, parent->gfid);
+
+ if (__is_root_gfid(parent->gfid) &&
+ ((strcmp(component, ".") == 0) || (strcmp(component, "..") == 0) ||
+ (strcmp(component, "") == 0))) {
+ if (!force_lookup) {
+ inode = inode_ref(parent);
+ } else {
+ ret = glfs_resolve_root(fs, subvol, parent, &ciatt);
+ if (!ret)
+ inode = inode_ref(parent);
+ }
+ goto found;
+ }
+ /* *
+ * if the component name is either "." or "..", it will try to
+ * resolve that if inode has a proper parent (named lookup).
+ *
+ * Below condition works like this
+ *
+ * Example 1 :
+ * Path /out_dir/dir/in_dir/.
+ * In put values :
+ * parent = in_dir
+ * component : "."
+ *
+ * Out put values:
+ * parent : dir
+ * component : "in_dir"
+ *
+ * Example 2 :
+ * Path /out_dir/dir/in_dir/..
+ * In put values :
+ * parent = in_dir
+ * component : ".."
+ *
+ * Out put values:
+ * parent : output_dir
+ * component : "dir"
+ *
+ * In case of nameless lookup, both "." and ".." retained
+ */
+
+ if (strcmp(component, ".") == 0) {
+ loc.inode = inode_ref(parent);
+ temp_parent = inode_parent(loc.inode, 0, 0);
+ if (temp_parent) {
+ inode_unref(loc.parent);
+ loc.parent = temp_parent;
+ gf_uuid_copy(loc.pargfid, temp_parent->gfid);
+ inode_find_directory_name(loc.inode, &loc.name);
+ }
+
+ } else if (strcmp(component, "..") == 0) {
+ loc.inode = inode_parent(parent, 0, 0);
+ if (loc.inode) {
+ temp_parent = inode_parent(loc.inode, 0, 0);
+ if (temp_parent) {
+ inode_unref(loc.parent);
+ loc.parent = temp_parent;
+ gf_uuid_copy(loc.pargfid, temp_parent->gfid);
+ inode_find_directory_name(loc.inode, &loc.name);
+ } else if (__is_root_gfid(loc.inode->gfid)) {
+ inode_unref(loc.parent);
+ loc.parent = inode_ref(loc.inode);
+ gf_uuid_copy(loc.pargfid, loc.inode->gfid);
+ loc.name = ".";
+ } else {
+ inode_unref(loc.inode);
+ loc.inode = NULL;
+ }
+ }
+ } else
+ loc.inode = inode_grep(parent->table, parent, component);
+
+ if (!loc.name)
+ loc.name = component;
+
+ if (loc.inode) {
+ gf_uuid_copy(loc.gfid, loc.inode->gfid);
+ reval = 1;
+
+ if (!(force_lookup || inode_needs_lookup(loc.inode, THIS))) {
+ inode = inode_ref(loc.inode);
+ goto found;
+ }
+ } else {
+ gf_uuid_generate(gfid);
+ loc.inode = inode_new(parent->table);
+ if (!loc.inode) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ errno = ENOMEM;
+ goto out;
+ }
+ }
+
+ glret = priv_glfs_loc_touchup(&loc);
+ if (glret < 0) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = syncop_lookup(subvol, &loc, &ciatt, NULL, xattr_req, NULL);
+ if (ret && reval) {
+ /*
+ * A stale mapping might exist for a dentry/inode that has been
+ * removed from another client.
+ */
+ if (-ret == ENOENT) {
+ inode_unlink(loc.inode, loc.parent, loc.name);
+ if (!inode_has_dentry(loc.inode))
+ inode_forget(loc.inode, 0);
+ }
+
+ inode_unref(loc.inode);
+ gf_uuid_clear(loc.gfid);
+ loc.inode = inode_new(parent->table);
+ if (!loc.inode) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ xattr_req = dict_new();
+ if (!xattr_req) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ gf_uuid_generate(gfid);
+
+ ret = dict_set_gfuuid(xattr_req, "gfid-req", gfid, true);
+ if (ret) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ ret = syncop_lookup(subvol, &loc, &ciatt, NULL, xattr_req, NULL);
+ }
+ DECODE_SYNCOP_ERR(ret);
+ if (ret)
+ goto out;
+
+ inode = inode_link(loc.inode, loc.parent, component, &ciatt);
+
+ if (!inode) {
+ gf_smsg(subvol->name, GF_LOG_WARNING, errno, API_MSG_INODE_LINK_FAILED,
+ "gfid=%s", uuid_utoa((unsigned char *)&ciatt.ia_gfid), NULL);
+ goto out;
+ } else if (inode == loc.inode)
+ inode_ctx_set(inode, THIS, &ctx_value);
+found:
+ if (inode) {
+ ciatt.ia_type = inode->ia_type;
+ inode_lookup(inode);
+ }
+ if (iatt)
+ *iatt = ciatt;
+out:
+ if (xattr_req)
+ dict_unref(xattr_req);
+ loc_wipe(&loc);
+
+ return inode;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_resolve_at, 3.4.0)
+int
+priv_glfs_resolve_at(struct glfs *fs, xlator_t *subvol, inode_t *at,
+ const char *origpath, loc_t *loc, struct iatt *iatt,
+ int follow, int reval)
+{
+ inode_t *inode = NULL;
+ inode_t *parent = NULL;
+ char *saveptr = NULL;
+ char *path = NULL;
+ char *component = NULL;
+ char *next_component = NULL;
+ int ret = -1;
+ struct iatt ciatt = {
+ 0,
+ };
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (origpath[0] == '\0') {
+ errno = EINVAL;
+ goto invalid_fs;
+ }
+
+ parent = NULL;
+ if (at && origpath[0] != '/') {
+ /* A relative resolution of a path which starts with '/'
+ is equal to an absolute path resolution.
+ */
+ inode = inode_ref(at);
+ } else {
+ inode = inode_ref(subvol->itable->root);
+
+ if (strcmp(origpath, "/") == 0)
+ glfs_resolve_root(fs, subvol, inode, &ciatt);
+ }
+
+ path = gf_strdup(origpath);
+ if (!path)
+ goto invalid_fs;
+
+ for (component = strtok_r(path, "/", &saveptr); component;
+ component = next_component) {
+ next_component = strtok_r(NULL, "/", &saveptr);
+
+ if (parent)
+ inode_unref(parent);
+ parent = inode;
+ inode = glfs_resolve_component(fs, subvol, parent, component, &ciatt,
+ /* force hard lookup on the last
+ component, as the caller
+ wants proper iatt filled
+ */
+ (reval || (!next_component && iatt)));
+ if (!inode) {
+ ret = -1;
+ break;
+ }
+
+ if (IA_ISLNK(ciatt.ia_type) && (next_component || follow)) {
+ /* If the component is not the last piece,
+ then following it is necessary even if
+ not requested by the caller
+ */
+ char *lpath = NULL;
+ loc_t sym_loc = {
+ 0,
+ };
+
+ if (follow > GLFS_SYMLINK_MAX_FOLLOW) {
+ errno = ELOOP;
+ ret = -1;
+ if (inode) {
+ inode_unref(inode);
+ inode = NULL;
+ }
+ break;
+ }
+
+ ret = glfs_resolve_symlink(fs, subvol, inode, &lpath);
+ inode_unref(inode);
+ inode = NULL;
+ if (ret < 0)
+ break;
+
+ ret = priv_glfs_resolve_at(fs, subvol, parent, lpath, &sym_loc,
+ /* followed iatt becomes the
+ component iatt
+ */
+ &ciatt,
+ /* always recurisvely follow while
+ following symlink
+ */
+ follow + 1, reval);
+ if (ret == 0)
+ inode = inode_ref(sym_loc.inode);
+ loc_wipe(&sym_loc);
+ GF_FREE(lpath);
+ }
+
+ if (!next_component)
+ break;
+
+ if (!IA_ISDIR(ciatt.ia_type)) {
+ /* next_component exists and this component is
+ not a directory
+ */
+ inode_unref(inode);
+ inode = NULL;
+ ret = -1;
+ errno = ENOTDIR;
+ break;
+ }
+ }
+
+ if (parent && next_component)
+ /* resolution failed mid-way */
+ goto out;
+
+ /* At this point, all components up to the last parent directory
+ have been resolved successfully (@parent). Resolution of basename
+ might have failed (@inode) if at all.
+ */
+
+ loc->parent = parent;
+ if (parent) {
+ gf_uuid_copy(loc->pargfid, parent->gfid);
+ loc->name = component;
+ }
+
+ loc->inode = inode;
+ if (inode) {
+ gf_uuid_copy(loc->gfid, inode->gfid);
+ if (iatt)
+ *iatt = ciatt;
+ ret = 0;
+ }
+
+ if (priv_glfs_loc_touchup(loc) < 0) {
+ ret = -1;
+ }
+out:
+ GF_FREE(path);
+ __GLFS_EXIT_FS;
+
+ /* do NOT loc_wipe here as only last component might be missing */
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_resolve_path(struct glfs *fs, xlator_t *subvol, const char *origpath,
+ loc_t *loc, struct iatt *iatt, int follow, int reval)
+{
+ int ret = -1;
+ inode_t *cwd = NULL;
+
+ if (origpath[0] == '/')
+ return priv_glfs_resolve_at(fs, subvol, NULL, origpath, loc, iatt,
+ follow, reval);
+
+ cwd = glfs_cwd_get(fs);
+ if (NULL == cwd) {
+ gf_smsg(subvol->name, GF_LOG_WARNING, EIO, API_MSG_GET_CWD_FAILED,
+ NULL);
+ errno = EIO;
+ goto out;
+ }
+
+ ret = priv_glfs_resolve_at(fs, subvol, cwd, origpath, loc, iatt, follow,
+ reval);
+ if (cwd)
+ inode_unref(cwd);
+
+out:
+ return ret;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_resolve, 3.7.0)
+int
+priv_glfs_resolve(struct glfs *fs, xlator_t *subvol, const char *origpath,
+ loc_t *loc, struct iatt *iatt, int reval)
+{
+ int ret = -1;
+
+ ret = glfs_resolve_path(fs, subvol, origpath, loc, iatt, 1, reval);
+
+ return ret;
+}
+
+int
+glfs_lresolve(struct glfs *fs, xlator_t *subvol, const char *origpath,
+ loc_t *loc, struct iatt *iatt, int reval)
+{
+ int ret = -1;
+
+ ret = glfs_resolve_path(fs, subvol, origpath, loc, iatt, 0, reval);
+
+ return ret;
+}
+
+int
+glfs_migrate_fd_locks_safe(struct glfs *fs, xlator_t *oldsubvol, fd_t *oldfd,
+ xlator_t *newsubvol, fd_t *newfd)
+{
+ dict_t *lockinfo = NULL;
+ int ret = 0;
+ char uuid1[64];
+
+ if (!oldfd->lk_ctx || fd_lk_ctx_empty(oldfd->lk_ctx))
+ return 0;
+
+ newfd->lk_ctx = fd_lk_ctx_ref(oldfd->lk_ctx);
+
+ ret = syncop_fgetxattr(oldsubvol, oldfd, &lockinfo, GF_XATTR_LOCKINFO_KEY,
+ NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret < 0) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno, API_MSG_FGETXATTR_FAILED,
+ "gfid=%s", uuid_utoa_r(oldfd->inode->gfid, uuid1), "err=%s",
+ strerror(errno), "subvol=%s", graphid_str(oldsubvol), "id=%d",
+ oldsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ if (!dict_get(lockinfo, GF_XATTR_LOCKINFO_KEY)) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, 0, API_MSG_LOCKINFO_KEY_MISSING,
+ "gfid=%s", uuid_utoa_r(oldfd->inode->gfid, uuid1), "subvol=%s",
+ graphid_str(oldsubvol), "id=%d", oldsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ ret = syncop_fsetxattr(newsubvol, newfd, lockinfo, 0, NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret < 0) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, 0, API_MSG_FSETXATTR_FAILED,
+ "gfid=%s", uuid_utoa_r(newfd->inode->gfid, uuid1), "err=%s",
+ strerror(errno), "subvol=%s", graphid_str(newsubvol), "id=%d",
+ newsubvol->graph->id, NULL);
+ goto out;
+ }
+out:
+ if (lockinfo)
+ dict_unref(lockinfo);
+ return ret;
+}
+
+fd_t *
+glfs_migrate_fd_safe(struct glfs *fs, xlator_t *newsubvol, fd_t *oldfd)
+{
+ fd_t *newfd = NULL;
+ inode_t *oldinode = NULL;
+ inode_t *newinode = NULL;
+ xlator_t *oldsubvol = NULL;
+ int ret = -1;
+ loc_t loc = {
+ 0,
+ };
+ char uuid1[64];
+ dict_t *xdata = NULL;
+
+ oldinode = oldfd->inode;
+ oldsubvol = oldinode->table->xl;
+
+ if (oldsubvol == newsubvol)
+ return fd_ref(oldfd);
+
+ if (!oldsubvol->switched) {
+ xdata = dict_new();
+ if (!xdata || dict_set_int8(xdata, "last-fsync", 1)) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, ENOMEM, API_MSG_FSYNC_FAILED,
+ "err=%s", "last-fsync set failed", "gfid=%s",
+ uuid_utoa_r(oldfd->inode->gfid, uuid1), "subvol=%s",
+ graphid_str(oldsubvol), "id=%d", oldsubvol->graph->id,
+ NULL);
+ }
+
+ ret = syncop_fsync(oldsubvol, oldfd, 0, NULL, NULL, xdata, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ if (ret) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno, API_MSG_FSYNC_FAILED,
+ "err=%s", strerror(errno), "gfid=%s",
+ uuid_utoa_r(oldfd->inode->gfid, uuid1), "subvol=%s",
+ graphid_str(oldsubvol), "id=%d", oldsubvol->graph->id,
+ NULL);
+ }
+ }
+
+ newinode = glfs_refresh_inode_safe(newsubvol, oldinode, _gf_false);
+ if (!newinode) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno,
+ API_MSG_INODE_REFRESH_FAILED, "gfid=%s",
+ uuid_utoa_r(oldinode->gfid, uuid1), "err=%s", strerror(errno),
+ "subvol=%s", graphid_str(newsubvol), "id=%d",
+ newsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ newfd = fd_create(newinode, getpid());
+ if (!newfd) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno,
+ API_MSG_FDCREATE_FAILED_ON_GRAPH, "gfid=%s",
+ uuid_utoa_r(newinode->gfid, uuid1), "err=%s", strerror(errno),
+ "subvol=%s", graphid_str(newsubvol), "id=%d",
+ newsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ loc.inode = inode_ref(newinode);
+
+ ret = inode_path(oldfd->inode, NULL, (char **)&loc.path);
+ if (ret < 0) {
+ gf_smsg(fs->volname, GF_LOG_INFO, 0, API_MSG_INODE_PATH_FAILED, NULL);
+ goto out;
+ }
+
+ gf_uuid_copy(loc.gfid, oldinode->gfid);
+
+ if (IA_ISDIR(oldinode->ia_type))
+ ret = syncop_opendir(newsubvol, &loc, newfd, NULL, NULL);
+ else
+ ret = syncop_open(newsubvol, &loc,
+ oldfd->flags & ~(O_TRUNC | O_EXCL | O_CREAT), newfd,
+ NULL, NULL);
+ DECODE_SYNCOP_ERR(ret);
+ loc_wipe(&loc);
+
+ if (ret) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno, API_MSG_SYNCOP_OPEN_FAILED,
+ "type=%s", IA_ISDIR(oldinode->ia_type) ? "dir" : "", "gfid=%s",
+ uuid_utoa_r(newinode->gfid, uuid1), "err=%s", strerror(errno),
+ "subvol=%s", graphid_str(newsubvol), "id=%d",
+ newsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ ret = glfs_migrate_fd_locks_safe(fs, oldsubvol, oldfd, newsubvol, newfd);
+
+ if (ret) {
+ gf_smsg(fs->volname, GF_LOG_WARNING, errno, API_MSG_LOCK_MIGRATE_FAILED,
+ "gfid=%s", uuid_utoa_r(newinode->gfid, uuid1), "err=%s",
+ strerror(errno), "subvol=%s", graphid_str(newsubvol), "id=%d",
+ newsubvol->graph->id, NULL);
+ goto out;
+ }
+
+ newfd->flags = oldfd->flags;
+ fd_bind(newfd);
+out:
+ if (newinode)
+ inode_unref(newinode);
+
+ if (ret) {
+ fd_unref(newfd);
+ newfd = NULL;
+ }
+
+ if (xdata)
+ dict_unref(xdata);
+
+ return newfd;
+}
+
+fd_t *
+__glfs_migrate_fd(struct glfs *fs, xlator_t *newsubvol, struct glfs_fd *glfd)
+{
+ fd_t *oldfd = NULL;
+ fd_t *newfd = NULL;
+
+ oldfd = glfd->fd;
+
+ fs->migration_in_progress = 1;
+ pthread_mutex_unlock(&fs->mutex);
+ {
+ newfd = glfs_migrate_fd_safe(fs, newsubvol, oldfd);
+ }
+ pthread_mutex_lock(&fs->mutex);
+ fs->migration_in_progress = 0;
+ pthread_cond_broadcast(&fs->cond);
+
+ /* wake up other waiting tasks */
+ __GLFS_SYNCTASK_WAKE(fs);
+
+ return newfd;
+}
+
+fd_t *
+__glfs_resolve_fd(struct glfs *fs, xlator_t *subvol, struct glfs_fd *glfd)
+{
+ fd_t *fd = NULL;
+
+ if (glfd->fd->inode->table->xl == subvol)
+ return fd_ref(glfd->fd);
+
+ fd = __glfs_migrate_fd(fs, subvol, glfd);
+ if (!fd)
+ return NULL;
+
+ if (subvol == fs->active_subvol) {
+ fd_unref(glfd->fd);
+ glfd->fd = fd_ref(fd);
+ }
+
+ return fd;
+}
+
+fd_t *
+glfs_resolve_fd(struct glfs *fs, xlator_t *subvol, struct glfs_fd *glfd)
+{
+ fd_t *fd = NULL;
+
+ glfs_lock(fs, _gf_true);
+ {
+ fd = __glfs_resolve_fd(fs, subvol, glfd);
+ }
+ glfs_unlock(fs);
+
+ return fd;
+}
+
+void
+__glfs_migrate_openfds(struct glfs *fs, xlator_t *subvol)
+{
+ struct glfs_fd *glfd = NULL;
+ fd_t *fd = NULL;
+
+ list_for_each_entry(glfd, &fs->openfds, openfds)
+ {
+ if (gf_uuid_is_null(glfd->fd->inode->gfid)) {
+ gf_smsg(fs->volname, GF_LOG_INFO, 0, API_MSG_OPENFD_SKIPPED,
+ "glfd=%p", glfd, "glfd->fd=%p", glfd->fd, "subvol=%s",
+ graphid_str(subvol), "id=%d", subvol->graph->id, NULL);
+ /* create in progress, defer */
+ continue;
+ }
+
+ fd = __glfs_migrate_fd(fs, subvol, glfd);
+ if (fd) {
+ fd_unref(glfd->fd);
+ glfd->fd = fd;
+ }
+ }
+}
+
+/* Note that though it appears that this function executes under fs->mutex,
+ * it is not fully executed under fs->mutex. i.e. there are functions like
+ * __glfs_first_lookup, __glfs_refresh_inode, __glfs_migrate_openfds which
+ * unlocks fs->mutex before sending any network fop, and reacquire fs->mutex
+ * once the fop is complete. Hence the variable read from fs at the start of the
+ * function need not have the same value by the end of the function.
+ */
+xlator_t *
+__glfs_active_subvol(struct glfs *fs)
+{
+ xlator_t *new_subvol = NULL;
+ int ret = -1;
+ inode_t *new_cwd = NULL;
+
+ if (!fs->next_subvol)
+ return fs->active_subvol;
+
+ new_subvol = fs->mip_subvol = fs->next_subvol;
+ fs->next_subvol = NULL;
+
+ ret = __glfs_first_lookup(fs, new_subvol);
+ if (ret) {
+ gf_smsg(fs->volname, GF_LOG_INFO, errno,
+ API_MSG_FIRST_LOOKUP_GRAPH_FAILED, "subvol=%s",
+ graphid_str(new_subvol), "id=%d", new_subvol->graph->id,
+ "err=%s", strerror(errno), NULL);
+ return NULL;
+ }
+
+ if (fs->cwd) {
+ new_cwd = __glfs_refresh_inode(fs, new_subvol, fs->cwd, _gf_false);
+
+ if (!new_cwd) {
+ char buf1[64];
+ gf_smsg(fs->volname, GF_LOG_INFO, errno,
+ API_MSG_CWD_GRAPH_REF_FAILED, "buf=%s",
+ uuid_utoa_r(fs->cwd->gfid, buf1), "subvol=%s",
+ graphid_str(new_subvol), "id=%d", new_subvol->graph->id,
+ "err=%s", strerror(errno), NULL);
+ return NULL;
+ }
+ }
+
+ __glfs_migrate_openfds(fs, new_subvol);
+ /* TODO: Migrate the fds and inodes which have leases to the new graph
+ * (issue #350)*/
+
+ /* switching @active_subvol and @cwd
+ should be atomic
+ */
+ fs->old_subvol = fs->active_subvol;
+ fs->active_subvol = fs->mip_subvol;
+ fs->mip_subvol = NULL;
+
+ if (new_cwd) {
+ __glfs_cwd_set(fs, new_cwd);
+ inode_unref(new_cwd);
+ }
+
+ gf_smsg(fs->volname, GF_LOG_INFO, 0, API_MSG_SWITCHED_GRAPH, "subvol=%s",
+ graphid_str(new_subvol), "id=%d", new_subvol->graph->id, NULL);
+
+ return new_subvol;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_subvol_done, 3.4.0)
+void
+priv_glfs_subvol_done(struct glfs *fs, xlator_t *subvol)
+{
+ int ref = 0;
+ xlator_t *active_subvol = NULL;
+
+ if (!subvol)
+ return;
+
+ /* For decrementing subvol->wind ref count we need not check/wait for
+ * migration-in-progress flag.
+ * Also glfs_subvol_done is called in call-back path therefore waiting
+ * for migration-in-progress flag can lead to dead-lock.
+ */
+ glfs_lock(fs, _gf_false);
+ {
+ ref = (--subvol->winds);
+ active_subvol = fs->active_subvol;
+ }
+ glfs_unlock(fs);
+
+ if (ref == 0) {
+ assert(subvol != active_subvol);
+ xlator_notify(subvol, GF_EVENT_PARENT_DOWN, subvol, NULL);
+ }
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_active_subvol, 3.4.0)
+xlator_t *
+priv_glfs_active_subvol(struct glfs *fs)
+{
+ xlator_t *subvol = NULL;
+ xlator_t *old_subvol = NULL;
+
+ glfs_lock(fs, _gf_true);
+ {
+ subvol = __glfs_active_subvol(fs);
+
+ if (subvol)
+ subvol->winds++;
+
+ if (fs->old_subvol) {
+ old_subvol = fs->old_subvol;
+ fs->old_subvol = NULL;
+ old_subvol->switched = 1;
+ }
+ }
+ glfs_unlock(fs);
+
+ if (old_subvol)
+ priv_glfs_subvol_done(fs, old_subvol);
+
+ return subvol;
+}
+
+int
+__glfs_cwd_set(struct glfs *fs, inode_t *inode)
+{
+ if (inode->table->xl != fs->active_subvol) {
+ inode = __glfs_refresh_inode(fs, fs->active_subvol, inode, _gf_false);
+ if (!inode)
+ return -1;
+ } else {
+ inode_ref(inode);
+ }
+
+ if (fs->cwd)
+ inode_unref(fs->cwd);
+
+ fs->cwd = inode;
+
+ return 0;
+}
+
+int
+glfs_cwd_set(struct glfs *fs, inode_t *inode)
+{
+ int ret = 0;
+
+ glfs_lock(fs, _gf_true);
+ {
+ ret = __glfs_cwd_set(fs, inode);
+ }
+ glfs_unlock(fs);
+
+ return ret;
+}
+
+inode_t *
+__glfs_cwd_get(struct glfs *fs)
+{
+ inode_t *cwd = NULL;
+
+ if (!fs->cwd)
+ return NULL;
+
+ if (fs->cwd->table->xl == fs->active_subvol) {
+ cwd = inode_ref(fs->cwd);
+ return cwd;
+ }
+
+ cwd = __glfs_refresh_inode(fs, fs->active_subvol, fs->cwd, _gf_false);
+
+ return cwd;
+}
+
+inode_t *
+glfs_cwd_get(struct glfs *fs)
+{
+ inode_t *cwd = NULL;
+
+ glfs_lock(fs, _gf_true);
+ {
+ cwd = __glfs_cwd_get(fs);
+ }
+ glfs_unlock(fs);
+
+ return cwd;
+}
+
+inode_t *
+__glfs_resolve_inode(struct glfs *fs, xlator_t *subvol,
+ struct glfs_object *object)
+{
+ inode_t *inode = NULL;
+ gf_boolean_t lookup_needed = _gf_false;
+
+ lookup_needed = inode_needs_lookup(object->inode, THIS);
+
+ if (!lookup_needed && object->inode->table->xl == subvol)
+ return inode_ref(object->inode);
+
+ inode = __glfs_refresh_inode(fs, fs->active_subvol, object->inode,
+ lookup_needed);
+ if (!inode)
+ return NULL;
+
+ if (subvol == fs->active_subvol) {
+ inode_unref(object->inode);
+ object->inode = inode_ref(inode);
+ }
+
+ return inode;
+}
+
+inode_t *
+glfs_resolve_inode(struct glfs *fs, xlator_t *subvol,
+ struct glfs_object *object)
+{
+ inode_t *inode = NULL;
+
+ glfs_lock(fs, _gf_true);
+ {
+ inode = __glfs_resolve_inode(fs, subvol, object);
+ }
+ glfs_unlock(fs);
+
+ return inode;
+}
+
+int
+glfs_create_object(loc_t *loc, struct glfs_object **retobject)
+{
+ struct glfs_object *object = NULL;
+
+ object = GF_CALLOC(1, sizeof(struct glfs_object), glfs_mt_glfs_object_t);
+ if (object == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+
+ object->inode = loc->inode;
+ gf_uuid_copy(object->gfid, object->inode->gfid);
+
+ /* we hold the reference */
+ loc->inode = NULL;
+
+ *retobject = object;
+
+ return 0;
+}
+
+struct glfs_object *
+glfs_h_resolve_symlink(struct glfs *fs, struct glfs_object *object)
+{
+ xlator_t *subvol = NULL;
+ loc_t sym_loc = {
+ 0,
+ };
+ struct iatt iatt = {
+ 0,
+ };
+ char *lpath = NULL;
+ int ret = 0;
+ struct glfs_object *target_object = NULL;
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ ret = glfs_resolve_symlink(fs, subvol, object->inode, &lpath);
+ if (ret < 0)
+ goto out;
+
+ ret = glfs_resolve_at(fs, subvol, NULL, lpath, &sym_loc, &iatt,
+ /* always recurisvely follow while
+ following symlink
+ */
+ 1, 0);
+ if (ret == 0)
+ ret = glfs_create_object(&sym_loc, &target_object);
+
+out:
+ loc_wipe(&sym_loc);
+ GF_FREE(lpath);
+ return target_object;
+}
diff --git a/api/src/glfs.c b/api/src/glfs.c
new file mode 100644
index 00000000000..b4bf1423f6d
--- /dev/null
+++ b/api/src/glfs.c
@@ -0,0 +1,1806 @@
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+/*
+ TODO:
+ - set proper pid/lk_owner to call frames (currently buried in syncop)
+ - fix logging.c/h to store logfp and loglevel in glusterfs_ctx_t and
+ reach it via THIS.
+ - update syncop functions to accept/return xdata. ???
+ - protocol/client to reconnect immediately after portmap disconnect.
+ - handle SEEK_END failure in _lseek()
+ - handle umask (per filesystem?)
+ - make itables LRU based
+ - 0-copy for readv/writev
+ - reconcile the open/creat mess
+*/
+
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <inttypes.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <limits.h>
+#ifdef GF_LINUX_HOST_OS
+#include <sys/prctl.h>
+#endif
+
+#include <glusterfs/glusterfs.h>
+#include <glusterfs/logging.h>
+#include <glusterfs/stack.h>
+#include <glusterfs/gf-event.h>
+#include "glfs-mem-types.h"
+#include <glusterfs/common-utils.h>
+#include <glusterfs/syncop.h>
+#include <glusterfs/call-stub.h>
+#include <glusterfs/hashfn.h>
+#include "rpc-clnt.h"
+#include <glusterfs/statedump.h>
+#include <glusterfs/syscall.h>
+
+#include "gfapi-messages.h"
+#include "glfs.h"
+#include "glfs-internal.h"
+
+static gf_boolean_t
+vol_assigned(cmd_args_t *args)
+{
+ return args->volfile || args->volfile_server;
+}
+
+static int
+glusterfs_ctx_defaults_init(glusterfs_ctx_t *ctx)
+{
+ call_pool_t *pool = NULL;
+ int ret = -1;
+
+ if (!ctx) {
+ goto err;
+ }
+
+ ret = xlator_mem_acct_init(THIS, glfs_mt_end + 1);
+ if (ret != 0) {
+ gf_smsg(THIS->name, GF_LOG_ERROR, ENOMEM, API_MSG_MEM_ACCT_INIT_FAILED,
+ NULL);
+ return ret;
+ }
+
+ /* reset ret to -1 so that we don't need to explicitly
+ * set it in all error paths before "goto err"
+ */
+
+ ret = -1;
+
+ ctx->process_uuid = generate_glusterfs_ctx_id();
+ if (!ctx->process_uuid) {
+ goto err;
+ }
+
+ ctx->page_size = 128 * GF_UNIT_KB;
+
+ ctx->iobuf_pool = iobuf_pool_new();
+ if (!ctx->iobuf_pool) {
+ goto err;
+ }
+
+ ctx->event_pool = gf_event_pool_new(DEFAULT_EVENT_POOL_SIZE,
+ STARTING_EVENT_THREADS);
+ if (!ctx->event_pool) {
+ goto err;
+ }
+
+ ctx->env = syncenv_new(0, 0, 0);
+ if (!ctx->env) {
+ goto err;
+ }
+
+ pool = GF_CALLOC(1, sizeof(call_pool_t), glfs_mt_call_pool_t);
+ if (!pool) {
+ goto err;
+ }
+
+ /* frame_mem_pool size 112 * 4k */
+ pool->frame_mem_pool = mem_pool_new(call_frame_t, 4096);
+ if (!pool->frame_mem_pool) {
+ goto err;
+ }
+ /* stack_mem_pool size 256 * 1024 */
+ pool->stack_mem_pool = mem_pool_new(call_stack_t, 1024);
+ if (!pool->stack_mem_pool) {
+ goto err;
+ }
+
+ ctx->stub_mem_pool = mem_pool_new(call_stub_t, 1024);
+ if (!ctx->stub_mem_pool) {
+ goto err;
+ }
+
+ ctx->dict_pool = mem_pool_new(dict_t, GF_MEMPOOL_COUNT_OF_DICT_T);
+ if (!ctx->dict_pool)
+ goto err;
+
+ ctx->dict_pair_pool = mem_pool_new(data_pair_t,
+ GF_MEMPOOL_COUNT_OF_DATA_PAIR_T);
+ if (!ctx->dict_pair_pool)
+ goto err;
+
+ ctx->dict_data_pool = mem_pool_new(data_t, GF_MEMPOOL_COUNT_OF_DATA_T);
+ if (!ctx->dict_data_pool)
+ goto err;
+
+ ctx->logbuf_pool = mem_pool_new(log_buf_t, GF_MEMPOOL_COUNT_OF_LRU_BUF_T);
+ if (!ctx->logbuf_pool)
+ goto err;
+
+ INIT_LIST_HEAD(&pool->all_frames);
+ INIT_LIST_HEAD(&ctx->cmd_args.xlator_options);
+ INIT_LIST_HEAD(&ctx->cmd_args.volfile_servers);
+
+ LOCK_INIT(&pool->lock);
+ ctx->pool = pool;
+
+ ret = 0;
+err:
+ if (ret && pool) {
+ if (pool->frame_mem_pool)
+ mem_pool_destroy(pool->frame_mem_pool);
+ if (pool->stack_mem_pool)
+ mem_pool_destroy(pool->stack_mem_pool);
+ GF_FREE(pool);
+ }
+
+ if (ret && ctx) {
+ if (ctx->stub_mem_pool)
+ mem_pool_destroy(ctx->stub_mem_pool);
+ if (ctx->dict_pool)
+ mem_pool_destroy(ctx->dict_pool);
+ if (ctx->dict_data_pool)
+ mem_pool_destroy(ctx->dict_data_pool);
+ if (ctx->dict_pair_pool)
+ mem_pool_destroy(ctx->dict_pair_pool);
+ if (ctx->logbuf_pool)
+ mem_pool_destroy(ctx->logbuf_pool);
+ }
+
+ return ret;
+}
+
+static int
+create_master(struct glfs *fs)
+{
+ int ret = 0;
+ xlator_t *master = NULL;
+
+ master = GF_CALLOC(1, sizeof(*master), glfs_mt_xlator_t);
+ if (!master)
+ goto err;
+
+ master->name = gf_strdup("gfapi");
+ if (!master->name)
+ goto err;
+
+ if (xlator_set_type(master, "mount/api") == -1) {
+ gf_smsg("glfs", GF_LOG_ERROR, 0, API_MSG_MASTER_XLATOR_INIT_FAILED,
+ "name=%s", fs->volname, NULL);
+ goto err;
+ }
+
+ master->ctx = fs->ctx;
+ master->private = fs;
+ master->options = dict_new();
+ if (!master->options)
+ goto err;
+
+ ret = xlator_init(master);
+ if (ret) {
+ gf_smsg("glfs", GF_LOG_ERROR, 0, API_MSG_GFAPI_XLATOR_INIT_FAILED,
+ NULL);
+ goto err;
+ }
+
+ fs->ctx->master = master;
+ THIS = master;
+
+ return 0;
+
+err:
+ if (master) {
+ xlator_destroy(master);
+ }
+
+ return -1;
+}
+
+static FILE *
+get_volfp(struct glfs *fs)
+{
+ cmd_args_t *cmd_args = NULL;
+ FILE *specfp = NULL;
+
+ cmd_args = &fs->ctx->cmd_args;
+
+ if ((specfp = fopen(cmd_args->volfile, "r")) == NULL) {
+ gf_smsg("glfs", GF_LOG_ERROR, errno, API_MSG_VOLFILE_OPEN_FAILED,
+ "file=%s", cmd_args->volfile, "err=%s", strerror(errno), NULL);
+ return NULL;
+ }
+
+ gf_msg_debug("glfs", 0, "loading volume file %s", cmd_args->volfile);
+
+ return specfp;
+}
+
+int
+glfs_volumes_init(struct glfs *fs)
+{
+ FILE *fp = NULL;
+ cmd_args_t *cmd_args = NULL;
+ int ret = 0;
+
+ cmd_args = &fs->ctx->cmd_args;
+
+ if (!vol_assigned(cmd_args))
+ return -1;
+
+ if (sys_access(SECURE_ACCESS_FILE, F_OK) == 0) {
+ fs->ctx->secure_mgmt = 1;
+ fs->ctx->ssl_cert_depth = glusterfs_read_secure_access_file();
+ }
+
+ if (cmd_args->volfile_server) {
+ ret = glfs_mgmt_init(fs);
+ goto out;
+ }
+
+ fp = get_volfp(fs);
+
+ if (!fp) {
+ gf_smsg("glfs", GF_LOG_ERROR, ENOENT, API_MSG_VOL_SPEC_FILE_ERROR,
+ NULL);
+ ret = -1;
+ goto out;
+ }
+
+ ret = glfs_process_volfp(fs, fp);
+ if (ret)
+ goto out;
+
+out:
+ return ret;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_xlator_option, 3.4.0)
+int
+pub_glfs_set_xlator_option(struct glfs *fs, const char *xlator, const char *key,
+ const char *value)
+{
+ xlator_cmdline_option_t *option = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ option = GF_CALLOC(1, sizeof(*option), glfs_mt_xlator_cmdline_option_t);
+ if (!option)
+ goto enomem;
+
+ INIT_LIST_HEAD(&option->cmd_args);
+
+ option->volume = gf_strdup(xlator);
+ if (!option->volume)
+ goto enomem;
+ option->key = gf_strdup(key);
+ if (!option->key)
+ goto enomem;
+ option->value = gf_strdup(value);
+ if (!option->value)
+ goto enomem;
+
+ list_add(&option->cmd_args, &fs->ctx->cmd_args.xlator_options);
+
+ __GLFS_EXIT_FS;
+
+ return 0;
+enomem:
+ errno = ENOMEM;
+
+ if (!option) {
+ __GLFS_EXIT_FS;
+ return -1;
+ }
+
+ GF_FREE(option->volume);
+ GF_FREE(option->key);
+ GF_FREE(option->value);
+ GF_FREE(option);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return -1;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_unset_volfile_server, 3.5.1)
+int
+pub_glfs_unset_volfile_server(struct glfs *fs, const char *transport,
+ const char *host, const int port)
+{
+ cmd_args_t *cmd_args = NULL;
+ server_cmdline_t *server = NULL;
+ server_cmdline_t *tmp = NULL;
+ char *transport_val = NULL;
+ int port_val = 0;
+ int ret = -1;
+
+ if (!fs || !host) {
+ errno = EINVAL;
+ return ret;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ cmd_args = &fs->ctx->cmd_args;
+
+ if (transport) {
+ transport_val = gf_strdup(transport);
+ } else {
+ transport_val = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
+ }
+
+ if (!transport_val) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ if (port) {
+ port_val = port;
+ } else {
+ port_val = GF_DEFAULT_BASE_PORT;
+ }
+
+ list_for_each_entry_safe(server, tmp, &cmd_args->curr_server->list, list)
+ {
+ if (!server->volfile_server || !server->transport)
+ continue;
+ if ((!strcmp(server->volfile_server, host) &&
+ !strcmp(server->transport, transport_val) &&
+ (server->port == port_val))) {
+ list_del(&server->list);
+ ret = 0;
+ goto out;
+ }
+ }
+
+out:
+ GF_FREE(transport_val);
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile_server, 3.4.0)
+int
+pub_glfs_set_volfile_server(struct glfs *fs, const char *transport,
+ const char *host, int port)
+{
+ cmd_args_t *cmd_args = NULL;
+ int ret = -1;
+ char *server_host = NULL;
+ char *server_transport = NULL;
+
+ if (!fs || !host) {
+ errno = EINVAL;
+ return ret;
+ }
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ cmd_args = &fs->ctx->cmd_args;
+ cmd_args->max_connect_attempts = 1;
+
+ server_host = gf_strdup(host);
+ if (!server_host) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ if (transport) {
+ /* volfile fetch support over tcp|unix only */
+ if (!strcmp(transport, "tcp") || !strcmp(transport, "unix")) {
+ server_transport = gf_strdup(transport);
+ } else if (!strcmp(transport, "rdma")) {
+ server_transport = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
+ gf_smsg("glfs", GF_LOG_WARNING, EINVAL, API_MSG_TRANS_RDMA_DEP,
+ NULL);
+ } else {
+ gf_smsg("glfs", GF_LOG_TRACE, EINVAL, API_MSG_TRANS_NOT_SUPPORTED,
+ "transport=%s", transport, NULL);
+ goto out;
+ }
+ } else {
+ server_transport = gf_strdup(GF_DEFAULT_VOLFILE_TRANSPORT);
+ }
+
+ if (!server_transport) {
+ errno = ENOMEM;
+ goto out;
+ }
+
+ if (!port) {
+ port = GF_DEFAULT_BASE_PORT;
+ }
+
+ if (!strcmp(server_transport, "unix")) {
+ port = 0;
+ }
+
+ ret = gf_set_volfile_server_common(cmd_args, server_host, server_transport,
+ port);
+ if (ret) {
+ gf_log("glfs", GF_LOG_ERROR, "failed to set volfile server: %s",
+ strerror(errno));
+ }
+
+out:
+ if (server_host) {
+ GF_FREE(server_host);
+ }
+
+ if (server_transport) {
+ GF_FREE(server_transport);
+ }
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+/* *
+ * Used to free the arguments allocated by glfs_set_volfile_server()
+ */
+static void
+glfs_free_volfile_servers(cmd_args_t *cmd_args)
+{
+ server_cmdline_t *server = NULL;
+ server_cmdline_t *tmp = NULL;
+
+ GF_VALIDATE_OR_GOTO(THIS->name, cmd_args, out);
+
+ list_for_each_entry_safe(server, tmp, &cmd_args->volfile_servers, list)
+ {
+ list_del_init(&server->list);
+ GF_FREE(server->volfile_server);
+ GF_FREE(server->transport);
+ GF_FREE(server);
+ }
+ cmd_args->curr_server = NULL;
+out:
+ return;
+}
+
+static void
+glfs_free_xlator_options(cmd_args_t *cmd_args)
+{
+ xlator_cmdline_option_t *xo = NULL;
+ xlator_cmdline_option_t *tmp_xo = NULL;
+
+ if (!&(cmd_args->xlator_options))
+ return;
+
+ list_for_each_entry_safe(xo, tmp_xo, &cmd_args->xlator_options, cmd_args)
+ {
+ list_del_init(&xo->cmd_args);
+ GF_FREE(xo->volume);
+ GF_FREE(xo->key);
+ GF_FREE(xo->value);
+ GF_FREE(xo);
+ }
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsuid, 3.4.2)
+int
+pub_glfs_setfsuid(uid_t fsuid)
+{
+ /* TODO:
+ * - Set the THIS and restore it appropriately
+ */
+ return syncopctx_setfsuid(&fsuid);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsgid, 3.4.2)
+int
+pub_glfs_setfsgid(gid_t fsgid)
+{
+ /* TODO:
+ * - Set the THIS and restore it appropriately
+ */
+ return syncopctx_setfsgid(&fsgid);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsgroups, 3.4.2)
+int
+pub_glfs_setfsgroups(size_t size, const gid_t *list)
+{
+ /* TODO:
+ * - Set the THIS and restore it appropriately
+ */
+ return syncopctx_setfsgroups(size, list);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsleaseid, 4.0.0)
+int
+pub_glfs_setfsleaseid(glfs_leaseid_t leaseid)
+{
+ int ret = -1;
+ char *gleaseid = NULL;
+
+ gleaseid = gf_leaseid_get();
+ if (gleaseid) {
+ if (leaseid)
+ memcpy(gleaseid, leaseid, LEASE_ID_SIZE);
+ else /* reset leaseid */
+ memset(gleaseid, 0, LEASE_ID_SIZE);
+ ret = 0;
+ }
+
+ if (ret)
+ gf_log("glfs", GF_LOG_ERROR, "failed to set leaseid: %s",
+ strerror(errno));
+ return ret;
+}
+
+int
+get_fop_attr_glfd(dict_t **fop_attr, struct glfs_fd *glfd)
+{
+ char *leaseid = NULL;
+ int ret = 0;
+ gf_boolean_t dict_create = _gf_false;
+
+ leaseid = GF_MALLOC(LEASE_ID_SIZE, gf_common_mt_char);
+ GF_CHECK_ALLOC_AND_LOG("gfapi", leaseid, ret, "lease id alloc failed", out);
+ memcpy(leaseid, glfd->lease_id, LEASE_ID_SIZE);
+ if (*fop_attr == NULL) {
+ *fop_attr = dict_new();
+ dict_create = _gf_true;
+ }
+ GF_CHECK_ALLOC_AND_LOG("gfapi", *fop_attr, ret, "dict_new failed", out);
+ ret = dict_set_bin(*fop_attr, "lease-id", leaseid, LEASE_ID_SIZE);
+out:
+ if (ret) {
+ GF_FREE(leaseid);
+ if (dict_create) {
+ if (*fop_attr)
+ dict_unref(*fop_attr);
+ *fop_attr = NULL;
+ }
+ }
+ return ret;
+}
+
+int
+set_fop_attr_glfd(struct glfs_fd *glfd)
+{
+ char *lease_id = NULL;
+ int ret = -1;
+
+ lease_id = gf_existing_leaseid();
+ if (lease_id) {
+ memcpy(glfd->lease_id, lease_id, LEASE_ID_SIZE);
+ ret = 0;
+ }
+ return ret;
+}
+
+int
+get_fop_attr_thrd_key(dict_t **fop_attr)
+{
+ char *existing_leaseid = NULL, *leaseid = NULL;
+ int ret = 0;
+ gf_boolean_t dict_create = _gf_false;
+
+ existing_leaseid = gf_existing_leaseid();
+ if (existing_leaseid) {
+ leaseid = GF_MALLOC(LEASE_ID_SIZE, gf_common_mt_char);
+ GF_CHECK_ALLOC_AND_LOG("gfapi", leaseid, ret, "lease id alloc failed",
+ out);
+ memcpy(leaseid, existing_leaseid, LEASE_ID_SIZE);
+ if (*fop_attr == NULL) {
+ *fop_attr = dict_new();
+ dict_create = _gf_true;
+ }
+ GF_CHECK_ALLOC_AND_LOG("gfapi", *fop_attr, ret, "dict_new failed", out);
+ ret = dict_set_bin(*fop_attr, "lease-id", leaseid, LEASE_ID_SIZE);
+ }
+
+out:
+ if (ret) {
+ GF_FREE(leaseid);
+ if (dict_create) {
+ if (*fop_attr)
+ dict_unref(*fop_attr);
+ *fop_attr = NULL;
+ }
+ }
+ return ret;
+}
+
+void
+unset_fop_attr(dict_t **fop_attr)
+{
+ char *lease_id = NULL;
+ lease_id = gf_existing_leaseid();
+ if (lease_id)
+ memset(lease_id, 0, LEASE_ID_SIZE);
+ if (*fop_attr) {
+ dict_unref(*fop_attr);
+ *fop_attr = NULL;
+ }
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_from_glfd, 3.4.0)
+struct glfs *
+pub_glfs_from_glfd(struct glfs_fd *glfd)
+{
+ if (glfd == NULL) {
+ errno = EBADF;
+ return NULL;
+ }
+
+ return glfd->fs;
+}
+
+static void
+glfs_fd_destroy(struct glfs_fd *glfd)
+{
+ if (!glfd)
+ return;
+
+ glfs_lock(glfd->fs, _gf_true);
+ {
+ list_del_init(&glfd->openfds);
+ }
+ glfs_unlock(glfd->fs);
+
+ if (glfd->fd) {
+ fd_unref(glfd->fd);
+ glfd->fd = NULL;
+ }
+
+ GF_FREE(glfd->readdirbuf);
+
+ GF_FREE(glfd);
+}
+
+struct glfs_fd *
+glfs_fd_new(struct glfs *fs)
+{
+ struct glfs_fd *glfd = NULL;
+
+ glfd = GF_CALLOC(1, sizeof(*glfd), glfs_mt_glfs_fd_t);
+ if (!glfd)
+ return NULL;
+
+ glfd->fs = fs;
+
+ INIT_LIST_HEAD(&glfd->openfds);
+
+ GF_REF_INIT(glfd, glfs_fd_destroy);
+
+ return glfd;
+}
+
+void
+glfs_fd_bind(struct glfs_fd *glfd)
+{
+ struct glfs *fs = NULL;
+
+ fs = glfd->fs;
+
+ glfs_lock(fs, _gf_true);
+ {
+ list_add_tail(&glfd->openfds, &fs->openfds);
+ }
+ glfs_unlock(fs);
+}
+
+static void *
+glfs_poller(void *data)
+{
+ struct glfs *fs = NULL;
+
+ fs = data;
+
+ gf_event_dispatch(fs->ctx->event_pool);
+
+ return NULL;
+}
+
+static struct glfs *
+glfs_new_fs(const char *volname)
+{
+ struct glfs *fs = NULL;
+
+ fs = CALLOC(1, sizeof(*fs));
+ if (!fs)
+ return NULL;
+
+ INIT_LIST_HEAD(&fs->openfds);
+ INIT_LIST_HEAD(&fs->upcall_list);
+ INIT_LIST_HEAD(&fs->waitq);
+
+ PTHREAD_MUTEX_INIT(&fs->mutex, NULL, fs->pthread_flags, GLFS_INIT_MUTEX,
+ err);
+
+ PTHREAD_COND_INIT(&fs->cond, NULL, fs->pthread_flags, GLFS_INIT_COND, err);
+
+ PTHREAD_COND_INIT(&fs->child_down_cond, NULL, fs->pthread_flags,
+ GLFS_INIT_COND_CHILD, err);
+
+ PTHREAD_MUTEX_INIT(&fs->upcall_list_mutex, NULL, fs->pthread_flags,
+ GLFS_INIT_MUTEX_UPCALL, err);
+
+ fs->volname = strdup(volname);
+ if (!fs->volname)
+ goto err;
+
+ fs->pin_refcnt = 0;
+ fs->upcall_events = 0;
+ fs->up_cbk = NULL;
+ fs->up_data = NULL;
+
+ return fs;
+
+err:
+ glfs_free_from_ctx(fs);
+ return NULL;
+}
+
+extern xlator_t global_xlator;
+extern glusterfs_ctx_t *global_ctx;
+extern pthread_mutex_t global_ctx_mutex;
+
+static int
+glfs_init_global_ctx()
+{
+ int ret = 0;
+ glusterfs_ctx_t *ctx = NULL;
+
+ pthread_mutex_lock(&global_ctx_mutex);
+ {
+ if (global_xlator.ctx)
+ goto unlock;
+
+ ctx = glusterfs_ctx_new();
+ if (!ctx) {
+ ret = -1;
+ goto unlock;
+ }
+
+ gf_log_globals_init(ctx, GF_LOG_NONE);
+
+ global_ctx = ctx;
+ global_xlator.ctx = global_ctx;
+
+ ret = glusterfs_ctx_defaults_init(ctx);
+ if (ret) {
+ global_ctx = NULL;
+ global_xlator.ctx = NULL;
+ goto unlock;
+ }
+ }
+unlock:
+ pthread_mutex_unlock(&global_ctx_mutex);
+
+ if (ret)
+ FREE(ctx);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_new, 3.4.0)
+struct glfs *
+pub_glfs_new(const char *volname)
+{
+ if (!volname) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ struct glfs *fs = NULL;
+ int i = 0;
+ int ret = -1;
+ glusterfs_ctx_t *ctx = NULL;
+ xlator_t *old_THIS = NULL;
+ char pname[16] = "";
+ char msg[32] = "";
+
+ if (volname[0] == '/' || volname[0] == '-') {
+ if (strncmp(volname, "/snaps/", 7) == 0) {
+ goto label;
+ }
+ errno = EINVAL;
+ return NULL;
+ }
+
+ for (i = 0; i < strlen(volname); i++) {
+ if (!isalnum(volname[i]) && (volname[i] != '_') &&
+ (volname[i] != '-')) {
+ errno = EINVAL;
+ return NULL;
+ }
+ }
+
+label:
+ /*
+ * Do this as soon as possible in case something else depends on
+ * pool allocations.
+ */
+ mem_pools_init();
+
+ fs = glfs_new_fs(volname);
+ if (!fs)
+ goto out;
+
+ ctx = glusterfs_ctx_new();
+ if (!ctx)
+ goto out;
+
+ /* first globals init, for gf_mem_acct_enable_set () */
+
+ ret = glusterfs_globals_init(ctx);
+ if (ret)
+ goto out;
+
+ old_THIS = THIS;
+ ret = glfs_init_global_ctx();
+ if (ret)
+ goto out;
+
+ /* then ctx_defaults_init, for xlator_mem_acct_init(THIS) */
+
+ ret = glusterfs_ctx_defaults_init(ctx);
+ if (ret)
+ goto out;
+
+ fs->ctx = ctx;
+ fs->ctx->process_mode = GF_CLIENT_PROCESS;
+
+ ret = glfs_set_logging(fs, "/dev/null", 0);
+ if (ret)
+ goto out;
+
+ fs->ctx->cmd_args.volfile_id = gf_strdup(volname);
+ if (!(fs->ctx->cmd_args.volfile_id)) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = -1;
+#ifdef GF_LINUX_HOST_OS
+ ret = prctl(PR_GET_NAME, (unsigned long)pname, 0, 0, 0);
+#endif
+ if (ret)
+ fs->ctx->cmd_args.process_name = gf_strdup("gfapi");
+ else {
+ snprintf(msg, sizeof(msg), "gfapi.%s", pname);
+ fs->ctx->cmd_args.process_name = gf_strdup(msg);
+ }
+ ret = 0;
+
+out:
+ if (ret) {
+ if (fs) {
+ glfs_fini(fs);
+ fs = NULL;
+ } else {
+ /* glfs_fini() calls mem_pools_fini() too */
+ mem_pools_fini();
+ }
+ }
+
+ if (old_THIS)
+ THIS = old_THIS;
+
+ return fs;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_new_from_ctx, 3.7.0)
+struct glfs *
+priv_glfs_new_from_ctx(glusterfs_ctx_t *ctx)
+{
+ struct glfs *fs = NULL;
+
+ if (!ctx)
+ goto out;
+
+ fs = glfs_new_fs("");
+ if (!fs)
+ goto out;
+
+ fs->ctx = ctx;
+
+out:
+ return fs;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_free_from_ctx, 3.7.0)
+void
+priv_glfs_free_from_ctx(struct glfs *fs)
+{
+ upcall_entry *u_list = NULL;
+ upcall_entry *tmp = NULL;
+
+ if (!fs)
+ return;
+
+ /* cleanup upcall structures */
+ list_for_each_entry_safe(u_list, tmp, &fs->upcall_list, upcall_list)
+ {
+ list_del_init(&u_list->upcall_list);
+ GF_FREE(u_list->upcall_data.data);
+ GF_FREE(u_list);
+ }
+
+ PTHREAD_MUTEX_DESTROY(&fs->mutex, fs->pthread_flags, GLFS_INIT_MUTEX);
+
+ PTHREAD_COND_DESTROY(&fs->cond, fs->pthread_flags, GLFS_INIT_COND);
+
+ PTHREAD_COND_DESTROY(&fs->child_down_cond, fs->pthread_flags,
+ GLFS_INIT_COND_CHILD);
+
+ PTHREAD_MUTEX_DESTROY(&fs->upcall_list_mutex, fs->pthread_flags,
+ GLFS_INIT_MUTEX_UPCALL);
+
+ if (fs->oldvolfile)
+ FREE(fs->oldvolfile);
+
+ FREE(fs->volname);
+
+ FREE(fs);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_volfile, 3.4.0)
+int
+pub_glfs_set_volfile(struct glfs *fs, const char *volfile)
+{
+ cmd_args_t *cmd_args = NULL;
+
+ cmd_args = &fs->ctx->cmd_args;
+
+ if (vol_assigned(cmd_args))
+ return -1;
+
+ cmd_args->volfile = gf_strdup(volfile);
+ if (!cmd_args->volfile)
+ return -1;
+ return 0;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_logging, 3.4.0)
+int
+pub_glfs_set_logging(struct glfs *fs, const char *logfile, int loglevel)
+{
+ int ret = -1;
+ char *tmplog = NULL;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (!logfile) {
+ ret = gf_set_log_file_path(&fs->ctx->cmd_args, fs->ctx);
+ if (ret)
+ goto out;
+ tmplog = fs->ctx->cmd_args.log_file;
+ } else {
+ tmplog = (char *)logfile;
+ }
+
+ /* finish log set parameters before init */
+ if (loglevel >= 0)
+ gf_log_set_loglevel(fs->ctx, loglevel);
+
+ ret = gf_log_init(fs->ctx, tmplog, NULL);
+ if (ret)
+ goto out;
+
+ ret = gf_log_inject_timer_event(fs->ctx);
+ if (ret)
+ goto out;
+
+out:
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+int
+glfs_init_wait(struct glfs *fs)
+{
+ int ret = -1;
+
+ /* Always a top-down call, use glfs_lock() */
+ glfs_lock(fs, _gf_true);
+ {
+ while (!fs->init)
+ pthread_cond_wait(&fs->cond, &fs->mutex);
+ ret = fs->ret;
+ errno = fs->err;
+ }
+ glfs_unlock(fs);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_init_done, 3.4.0)
+void
+priv_glfs_init_done(struct glfs *fs, int ret)
+{
+ glfs_init_cbk init_cbk;
+
+ if (!fs) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_GLFS_FSOBJ_NULL, NULL);
+ goto out;
+ }
+
+ init_cbk = fs->init_cbk;
+
+ /* Always a bottom-up call, use mutex_lock() */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ fs->init = 1;
+ fs->ret = ret;
+ fs->err = errno;
+
+ if (!init_cbk)
+ pthread_cond_broadcast(&fs->cond);
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ if (init_cbk)
+ init_cbk(fs, ret);
+out:
+ return;
+}
+
+int
+glfs_init_common(struct glfs *fs)
+{
+ int ret = -1;
+
+ ret = create_master(fs);
+ if (ret)
+ return ret;
+
+ ret = gf_thread_create(&fs->poller, NULL, glfs_poller, fs, "glfspoll");
+ if (ret)
+ return ret;
+
+ ret = glfs_volumes_init(fs);
+ if (ret)
+ return ret;
+
+ fs->dev_id = gf_dm_hashfn(fs->volname, strlen(fs->volname));
+ return ret;
+}
+
+int
+glfs_init_async(struct glfs *fs, glfs_init_cbk cbk)
+{
+ int ret = -1;
+
+ if (!fs || !fs->ctx) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_FS_NOT_INIT, NULL);
+ errno = EINVAL;
+ return ret;
+ }
+
+ fs->init_cbk = cbk;
+
+ ret = glfs_init_common(fs);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_init, 3.4.0)
+int
+pub_glfs_init(struct glfs *fs)
+{
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+
+ if (!fs || !fs->ctx) {
+ gf_smsg("glfs", GF_LOG_ERROR, EINVAL, API_MSG_FS_NOT_INIT, NULL);
+ errno = EINVAL;
+ return ret;
+ }
+
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ ret = glfs_init_common(fs);
+ if (ret)
+ goto out;
+
+ ret = glfs_init_wait(fs);
+out:
+ __GLFS_EXIT_FS;
+
+ /* Set the initial current working directory to "/" */
+ if (ret >= 0) {
+ ret = glfs_chdir(fs, "/");
+ }
+
+invalid_fs:
+ return ret;
+}
+
+static int
+glusterfs_ctx_destroy(glusterfs_ctx_t *ctx)
+{
+ call_pool_t *pool = NULL;
+ int ret = 0;
+ glusterfs_graph_t *trav_graph = NULL;
+ glusterfs_graph_t *tmp = NULL;
+
+ if (ctx == NULL)
+ return 0;
+
+ if (ctx->cmd_args.curr_server)
+ glfs_free_volfile_servers(&ctx->cmd_args);
+
+ glfs_free_xlator_options(&ctx->cmd_args);
+
+ /* For all the graphs, crawl through the xlator_t structs and free
+ * all its members except for the mem_acct member,
+ * as GF_FREE will be referencing it.
+ */
+ list_for_each_entry_safe(trav_graph, tmp, &ctx->graphs, list)
+ {
+ xlator_tree_free_members(trav_graph->first);
+ }
+
+ /* Free the memory pool */
+ if (ctx->stub_mem_pool)
+ mem_pool_destroy(ctx->stub_mem_pool);
+ if (ctx->dict_pool)
+ mem_pool_destroy(ctx->dict_pool);
+ if (ctx->dict_data_pool)
+ mem_pool_destroy(ctx->dict_data_pool);
+ if (ctx->dict_pair_pool)
+ mem_pool_destroy(ctx->dict_pair_pool);
+ if (ctx->logbuf_pool)
+ mem_pool_destroy(ctx->logbuf_pool);
+
+ pool = ctx->pool;
+ if (pool) {
+ if (pool->frame_mem_pool)
+ mem_pool_destroy(pool->frame_mem_pool);
+ if (pool->stack_mem_pool)
+ mem_pool_destroy(pool->stack_mem_pool);
+ LOCK_DESTROY(&pool->lock);
+ GF_FREE(pool);
+ }
+
+ /* Free the event pool */
+ ret = gf_event_pool_destroy(ctx->event_pool);
+
+ /* Free the iobuf pool */
+ iobuf_pool_destroy(ctx->iobuf_pool);
+
+ GF_FREE(ctx->process_uuid);
+ GF_FREE(ctx->cmd_args.volfile_id);
+ GF_FREE(ctx->cmd_args.process_name);
+
+ LOCK_DESTROY(&ctx->lock);
+ pthread_mutex_destroy(&ctx->notify_lock);
+ pthread_cond_destroy(&ctx->notify_cond);
+
+ /* Free all the graph structs and its containing xlator_t structs
+ * from this point there should be no reference to GF_FREE/GF_CALLOC
+ * as it will try to access mem_acct and the below function would
+ * have freed the same.
+ */
+ list_for_each_entry_safe(trav_graph, tmp, &ctx->graphs, list)
+ {
+ glusterfs_graph_destroy_residual(trav_graph);
+ }
+
+ GF_FREE(ctx->statedump_path);
+ FREE(ctx);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_fini, 3.4.0)
+int
+pub_glfs_fini(struct glfs *fs)
+{
+ int ret = -1;
+ int countdown = 100;
+ xlator_t *subvol = NULL;
+ glusterfs_ctx_t *ctx = NULL;
+ glusterfs_graph_t *graph = NULL;
+ call_pool_t *call_pool = NULL;
+ int fs_init = 0;
+ int err = -1;
+ struct synctask *waittask = NULL;
+
+ DECLARE_OLD_THIS;
+
+ if (!fs) {
+ errno = EINVAL;
+ goto invalid_fs;
+ }
+
+ ctx = fs->ctx;
+ if (!ctx) {
+ goto free_fs;
+ }
+
+ THIS = fs->ctx->master;
+
+ if (ctx->mgmt) {
+ rpc_clnt_disable(ctx->mgmt);
+ }
+
+ call_pool = fs->ctx->pool;
+
+ /* Wake up any suspended synctasks */
+ while (!list_empty(&fs->waitq)) {
+ waittask = list_entry(fs->waitq.next, struct synctask, waitq);
+ list_del_init(&waittask->waitq);
+ synctask_wake(waittask);
+ }
+
+ while (countdown--) {
+ /* give some time for background frames to finish */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ /* Do we need to increase countdown? */
+ if ((!call_pool->cnt) && (!fs->pin_refcnt)) {
+ gf_msg_trace("glfs", 0,
+ "call_pool_cnt - %" PRId64
+ ","
+ "pin_refcnt - %d",
+ call_pool->cnt, fs->pin_refcnt);
+
+ ctx->cleanup_started = 1;
+ pthread_mutex_unlock(&fs->mutex);
+ break;
+ }
+ }
+ pthread_mutex_unlock(&fs->mutex);
+ gf_nanosleep(100000 * GF_US_IN_NS);
+ }
+
+ /* leaked frames may exist, we ignore */
+
+ /*We deem glfs_fini as successful if there are no pending frames in the call
+ *pool*/
+ ret = (call_pool->cnt == 0) ? 0 : -1;
+
+ pthread_mutex_lock(&fs->mutex);
+ {
+ fs_init = fs->init;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+ if (fs_init != 0) {
+ subvol = glfs_active_subvol(fs);
+ if (subvol) {
+ /* PARENT_DOWN within glfs_subvol_done() is issued
+ only on graph switch (new graph should activiate
+ and decrement the extra @winds count taken in
+ glfs_graph_setup()
+
+ Since we are explicitly destroying,
+ PARENT_DOWN is necessary
+ */
+ xlator_notify(subvol, GF_EVENT_PARENT_DOWN, subvol, 0);
+ /* Here we wait for GF_EVENT_CHILD_DOWN before exiting,
+ in case of asynchrnous cleanup
+ */
+ graph = subvol->graph;
+ err = pthread_mutex_lock(&fs->mutex);
+ if (err != 0) {
+ gf_smsg("glfs", GF_LOG_ERROR, err, API_MSG_FSMUTEX_LOCK_FAILED,
+ "error=%s", strerror(err), NULL);
+ goto fail;
+ }
+ /* check and wait for CHILD_DOWN for active subvol*/
+ {
+ while (graph->used) {
+ err = pthread_cond_wait(&fs->child_down_cond, &fs->mutex);
+ if (err != 0)
+ gf_smsg("glfs", GF_LOG_INFO, err,
+ API_MSG_COND_WAIT_FAILED, "name=%s",
+ subvol->name, "err=%s", strerror(err), NULL);
+ }
+ }
+
+ err = pthread_mutex_unlock(&fs->mutex);
+ if (err != 0) {
+ gf_smsg("glfs", GF_LOG_ERROR, err,
+ API_MSG_FSMUTEX_UNLOCK_FAILED, "error=%s",
+ strerror(err), NULL);
+ goto fail;
+ }
+ }
+ glfs_subvol_done(fs, subvol);
+ }
+
+ ctx->cleanup_started = 1;
+
+ if (fs_init != 0) {
+ /* Destroy all the inode tables of all the graphs.
+ * NOTE:
+ * - inode objects should be destroyed before calling fini()
+ * of each xlator, as fini() and forget() of the xlators
+ * can share few common locks or data structures, calling
+ * fini first might destroy those required by forget
+ * ( eg: in quick-read)
+ * - The call to inode_table_destroy_all is not required when
+ * the cleanup during graph switch is implemented to perform
+ * inode table destroy.
+ */
+ inode_table_destroy_all(ctx);
+
+ /* Call fini() of all the xlators in the active graph
+ * NOTE:
+ * - xlator fini() should be called before destroying any of
+ * the threads. (eg: fini() in protocol-client uses timer
+ * thread) */
+ glusterfs_graph_deactivate(ctx->active);
+
+ /* Join the syncenv_processor threads and cleanup
+ * syncenv resources*/
+ syncenv_destroy(ctx->env);
+
+ /* Join the poller thread */
+ if (gf_event_dispatch_destroy(ctx->event_pool) < 0)
+ ret = -1;
+ }
+
+ /* Avoid dispatching events to mgmt after freed,
+ * unreference mgmt after the event_dispatch_destroy */
+ if (ctx->mgmt) {
+ rpc_clnt_unref(ctx->mgmt);
+ ctx->mgmt = NULL;
+ }
+
+ /* log infra has to be brought down before destroying
+ * timer registry, as logging uses timer infra
+ */
+ if (gf_log_fini(ctx) != 0)
+ ret = -1;
+
+ /* Join the timer thread */
+ if (fs_init != 0) {
+ gf_timer_registry_destroy(ctx);
+ }
+
+ /* Destroy the context and the global pools */
+ if (glusterfs_ctx_destroy(ctx) != 0)
+ ret = -1;
+
+free_fs:
+ glfs_free_from_ctx(fs);
+
+ /*
+ * Do this as late as possible in case anything else has (or
+ * grows) a dependency on mem-pool allocations.
+ */
+ mem_pools_fini();
+
+fail:
+ if (!ret)
+ ret = err;
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_get_volfile, 3.6.0)
+ssize_t
+pub_glfs_get_volfile(struct glfs *fs, void *buf, size_t len)
+{
+ ssize_t res = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ glfs_lock(fs, _gf_true);
+ if (len >= fs->oldvollen) {
+ gf_msg_trace("glfs", 0, "copying %zu to %p", len, buf);
+ memcpy(buf, fs->oldvolfile, len);
+ res = len;
+ } else {
+ res = len - fs->oldvollen;
+ gf_msg_trace("glfs", 0, "buffer is %zd too short", -res);
+ }
+ glfs_unlock(fs);
+
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return res;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_ipc, 3.12.0)
+int
+priv_glfs_ipc(struct glfs *fs, int opcode, void *xd_in, void **xd_out)
+{
+ xlator_t *subvol = NULL;
+ int ret = -1;
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ subvol = glfs_active_subvol(fs);
+ if (!subvol) {
+ ret = -1;
+ errno = EIO;
+ goto out;
+ }
+
+ ret = syncop_ipc(subvol, opcode, (dict_t *)xd_in, (dict_t **)xd_out);
+ DECODE_SYNCOP_ERR(ret);
+
+out:
+ glfs_subvol_done(fs, subvol);
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PRIVATE_DEFAULT(glfs_setfspid, 6.1)
+int
+priv_glfs_setfspid(struct glfs *fs, pid_t pid)
+{
+ cmd_args_t *cmd_args = NULL;
+ int ret = 0;
+
+ cmd_args = &fs->ctx->cmd_args;
+ cmd_args->client_pid = pid;
+ cmd_args->client_pid_set = 1;
+ ret = syncopctx_setfspid(&pid);
+
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_free, 3.7.16)
+void
+pub_glfs_free(void *ptr)
+{
+ GLFS_FREE(ptr);
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_fs, 3.7.16)
+struct glfs *
+pub_glfs_upcall_get_fs(struct glfs_upcall *arg)
+{
+ return arg->fs;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_reason, 3.7.16)
+enum glfs_upcall_reason
+pub_glfs_upcall_get_reason(struct glfs_upcall *arg)
+{
+ return arg->reason;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_get_event, 3.7.16)
+void *
+pub_glfs_upcall_get_event(struct glfs_upcall *arg)
+{
+ return arg->event;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_object, 3.7.16)
+struct glfs_object *
+pub_glfs_upcall_inode_get_object(struct glfs_upcall_inode *arg)
+{
+ return arg->object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_flags, 3.7.16)
+uint64_t
+pub_glfs_upcall_inode_get_flags(struct glfs_upcall_inode *arg)
+{
+ return arg->flags;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_stat, 3.7.16)
+struct stat *
+pub_glfs_upcall_inode_get_stat(struct glfs_upcall_inode *arg)
+{
+ return &arg->buf;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_expire, 3.7.16)
+uint64_t
+pub_glfs_upcall_inode_get_expire(struct glfs_upcall_inode *arg)
+{
+ return arg->expire_time_attr;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pobject, 3.7.16)
+struct glfs_object *
+pub_glfs_upcall_inode_get_pobject(struct glfs_upcall_inode *arg)
+{
+ return arg->p_object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_pstat, 3.7.16)
+struct stat *
+pub_glfs_upcall_inode_get_pstat(struct glfs_upcall_inode *arg)
+{
+ return &arg->p_buf;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpobject, 3.7.16)
+struct glfs_object *
+pub_glfs_upcall_inode_get_oldpobject(struct glfs_upcall_inode *arg)
+{
+ return arg->oldp_object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16)
+struct stat *
+pub_glfs_upcall_inode_get_oldpstat(struct glfs_upcall_inode *arg)
+{
+ return &arg->oldp_buf;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_object, 4.1.6)
+struct glfs_object *
+pub_glfs_upcall_lease_get_object(struct glfs_upcall_lease *arg)
+{
+ return arg->object;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_lease_type, 4.1.6)
+uint32_t
+pub_glfs_upcall_lease_get_lease_type(struct glfs_upcall_lease *arg)
+{
+ return arg->lease_type;
+}
+
+/* definitions of the GLFS_SYSRQ_* chars are in glfs.h */
+static struct glfs_sysrq_help {
+ char sysrq;
+ char *msg;
+} glfs_sysrq_help[] = {{GLFS_SYSRQ_HELP, "(H)elp"},
+ {GLFS_SYSRQ_STATEDUMP, "(S)tatedump"},
+ {0, NULL}};
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_sysrq, 3.10.0)
+int
+pub_glfs_sysrq(struct glfs *fs, char sysrq)
+{
+ glusterfs_ctx_t *ctx = NULL;
+ int ret = 0;
+ int msg_len;
+ char msg[1024] = {
+ 0,
+ }; /* should not exceed 1024 chars */
+
+ if (!fs || !fs->ctx) {
+ ret = -1;
+ errno = EINVAL;
+ goto out;
+ }
+
+ ctx = fs->ctx;
+
+ switch (sysrq) {
+ case GLFS_SYSRQ_HELP: {
+ struct glfs_sysrq_help *usage = NULL;
+
+ for (usage = glfs_sysrq_help; usage->sysrq; usage++) {
+ msg_len = strlen(msg);
+ snprintf(msg + msg_len, /* append to msg */
+ sizeof(msg) - msg_len - 2,
+ /* - 2 for the " " + terminating \0 */
+ " %s", usage->msg);
+ }
+
+ /* not really an 'error', but make sure it gets logged */
+ gf_log("glfs", GF_LOG_ERROR, "available events: %s", msg);
+
+ break;
+ }
+ case GLFS_SYSRQ_STATEDUMP:
+ gf_proc_dump_info(SIGUSR1, ctx);
+ break;
+ default:
+ gf_smsg("glfs", GF_LOG_ERROR, ENOTSUP, API_MSG_INVALID_SYSRQ,
+ "sysrq=%c", sysrq, NULL);
+ errno = ENOTSUP;
+ ret = -1;
+ }
+out:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_register, 3.13.0)
+int
+pub_glfs_upcall_register(struct glfs *fs, uint32_t event_list,
+ glfs_upcall_cbk cbk, void *data)
+{
+ int ret = 0;
+
+ /* list of supported upcall events */
+ uint32_t up_events = (GLFS_EVENT_INODE_INVALIDATE |
+ GLFS_EVENT_RECALL_LEASE);
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ GF_VALIDATE_OR_GOTO(THIS->name, cbk, out);
+
+ /* Event list should be either GLFS_EVENT_ANY
+ * or list of supported individual events (up_events)
+ */
+ if ((event_list != GLFS_EVENT_ANY) && (event_list & ~up_events)) {
+ errno = EINVAL;
+ ret = -1;
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ARG,
+ "event_list=(0x%08x)", event_list, NULL);
+ goto out;
+ }
+
+ /* in case other thread does unregister */
+ pthread_mutex_lock(&fs->mutex);
+ {
+ if (event_list & GLFS_EVENT_INODE_INVALIDATE) {
+ /* @todo: Check if features.cache-invalidation is
+ * enabled.
+ */
+ fs->upcall_events |= GF_UPCALL_CACHE_INVALIDATION;
+ ret |= GLFS_EVENT_INODE_INVALIDATE;
+ }
+ if (event_list & GLFS_EVENT_RECALL_LEASE) {
+ /* @todo: Check if features.leases is enabled */
+ fs->upcall_events |= GF_UPCALL_RECALL_LEASE;
+ ret |= GLFS_EVENT_RECALL_LEASE;
+ }
+ /* Override cbk function if existing */
+ fs->up_cbk = cbk;
+ fs->up_data = data;
+ fs->cache_upcalls = _gf_true;
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+out:
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_unregister, 3.13.0)
+int
+pub_glfs_upcall_unregister(struct glfs *fs, uint32_t event_list)
+{
+ int ret = 0;
+ /* list of supported upcall events */
+ uint32_t up_events = (GLFS_EVENT_INODE_INVALIDATE |
+ GLFS_EVENT_RECALL_LEASE);
+
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ /* Event list should be either GLFS_EVENT_ANY
+ * or list of supported individual events (up_events)
+ */
+ if ((event_list != GLFS_EVENT_ANY) && (event_list & ~up_events)) {
+ errno = EINVAL;
+ ret = -1;
+ gf_smsg(THIS->name, GF_LOG_ERROR, errno, API_MSG_INVALID_ARG,
+ "event_list=(0x%08x)", event_list, NULL);
+ goto out;
+ }
+
+ pthread_mutex_lock(&fs->mutex);
+ {
+ /* We already checked if event_list contains list of supported
+ * upcall events. No other specific checks needed as of now for
+ * unregister */
+ fs->upcall_events &= ~(event_list);
+ ret |= ((event_list == GLFS_EVENT_ANY) ? up_events : event_list);
+
+ /* If there are no upcall events registered, reset cbk */
+ if (fs->upcall_events == 0) {
+ fs->up_cbk = NULL;
+ fs->up_data = NULL;
+ fs->cache_upcalls = _gf_false;
+ }
+ }
+ pthread_mutex_unlock(&fs->mutex);
+
+out:
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return ret;
+}
+
+GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_set_statedump_path, 7.0)
+int
+pub_glfs_set_statedump_path(struct glfs *fs, const char *path)
+{
+ struct stat st;
+ int ret;
+ DECLARE_OLD_THIS;
+ __GLFS_ENTRY_VALIDATE_FS(fs, invalid_fs);
+
+ if (!path) {
+ gf_log("glfs", GF_LOG_ERROR, "path is NULL");
+ errno = EINVAL;
+ goto err;
+ }
+
+ /* If path is not present OR, if it is directory AND has enough permission
+ * to create files, then proceed */
+ ret = sys_stat(path, &st);
+ if (ret && errno != ENOENT) {
+ gf_log("glfs", GF_LOG_ERROR, "%s: not a valid path (%s)", path,
+ strerror(errno));
+ errno = EINVAL;
+ goto err;
+ }
+
+ if (!ret) {
+ /* file is present, now check other things */
+ if (!S_ISDIR(st.st_mode)) {
+ gf_log("glfs", GF_LOG_ERROR, "%s: path is not directory", path);
+ errno = EINVAL;
+ goto err;
+ }
+ if (sys_access(path, W_OK | X_OK) < 0) {
+ gf_log("glfs", GF_LOG_ERROR,
+ "%s: path doesn't have write permission", path);
+ errno = EPERM;
+ goto err;
+ }
+ }
+
+ /* If set, it needs to be freed, so we don't have leak */
+ GF_FREE(fs->ctx->statedump_path);
+
+ fs->ctx->statedump_path = gf_strdup(path);
+ if (!fs->ctx->statedump_path) {
+ gf_log("glfs", GF_LOG_ERROR,
+ "%s: failed to set statedump path, no memory", path);
+ errno = ENOMEM;
+ goto err;
+ }
+
+ __GLFS_EXIT_FS;
+
+ return 0;
+err:
+ __GLFS_EXIT_FS;
+
+invalid_fs:
+ return -1;
+}
diff --git a/api/src/glfs.h b/api/src/glfs.h
new file mode 100644
index 00000000000..279d11d58ee
--- /dev/null
+++ b/api/src/glfs.h
@@ -0,0 +1,1485 @@
+/*
+ Copyright (c) 2012-2018 Red Hat, Inc. <http://www.redhat.com>
+ This file is part of GlusterFS.
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _GLFS_H
+#define _GLFS_H
+
+/*
+ Enforce the following flags as libgfapi is built
+ with them, and we want programs linking against them to also
+ be built with these flags. This is necessary as it affects
+ some of the structures defined in libc headers (like struct stat)
+ and those definitions need to be consistently compiled in
+ both the library and the application.
+*/
+
+/* Values for valid flags to be used when using XXXsetattr, to set multiple
+ attribute values passed via the related stat structure.
+ */
+
+#define GFAPI_SET_ATTR_MODE 0x1
+#define GFAPI_SET_ATTR_UID 0x2
+#define GFAPI_SET_ATTR_GID 0x4
+#define GFAPI_SET_ATTR_SIZE 0x8
+#define GFAPI_SET_ATTR_ATIME 0x10
+#define GFAPI_SET_ATTR_MTIME 0x20
+
+#ifndef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 64
+#endif
+
+#ifndef __USE_FILE_OFFSET64
+#define __USE_FILE_OFFSET64
+#endif
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <dirent.h>
+#include <sys/statvfs.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+/*
+ * For off64_t to be defined, we need both
+ * __USE_LARGEFILE64 to be true and __off64_t_defnined to be
+ * false. But, making __USE_LARGEFILE64 true causes other issues
+ * such as redinition of stat and fstat to stat64 and fstat64
+ * respectively which again causes compilation issues.
+ * Without off64_t being defined, this will not compile as
+ * copy_file_range uses off64_t. Hence define it here. First
+ * check whether __off64_t_defined is true or not. <unistd.h>
+ * sets that flag when it defines off64_t. If __off64_t_defined
+ * is false and __USE_FILE_OFFSET64 is true, then go on to define
+ * off64_t using __off64_t.
+ */
+#ifndef GF_BSD_HOST_OS
+#if defined(__USE_FILE_OFFSET64) && !defined(__off64_t_defined)
+typedef __off64_t off64_t;
+#endif /* defined(__USE_FILE_OFFSET64) && !defined(__off64_t_defined) */
+#else
+#include <stdio.h>
+#ifndef _OFF64_T_DECLARED
+/*
+ * Including <stdio.h> (done above) should actually define
+ * _OFF64_T_DECLARED with off64_t data type being available
+ * for consumption. But, off64_t data type is not recognizable
+ * for FreeBSD versions less than 11. Hence, int64_t is typedefed
+ * to off64_t.
+ */
+#define _OFF64_T_DECLARED
+typedef int64_t off64_t;
+#endif /* _OFF64_T_DECLARED */
+#endif /* GF_BSD_HOST_OS */
+
+#if defined(HAVE_SYS_ACL_H) || (defined(USE_POSIX_ACLS) && USE_POSIX_ACLS)
+#include <sys/acl.h>
+#else
+typedef void *acl_t;
+typedef int acl_type_t;
+#endif
+
+/* Portability non glibc c++ build systems */
+#ifndef __THROW
+#if defined __cplusplus
+#define __THROW throw()
+#else
+#define __THROW
+#endif
+#endif
+
+#ifndef GF_DARWIN_HOST_OS
+#define GFAPI_PUBLIC(sym, ver) /**/
+#define GFAPI_PRIVATE(sym, ver) /**/
+#else
+#define GFAPI_PUBLIC(sym, ver) __asm("_" __STRING(sym) "$GFAPI_" __STRING(ver))
+#define GFAPI_PRIVATE(sym, ver) \
+ __asm("_" __STRING(sym) "$GFAPI_PRIVATE_" __STRING(ver))
+#endif
+
+__BEGIN_DECLS
+
+/* The filesystem object. One object per 'virtual mount' */
+struct glfs;
+typedef struct glfs glfs_t;
+
+/*
+ SYNOPSIS
+
+ glfs_new: Create a new 'virtual mount' object.
+
+ DESCRIPTION
+
+ This is most likely the very first function you will use. This function
+ will create a new glfs_t (virtual mount) object in memory.
+
+ On this newly created glfs_t, you need to be either set a volfile path
+ (glfs_set_volfile) or a volfile server (glfs_set_volfile_server).
+
+ The glfs_t object needs to be initialized with glfs_init() before you
+ can start issuing file operations on it.
+
+ PARAMETERS
+
+ @volname: Name of the volume. This identifies the server-side volume and
+ the fetched volfile (equivalent of --volfile-id command line
+ parameter to glusterfsd). When used with glfs_set_volfile() the
+ @volname has no effect (except for appearing in log messages).
+
+ RETURN VALUES
+
+ NULL : Out of memory condition.
+ Others : Pointer to the newly created glfs_t virtual mount object.
+
+*/
+
+glfs_t *
+glfs_new(const char *volname) __THROW GFAPI_PUBLIC(glfs_new, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_set_volfile: Specify the path to the volume specification file.
+
+ DESCRIPTION
+
+ If you are using a static volume specification file (without dynamic
+ volume management abilities from the CLI), then specify the path to
+ the volume specification file.
+
+ This is incompatible with glfs_set_volfile_server().
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be configured with the volume
+ specification file.
+
+ @volfile: Path to the locally available volume specification file.
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Failure. @errno will be set with the type of failure.
+
+*/
+
+int
+glfs_set_volfile(glfs_t *fs, const char *volfile) __THROW
+ GFAPI_PUBLIC(glfs_set_volfile, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_set_volfile_server: Specify the list of addresses for management server.
+
+ DESCRIPTION
+
+ This function specifies the list of addresses for the management server
+ (glusterd) to connect, and establish the volume configuration. The @volname
+ parameter passed to glfs_new() is the volume which will be virtually
+ mounted as the glfs_t object. All operations performed by the CLI at
+ the management server will automatically be reflected in the 'virtual
+ mount' object as it maintains a connection to glusterd and polls on
+ configuration change notifications.
+
+ This is incompatible with glfs_set_volfile().
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be configured with the volume
+ specification file.
+
+ @transport: String specifying the transport used to connect to the
+ management daemon. Specifying NULL will result in the
+ usage of the default (tcp) transport type. Permitted
+ values are "tcp" or "unix".
+
+ @host: String specifying the address where to find the management daemon.
+ Socket path, while using Unix domain socket as transport type.
+ This would either be
+ - FQDN (e.g : "storage01.company.com") or
+ - ASCII (e.g : "192.168.22.1") or
+ - Socket path (e.g : "/var/run/glusterd.socket")
+
+ NOTE: This API is special, multiple calls to this function with different
+ volfile servers, port or transport-type would create a list of volfile
+ servers which would be polled during `volfile_fetch_attempts()`
+
+ @port: The TCP port number where gluster management daemon is listening.
+ Specifying 0 uses the default port number GF_DEFAULT_BASE_PORT.
+ This parameter is unused if you are using a UNIX domain socket.
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Failure. @errno will be set with the type of failure.
+
+*/
+
+int
+glfs_set_volfile_server(glfs_t *fs, const char *transport, const char *host,
+ int port) __THROW
+ GFAPI_PUBLIC(glfs_set_volfile_server, 3.4.0);
+
+int
+glfs_unset_volfile_server(glfs_t *fs, const char *transport, const char *host,
+ int port) __THROW
+ GFAPI_PUBLIC(glfs_unset_volfile_server, 3.5.1);
+/*
+ SYNOPSIS
+
+ glfs_set_logging: Specify logging parameters.
+
+ DESCRIPTION
+
+ This function specifies logging parameters for the virtual mount.
+ Default log file is /dev/null.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be configured with the logging parameters.
+
+ @logfile: The logfile to be used for logging. Will be created if it does not
+ already exist (provided system permissions allow). If NULL, a new
+ logfile will be created in default log directory associated with
+ the glusterfs installation.
+
+ @loglevel: Numerical value specifying the degree of verbosity. Higher the
+ value, more verbose the logging.
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Failure. @errno will be set with the type of failure.
+
+*/
+
+int
+glfs_set_logging(glfs_t *fs, const char *logfile, int loglevel) __THROW
+ GFAPI_PUBLIC(glfs_set_logging, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_init: Initialize the 'virtual mount'
+
+ DESCRIPTION
+
+ This function initializes the glfs_t object. This consists of many steps:
+ - Spawn a poll-loop thread.
+ - Establish connection to management daemon and receive volume specification.
+ - Construct translator graph and initialize graph.
+ - Wait for initialization (connecting to all bricks) to complete.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be initialized.
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Failure. @errno will be set with the type of failure.
+
+*/
+
+int
+glfs_init(glfs_t *fs) __THROW GFAPI_PUBLIC(glfs_init, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_fini: Cleanup and destroy the 'virtual mount'
+
+ DESCRIPTION
+
+ This function attempts to gracefully destroy glfs_t object. An attempt is
+ made to wait for all background processing to complete before returning.
+
+ glfs_fini() must be called after all operations on glfs_t is finished.
+
+ IMPORTANT
+
+ IT IS NECESSARY TO CALL glfs_fini() ON ALL THE INITIALIZED glfs_t
+ OBJECTS BEFORE TERMINATING THE PROGRAM. THERE MAY BE CACHED AND
+ UNWRITTEN / INCOMPLETE OPERATIONS STILL IN PROGRESS EVEN THOUGH THE
+ API CALLS HAVE RETURNED. glfs_fini() WILL WAIT FOR BACKGROUND OPERATIONS
+ TO COMPLETE BEFORE RETURNING, THEREBY MAKING IT SAFE FOR THE PROGRAM TO
+ EXIT.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be destroyed.
+
+ RETURN VALUES
+
+ 0 : Success.
+*/
+
+int
+glfs_fini(glfs_t *fs) __THROW GFAPI_PUBLIC(glfs_fini, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_getvol: Get the volfile associated with a 'virtual mount'
+
+ DESCRIPTION
+
+ Sometimes it's useful e.g. for scripts to see the volfile, so that they
+ can parse it and find subvolumes to do things like split-brain resolution
+ or custom layouts. The API here was specifically intended to make access
+ e.g. from Python as simple as possible.
+
+ Note that the volume must be started (not necessarily mounted) for this
+ to work.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object for which a volfile is desired
+ @buf: Pointer to a place for the volfile length to be stored
+ @len: Length of @buf
+
+ RETURN VALUES
+
+ >0: filled N bytes of buffer
+ 0: no volfile available
+ <0: volfile length exceeds @len by N bytes (@buf unchanged)
+*/
+
+ssize_t
+glfs_get_volfile(glfs_t *fs, void *buf, size_t len) __THROW
+ GFAPI_PUBLIC(glfs_get_volfile, 3.6.0);
+
+/*
+ SYNOPSIS
+
+ glfs_get_volumeid: Copy the Volume UUID stored in the glfs object fs.
+
+ DESCRIPTION
+
+ This function when invoked for the first time sends RPC call to the
+ the management server (glusterd) to fetch volume uuid and stores it
+ in the glusterfs_context linked to the glfs object fs which can be used
+ in the subsequent calls. Later it parses that UUID to convert it from
+ canonical string format into an opaque byte array and copy it into
+ the volid array. In case if either of the input parameters, volid or
+ size, is NULL, number of bytes required to copy the volume UUID is returned.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be used to retrieve and store
+ volume's UUID.
+ @volid: Pointer to a place for the volume UUID to be stored
+ @size: Length of @volid
+
+ RETURN VALUES
+
+ -1 : Failure. @errno will be set with the type of failure.
+ Others : length of the volume UUID stored.
+*/
+
+int
+glfs_get_volumeid(glfs_t *fs, char *volid, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_get_volumeid, 3.5.0);
+
+/*
+ * FILE OPERATION
+ *
+ * What follows are filesystem operations performed on the
+ * 'virtual mount'. The calls here are kept as close to
+ * the POSIX system calls as possible.
+ *
+ * Notes:
+ *
+ * - All paths specified, even if absolute, are relative to the
+ * root of the virtual mount and not the system root (/).
+ *
+ */
+
+/* The file descriptor object. One per open file/directory. */
+
+struct glfs_fd;
+typedef struct glfs_fd glfs_fd_t;
+
+/*
+ * Mask for request/result items in the struct glfs_stat.
+ *
+ * Query request/result mask for glfs_stat() (family of functions) and
+ * struct glfs_stat::glfs_st_mask.
+ *
+ * These bits should be set in the mask argument of glfs_stat() (family of
+ * functions) to request particular items when calling glfs_stat().
+ *
+ * NOTE: Lower order 32 bits are used to reflect statx(2) bits. For Gluster
+ * specific attrs/extensions, use higher order 32 bits.
+ *
+ */
+#define GLFS_STAT_TYPE 0x0000000000000001U /* Want/got stx_mode & S_IFMT */
+#define GLFS_STAT_MODE 0x0000000000000002U /* Want/got stx_mode & ~S_IFMT */
+#define GLFS_STAT_NLINK 0x0000000000000004U /* Want/got stx_nlink */
+#define GLFS_STAT_UID 0x0000000000000008U /* Want/got stx_uid */
+#define GLFS_STAT_GID 0x0000000000000010U /* Want/got stx_gid */
+#define GLFS_STAT_ATIME 0x0000000000000020U /* Want/got stx_atime */
+#define GLFS_STAT_MTIME 0x0000000000000040U /* Want/got stx_mtime */
+#define GLFS_STAT_CTIME 0x0000000000000080U /* Want/got stx_ctime */
+#define GLFS_STAT_INO 0x0000000000000100U /* Want/got stx_ino */
+#define GLFS_STAT_SIZE 0x0000000000000200U /* Want/got stx_size */
+#define GLFS_STAT_BLOCKS 0x0000000000000400U /* Want/got stx_blocks */
+#define GLFS_STAT_BASIC_STATS \
+ 0x00000000000007ffU /* Items in the normal stat struct */
+#define GLFS_STAT_BTIME 0x0000000000000800U /* Want/got stx_btime */
+#define GLFS_STAT_ALL 0x0000000000000fffU /* All currently supported flags */
+#define GLFS_STAT_RESERVED \
+ 0x8000000000000000U /* Reserved to denote future expansion */
+
+/* Macros for checking validity of struct glfs_stat members.*/
+#define GLFS_STAT_TYPE_VALID(stmask) (stmask & GLFS_STAT_TYPE)
+#define GLFS_STAT_MODE_VALID(stmask) (stmask & GLFS_STAT_MODE)
+#define GLFS_STAT_NLINK_VALID(stmask) (stmask & GLFS_STAT_NLINK)
+#define GLFS_STAT_UID_VALID(stmask) (stmask & GLFS_STAT_UID)
+#define GLFS_STAT_GID_VALID(stmask) (stmask & GLFS_STAT_GID)
+#define GLFS_STAT_ATIME_VALID(stmask) (stmask & GLFS_STAT_ATIME)
+#define GLFS_STAT_MTIME_VALID(stmask) (stmask & GLFS_STAT_MTIME)
+#define GLFS_STAT_CTIME_VALID(stmask) (stmask & GLFS_STAT_CTIME)
+#define GLFS_STAT_INO_VALID(stmask) (stmask & GLFS_STAT_INO)
+#define GLFS_STAT_SIZE_VALID(stmask) (stmask & GLFS_STAT_SIZE)
+#define GLFS_STAT_BLOCKS_VALID(stmask) (stmask & GLFS_STAT_BLOCKS)
+#define GLFS_STAT_BTIME_VALID(stmask) (stmask & GLFS_STAT_BTIME)
+#define GLFS_STAT_GFID_VALID(stmask) (stmask & GLFS_STAT_GFID)
+
+/*
+ * Attributes to be found in glfs_st_attributes and masked in
+ * glfs_st_attributes_mask.
+ *
+ * These give information about the features or the state of a file that might
+ * be of use to programs.
+ *
+ * NOTE: Lower order 32 bits are used to reflect statx(2) attribute bits. For
+ * Gluster specific attrs, use higher order 32 bits.
+ *
+ * NOTE: We do not support any file attributes or state as yet!
+ */
+#define GLFS_STAT_ATTR_RESERVED \
+ 0x8000000000000000U /* Reserved to denote future expansion */
+
+/* Extended file attribute structure.
+ *
+ * The caller passes a mask of what they're specifically interested in as a
+ * parameter to glfs_stat(). What glfs_stat() actually got will be indicated
+ * in glfs_st_mask upon return.
+ *
+ * For each bit in the mask argument:
+ *
+ * - if the datum is not supported:
+ *
+ * - the bit will be cleared, and
+ *
+ * - the datum value is undefined
+ *
+ * - otherwise, if explicitly requested:
+ *
+ * - the field will be filled in and the bit will be set;
+ *
+ * - otherwise, if not requested, but available in, it will be filled in
+ * anyway, and the bit will be set upon return;
+ *
+ * - otherwise the field and the bit will be cleared before returning.
+ *
+ */
+
+struct glfs_stat {
+ uint64_t glfs_st_mask; /* What results were written [uncond] */
+ uint64_t glfs_st_attributes; /* Flags conveying information about the file
+ [uncond] */
+ uint64_t glfs_st_attributes_mask; /* Mask to show what's supported in
+ st_attributes [ucond] */
+ struct timespec glfs_st_atime; /* Last access time */
+ struct timespec glfs_st_btime; /* File creation time */
+ struct timespec glfs_st_ctime; /* Last attribute change time */
+ struct timespec glfs_st_mtime; /* Last data modification time */
+ ino_t glfs_st_ino; /* Inode number */
+ off_t glfs_st_size; /* File size */
+ blkcnt_t glfs_st_blocks; /* Number of 512-byte blocks allocated */
+ uint32_t glfs_st_rdev_major; /* Device ID of special file [if bdev/cdev] */
+ uint32_t glfs_st_rdev_minor;
+ uint32_t glfs_st_dev_major; /* ID of device containing file [uncond] */
+ uint32_t glfs_st_dev_minor;
+ blksize_t glfs_st_blksize; /* Preferred general I/O size [uncond] */
+ nlink_t glfs_st_nlink; /* Number of hard links */
+ uid_t glfs_st_uid; /* User ID of owner */
+ gid_t glfs_st_gid; /* Group ID of owner */
+ mode_t glfs_st_mode; /* File mode */
+};
+
+#define GLFS_LEASE_ID_SIZE 16 /* 128bits */
+typedef char glfs_leaseid_t[GLFS_LEASE_ID_SIZE];
+
+/*
+ * PER THREAD IDENTITY MODIFIERS
+ *
+ * The following operations enable to set a per thread identity context
+ * for the glfs APIs to perform operations as. The calls here are kept as close
+ * to POSIX equivalents as possible.
+ *
+ * NOTES:
+ *
+ * - setgroups is a per thread setting, hence this is named as fsgroups to be
+ * close in naming to the fs(u/g)id APIs
+ * - Typical mode of operation is to set the IDs as required, with the
+ * supplementary groups being optionally set, make the glfs call and post the
+ * glfs operation set them back to eu/gid or uid/gid as appropriate to the
+ * caller
+ * - The groups once set, need to be unset by setting the size to 0 (in which
+ * case the list argument is a do not care)
+ * - In case of leases feature enables, setfsleaseid is used to set and reset
+ * leaseid before and after every I/O operation.
+ * - Once a process for a thread of operation choses to set the IDs, all glfs
+ * calls made from that thread would default to the IDs set for the thread.
+ * As a result use these APIs with care and ensure that the set IDs are
+ * reverted to global process defaults as required.
+ *
+ */
+int
+glfs_setfsuid(uid_t fsuid) __THROW GFAPI_PUBLIC(glfs_setfsuid, 3.4.2);
+
+int
+glfs_setfsgid(gid_t fsgid) __THROW GFAPI_PUBLIC(glfs_setfsgid, 3.4.2);
+
+int
+glfs_setfsgroups(size_t size, const gid_t *list) __THROW
+ GFAPI_PUBLIC(glfs_setfsgroups, 3.4.2);
+
+int
+glfs_setfsleaseid(glfs_leaseid_t leaseid) __THROW
+ GFAPI_PUBLIC(glfs_setfsleaseid, 4.0.0);
+
+/*
+ SYNOPSIS
+
+ glfs_open: Open a file.
+
+ DESCRIPTION
+
+ This function opens a file on a virtual mount.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be initialized.
+
+ @path: Path of the file within the virtual mount.
+
+ @flags: Open flags. See open(2). O_CREAT is not supported.
+ Use glfs_creat() for creating files.
+
+ RETURN VALUES
+
+ NULL : Failure. @errno will be set with the type of failure.
+ Others : Pointer to the opened glfs_fd_t.
+
+ */
+
+glfs_fd_t *
+glfs_open(glfs_t *fs, const char *path, int flags) __THROW
+ GFAPI_PUBLIC(glfs_open, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_creat: Create a file.
+
+ DESCRIPTION
+
+ This function opens a file on a virtual mount.
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be initialized.
+
+ @path: Path of the file within the virtual mount.
+
+ @mode: Permission of the file to be created.
+
+ @flags: Create flags. See open(2). O_EXCL is supported.
+
+ RETURN VALUES
+
+ NULL : Failure. @errno will be set with the type of failure.
+ Others : Pointer to the opened glfs_fd_t.
+
+ */
+
+glfs_fd_t *
+glfs_creat(glfs_t *fs, const char *path, int flags, mode_t mode) __THROW
+ GFAPI_PUBLIC(glfs_creat, 3.4.0);
+
+int
+glfs_close(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_close, 3.4.0);
+
+glfs_t *
+glfs_from_glfd(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_from_glfd, 3.4.0);
+
+int
+glfs_set_xlator_option(glfs_t *fs, const char *xlator, const char *key,
+ const char *value) __THROW
+ GFAPI_PUBLIC(glfs_set_xlator_option, 3.4.0);
+
+/*
+
+ glfs_io_cbk
+
+ The following is the function type definition of the callback
+ function pointer which has to be provided by the caller to the
+ *_async() versions of the IO calls.
+
+ The callback function is called on completion of the requested
+ IO, and the appropriate return value is returned in @ret.
+
+ In case of an error in completing the IO, @ret will be -1 and
+ @errno will be set with the appropriate error.
+
+ @ret will be same as the return value of the non _async() variant
+ of the particular call
+
+ @data is the same context pointer provided by the caller at the
+ time of issuing the async IO call. This can be used by the
+ caller to differentiate different instances of the async requests
+ in a common callback function.
+
+ @prestat and @poststat are allocated on the stack, that are auto destroyed
+ post the callback function returns.
+*/
+
+typedef void (*glfs_io_cbk)(glfs_fd_t *fd, ssize_t ret,
+ struct glfs_stat *prestat,
+ struct glfs_stat *poststat, void *data);
+
+// glfs_{read,write}[_async]
+
+ssize_t
+glfs_read(glfs_fd_t *fd, void *buf, size_t count, int flags) __THROW
+ GFAPI_PUBLIC(glfs_read, 3.4.0);
+
+ssize_t
+glfs_write(glfs_fd_t *fd, const void *buf, size_t count, int flags) __THROW
+ GFAPI_PUBLIC(glfs_write, 3.4.0);
+
+int
+glfs_read_async(glfs_fd_t *fd, void *buf, size_t count, int flags,
+ glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_read_async, 6.0);
+
+int
+glfs_write_async(glfs_fd_t *fd, const void *buf, size_t count, int flags,
+ glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_write_async, 6.0);
+
+// glfs_{read,write}v[_async]
+
+ssize_t
+glfs_readv(glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
+ int flags) __THROW GFAPI_PUBLIC(glfs_readv, 3.4.0);
+
+ssize_t
+glfs_writev(glfs_fd_t *fd, const struct iovec *iov, int iovcnt,
+ int flags) __THROW GFAPI_PUBLIC(glfs_writev, 3.4.0);
+
+int
+glfs_readv_async(glfs_fd_t *fd, const struct iovec *iov, int count, int flags,
+ glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_readv_async, 6.0);
+
+int
+glfs_writev_async(glfs_fd_t *fd, const struct iovec *iov, int count, int flags,
+ glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_writev_async, 6.0);
+
+// glfs_p{read,write}[_async]
+
+ssize_t
+glfs_pread(glfs_fd_t *fd, void *buf, size_t count, off_t offset, int flags,
+ struct glfs_stat *poststat) __THROW GFAPI_PUBLIC(glfs_pread, 6.0);
+
+ssize_t
+glfs_pwrite(glfs_fd_t *fd, const void *buf, size_t count, off_t offset,
+ int flags, struct glfs_stat *prestat,
+ struct glfs_stat *poststat) __THROW GFAPI_PUBLIC(glfs_pwrite, 6.0);
+
+int
+glfs_pread_async(glfs_fd_t *fd, void *buf, size_t count, off_t offset,
+ int flags, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_pread_async, 6.0);
+
+int
+glfs_pwrite_async(glfs_fd_t *fd, const void *buf, int count, off_t offset,
+ int flags, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_pwrite_async, 6.0);
+
+// glfs_p{read,write}v[_async]
+
+ssize_t
+glfs_preadv(glfs_fd_t *fd, const struct iovec *iov, int iovcnt, off_t offset,
+ int flags) __THROW GFAPI_PUBLIC(glfs_preadv, 3.4.0);
+
+ssize_t
+glfs_pwritev(glfs_fd_t *fd, const struct iovec *iov, int iovcnt, off_t offset,
+ int flags) __THROW GFAPI_PUBLIC(glfs_pwritev, 3.4.0);
+
+int
+glfs_preadv_async(glfs_fd_t *fd, const struct iovec *iov, int count,
+ off_t offset, int flags, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_preadv_async, 6.0);
+
+int
+glfs_pwritev_async(glfs_fd_t *fd, const struct iovec *iov, int count,
+ off_t offset, int flags, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_pwritev_async, 6.0);
+
+off_t
+glfs_lseek(glfs_fd_t *fd, off_t offset, int whence) __THROW
+ GFAPI_PUBLIC(glfs_lseek, 3.4.0);
+
+ssize_t
+glfs_copy_file_range(struct glfs_fd *glfd_in, off64_t *off_in,
+ struct glfs_fd *glfd_out, off64_t *off_out, size_t len,
+ unsigned int flags, struct glfs_stat *statbuf,
+ struct glfs_stat *prestat,
+ struct glfs_stat *poststat) __THROW
+ GFAPI_PUBLIC(glfs_copy_file_range, 6.0);
+
+int
+glfs_truncate(glfs_t *fs, const char *path, off_t length) __THROW
+ GFAPI_PUBLIC(glfs_truncate, 3.7.15);
+
+int
+glfs_ftruncate(glfs_fd_t *fd, off_t length, struct glfs_stat *prestat,
+ struct glfs_stat *poststat) __THROW
+ GFAPI_PUBLIC(glfs_ftruncate, 6.0);
+
+int
+glfs_ftruncate_async(glfs_fd_t *fd, off_t length, glfs_io_cbk fn,
+ void *data) __THROW
+ GFAPI_PUBLIC(glfs_ftruncate_async, 6.0);
+
+int
+glfs_lstat(glfs_t *fs, const char *path, struct stat *buf) __THROW
+ GFAPI_PUBLIC(glfs_lstat, 3.4.0);
+
+int
+glfs_stat(glfs_t *fs, const char *path, struct stat *buf) __THROW
+ GFAPI_PUBLIC(glfs_stat, 3.4.0);
+
+int
+glfs_fstat(glfs_fd_t *fd, struct stat *buf) __THROW
+ GFAPI_PUBLIC(glfs_fstat, 3.4.0);
+
+int
+glfs_fsync(glfs_fd_t *fd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat) __THROW GFAPI_PUBLIC(glfs_fsync, 6.0);
+
+int
+glfs_fsync_async(glfs_fd_t *fd, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_fsync_async, 6.0);
+
+int
+glfs_fdatasync(glfs_fd_t *fd, struct glfs_stat *prestat,
+ struct glfs_stat *poststat) __THROW
+ GFAPI_PUBLIC(glfs_fdatasync, 6.0);
+
+int
+glfs_fdatasync_async(glfs_fd_t *fd, glfs_io_cbk fn, void *data) __THROW
+ GFAPI_PUBLIC(glfs_fdatasync_async, 6.0);
+
+int
+glfs_access(glfs_t *fs, const char *path, int mode) __THROW
+ GFAPI_PUBLIC(glfs_access, 3.4.0);
+
+int
+glfs_symlink(glfs_t *fs, const char *oldpath, const char *newpath) __THROW
+ GFAPI_PUBLIC(glfs_symlink, 3.4.0);
+
+int
+glfs_readlink(glfs_t *fs, const char *path, char *buf, size_t bufsiz) __THROW
+ GFAPI_PUBLIC(glfs_readlink, 3.4.0);
+
+int
+glfs_mknod(glfs_t *fs, const char *path, mode_t mode, dev_t dev) __THROW
+ GFAPI_PUBLIC(glfs_mknod, 3.4.0);
+
+int
+glfs_mkdir(glfs_t *fs, const char *path, mode_t mode) __THROW
+ GFAPI_PUBLIC(glfs_mkdir, 3.4.0);
+
+int
+glfs_unlink(glfs_t *fs, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_unlink, 3.4.0);
+
+int
+glfs_rmdir(glfs_t *fs, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_rmdir, 3.4.0);
+
+int
+glfs_rename(glfs_t *fs, const char *oldpath, const char *newpath) __THROW
+ GFAPI_PUBLIC(glfs_rename, 3.4.0);
+
+int
+glfs_link(glfs_t *fs, const char *oldpath, const char *newpath) __THROW
+ GFAPI_PUBLIC(glfs_link, 3.4.0);
+
+glfs_fd_t *
+glfs_opendir(glfs_t *fs, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_opendir, 3.4.0);
+
+/*
+ * @glfs_readdir_r and @glfs_readdirplus_r ARE thread safe AND re-entrant,
+ * but the interface has ambiguity about the size of @dirent to be allocated
+ * before calling the APIs. 512 byte buffer (for @dirent) is sufficient for
+ * all known systems which are tested againt glusterfs/gfapi, but may be
+ * insufficient in the future.
+ */
+
+int
+glfs_readdir_r(glfs_fd_t *fd, struct dirent *dirent,
+ struct dirent **result) __THROW
+ GFAPI_PUBLIC(glfs_readdir_r, 3.4.0);
+
+int
+glfs_readdirplus_r(glfs_fd_t *fd, struct stat *stat, struct dirent *dirent,
+ struct dirent **result) __THROW
+ GFAPI_PUBLIC(glfs_readdirplus_r, 3.4.0);
+
+/*
+ * @glfs_readdir and @glfs_readdirplus are NEITHER thread safe NOR re-entrant
+ * when called on the same directory handle. However they ARE thread safe
+ * AND re-entrant when called on different directory handles (which may be
+ * referring to the same directory too.)
+ */
+
+struct dirent *
+glfs_readdir(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_readdir, 3.5.0);
+
+struct dirent *
+glfs_readdirplus(glfs_fd_t *fd, struct stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_readdirplus, 3.5.0);
+
+long
+glfs_telldir(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_telldir, 3.4.0);
+
+void
+glfs_seekdir(glfs_fd_t *fd, long offset) __THROW
+ GFAPI_PUBLIC(glfs_seekdir, 3.4.0);
+
+int
+glfs_closedir(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_closedir, 3.4.0);
+
+int
+glfs_statvfs(glfs_t *fs, const char *path, struct statvfs *buf) __THROW
+ GFAPI_PUBLIC(glfs_statvfs, 3.4.0);
+
+int
+glfs_chmod(glfs_t *fs, const char *path, mode_t mode) __THROW
+ GFAPI_PUBLIC(glfs_chmod, 3.4.0);
+
+int
+glfs_fchmod(glfs_fd_t *fd, mode_t mode) __THROW
+ GFAPI_PUBLIC(glfs_fchmod, 3.4.0);
+
+int
+glfs_chown(glfs_t *fs, const char *path, uid_t uid, gid_t gid) __THROW
+ GFAPI_PUBLIC(glfs_chown, 3.4.0);
+
+int
+glfs_lchown(glfs_t *fs, const char *path, uid_t uid, gid_t gid) __THROW
+ GFAPI_PUBLIC(glfs_lchown, 3.4.0);
+
+int
+glfs_fchown(glfs_fd_t *fd, uid_t uid, gid_t gid) __THROW
+ GFAPI_PUBLIC(glfs_fchown, 3.4.0);
+
+int
+glfs_utimens(glfs_t *fs, const char *path,
+ const struct timespec times[2]) __THROW
+ GFAPI_PUBLIC(glfs_utimens, 3.4.0);
+
+int
+glfs_lutimens(glfs_t *fs, const char *path,
+ const struct timespec times[2]) __THROW
+ GFAPI_PUBLIC(glfs_lutimens, 3.4.0);
+
+int
+glfs_futimens(glfs_fd_t *fd, const struct timespec times[2]) __THROW
+ GFAPI_PUBLIC(glfs_futimens, 3.4.0);
+
+ssize_t
+glfs_getxattr(glfs_t *fs, const char *path, const char *name, void *value,
+ size_t size) __THROW GFAPI_PUBLIC(glfs_getxattr, 3.4.0);
+
+ssize_t
+glfs_lgetxattr(glfs_t *fs, const char *path, const char *name, void *value,
+ size_t size) __THROW GFAPI_PUBLIC(glfs_lgetxattr, 3.4.0);
+
+ssize_t
+glfs_fgetxattr(glfs_fd_t *fd, const char *name, void *value,
+ size_t size) __THROW GFAPI_PUBLIC(glfs_fgetxattr, 3.4.0);
+
+ssize_t
+glfs_listxattr(glfs_t *fs, const char *path, void *value, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_listxattr, 3.4.0);
+
+ssize_t
+glfs_llistxattr(glfs_t *fs, const char *path, void *value, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_llistxattr, 3.4.0);
+
+ssize_t
+glfs_flistxattr(glfs_fd_t *fd, void *value, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_flistxattr, 3.4.0);
+
+int
+glfs_setxattr(glfs_t *fs, const char *path, const char *name, const void *value,
+ size_t size, int flags) __THROW
+ GFAPI_PUBLIC(glfs_setxattr, 3.4.0);
+
+int
+glfs_lsetxattr(glfs_t *fs, const char *path, const char *name,
+ const void *value, size_t size, int flags) __THROW
+ GFAPI_PUBLIC(glfs_lsetxattr, 3.4.0);
+
+int
+glfs_fsetxattr(glfs_fd_t *fd, const char *name, const void *value, size_t size,
+ int flags) __THROW GFAPI_PUBLIC(glfs_fsetxattr, 3.4.0);
+
+int
+glfs_removexattr(glfs_t *fs, const char *path, const char *name) __THROW
+ GFAPI_PUBLIC(glfs_removexattr, 3.4.0);
+
+int
+glfs_lremovexattr(glfs_t *fs, const char *path, const char *name) __THROW
+ GFAPI_PUBLIC(glfs_lremovexattr, 3.4.0);
+
+int
+glfs_fremovexattr(glfs_fd_t *fd, const char *name) __THROW
+ GFAPI_PUBLIC(glfs_fremovexattr, 3.4.0);
+
+int
+glfs_fallocate(glfs_fd_t *fd, int keep_size, off_t offset, size_t len) __THROW
+ GFAPI_PUBLIC(glfs_fallocate, 3.5.0);
+
+int
+glfs_discard(glfs_fd_t *fd, off_t offset, size_t len) __THROW
+ GFAPI_PUBLIC(glfs_discard, 3.5.0);
+
+int
+glfs_discard_async(glfs_fd_t *fd, off_t length, size_t lent, glfs_io_cbk fn,
+ void *data) __THROW GFAPI_PUBLIC(glfs_discard_async, 6.0);
+
+int
+glfs_zerofill(glfs_fd_t *fd, off_t offset, off_t len) __THROW
+ GFAPI_PUBLIC(glfs_zerofill, 3.5.0);
+
+int
+glfs_zerofill_async(glfs_fd_t *fd, off_t length, off_t len, glfs_io_cbk fn,
+ void *data) __THROW GFAPI_PUBLIC(glfs_zerofill_async, 6.0);
+
+char *
+glfs_getcwd(glfs_t *fs, char *buf, size_t size) __THROW
+ GFAPI_PUBLIC(glfs_getcwd, 3.4.0);
+
+int
+glfs_chdir(glfs_t *fs, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_chdir, 3.4.0);
+
+int
+glfs_fchdir(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_fchdir, 3.4.0);
+
+char *
+glfs_realpath(glfs_t *fs, const char *path, char *resolved_path) __THROW
+ GFAPI_PUBLIC(glfs_realpath, 3.7.17);
+
+/*
+ * @cmd and @flock are as specified in man fcntl(2).
+ */
+int
+glfs_posix_lock(glfs_fd_t *fd, int cmd, struct flock *flock) __THROW
+ GFAPI_PUBLIC(glfs_posix_lock, 3.4.0);
+
+/*
+ SYNOPSIS
+
+ glfs_file_lock: Request extended byte range lock on a file
+
+ DESCRIPTION
+
+ This function is capable of requesting either advisory or mandatory type
+ byte range locks on a file.
+
+ Note: To set a unique owner key for locks based on a particular file
+ descriptor, make use of glfs_fd_set_lkowner() api to do so before
+ requesting lock via this api. This owner key will be further consumed
+ by other incoming data modifying file operations via the same file
+ descriptor.
+
+ PARAMETERS
+
+ @fd: File descriptor
+
+ @cmd: As specified in man fcntl(2).
+
+ @flock: As specified in man fcntl(2).
+
+ @lk_mode: Required lock type from options available with the
+ enum glfs_lock_mode_t defined below.
+
+ RETURN VALUES
+
+ 0 : Success. Lock has been granted.
+ -1 : Failure. @errno will be set indicating the type of failure.
+
+ */
+
+/* Lock modes used by glfs_file_lock() */
+enum glfs_lock_mode { GLFS_LK_ADVISORY = 0, GLFS_LK_MANDATORY };
+typedef enum glfs_lock_mode glfs_lock_mode_t;
+
+int
+glfs_file_lock(glfs_fd_t *fd, int cmd, struct flock *flock,
+ glfs_lock_mode_t lk_mode) __THROW
+ GFAPI_PUBLIC(glfs_file_lock, 3.13.0);
+
+glfs_fd_t *
+glfs_dup(glfs_fd_t *fd) __THROW GFAPI_PUBLIC(glfs_dup, 3.4.0);
+
+void
+glfs_free(void *ptr) __THROW GFAPI_PUBLIC(glfs_free, 3.7.16);
+
+/*
+ * glfs_sysrq: send a system request to the @fs instance
+ *
+ * Different commands for @sysrq are possible, the defines for these are listed
+ * below the function definition.
+ *
+ * This function always returns success if the @sysrq is recognized. The return
+ * value does not way anythin about the result of the @sysrq execution. Not all
+ * @sysrq command will be able to return a success/failure status.
+ */
+int
+glfs_sysrq(glfs_t *fs, char sysrq) __THROW GFAPI_PUBLIC(glfs_sysrq, 3.10.0);
+
+#define GLFS_SYSRQ_HELP 'h' /* log a message with supported sysrq commands */
+#define GLFS_SYSRQ_STATEDUMP 's' /* create a statedump */
+
+/*
+ * Structure returned as part of xreaddirplus
+ */
+struct glfs_xreaddirp_stat;
+typedef struct glfs_xreaddirp_stat glfs_xreaddirp_stat_t;
+
+/* Request flags to be used in XREADDIRP operation */
+#define GFAPI_XREADDIRP_NULL \
+ 0x00000000 /* by default, no stat will be fetched */
+#define GFAPI_XREADDIRP_STAT 0x00000001 /* Get stat */
+#define GFAPI_XREADDIRP_HANDLE 0x00000002 /* Get object handle */
+
+/*
+ * This stat structure returned gets freed as part of glfs_free(xstat)
+ */
+struct stat *
+glfs_xreaddirplus_get_stat(glfs_xreaddirp_stat_t *xstat) __THROW
+ GFAPI_PUBLIC(glfs_xreaddirplus_get_stat, 3.11.0);
+
+/*
+ * SYNOPSIS
+ *
+ * glfs_xreaddirplus_r: Extended Readirplus operation
+ *
+ * DESCRIPTION
+ *
+ * This API does readdirplus operation, but along with stat it can fetch other
+ * extra information like object handles etc for each of the dirents returned
+ * based on requested flags. On success it returns the set of flags successfully
+ * processed.
+ *
+ * Note that there are chances that some of the requested information may not be
+ * available or returned (for example if reached EOD). Ensure to validate the
+ * returned value to determine what flags have been successfully processed
+ * & set.
+ *
+ * PARAMETERS
+ *
+ * INPUT:
+ * @glfd: GFAPI file descriptor of the directory
+ * @flags: Flags determining xreaddirp_stat requested
+ * Current available values are:
+ * GFAPI_XREADDIRP_NULL
+ * GFAPI_XREADDIRP_STAT
+ * GFAPI_XREADDIRP_HANDLE
+ * @ext: Dirent struture to copy the values to
+ * (though optional recommended to be allocated by application
+ * esp., in multi-threaded environment)
+ *
+ * OUTPUT:
+ * @res: to store the next dirent value. If NULL and return value is '0',
+ * it means it reached end of the directory.
+ * @xstat_p: Pointer to contain all the requested data returned
+ * for that dirent. Application should make use of glfs_free() API
+ * to free this pointer and the variables returned by
+ * glfs_xreaddirplus_get_*() APIs.
+ *
+ * RETURN VALUE:
+ * >=0: SUCCESS (value contains the flags successfully processed)
+ * -1: FAILURE
+ */
+int
+glfs_xreaddirplus_r(glfs_fd_t *glfd, uint32_t flags,
+ glfs_xreaddirp_stat_t **xstat_p, struct dirent *ext,
+ struct dirent **res) __THROW
+ GFAPI_PUBLIC(glfs_xreaddirplus_r, 3.11.0);
+
+#define GFAPI_MAX_LOCK_OWNER_LEN 255
+
+/*
+ *
+ * DESCRIPTION
+ *
+ * This API allows application to set lk_owner on a fd.
+ * A glfd can be associated with only single lk_owner. In case if there
+ * is need to set another lk_owner, applications can make use of
+ * 'glfs_dup' to get duplicate glfd and set new lk_owner on that second
+ * glfd.
+ *
+ * Also its not recommended to override or clear lk_owner value as the
+ * same shall be used to flush any outstanding locks while closing the fd.
+ *
+ * PARAMETERS
+ *
+ * INPUT:
+ * @glfd: GFAPI file descriptor
+ * @len: Size of lk_owner buffer. Max value can be GFAPI_MAX_LOCK_OWNER_LEN
+ * @data: lk_owner data buffer.
+ *
+ * OUTPUT:
+ * 0: SUCCESS
+ * -1: FAILURE
+ */
+int
+glfs_fd_set_lkowner(glfs_fd_t *glfd, void *data, int len) __THROW
+ GFAPI_PUBLIC(glfs_fd_set_lkowner, 3.10.7);
+
+/*
+ * Applications (currently NFS-Ganesha) can make use of this
+ * structure to read upcall notifications sent by server either
+ * by polling or registering a callback function.
+ *
+ * On success, applications need to check for 'reason' to decide
+ * if any upcall event is received.
+ *
+ * Currently supported upcall_events -
+ * GLFS_UPCALL_INODE_INVALIDATE -
+ * 'event_arg' - glfs_upcall_inode
+ *
+ * After processing the event, applications need to free 'event_arg' with
+ * glfs_free().
+ *
+ * Also similar to I/Os, the application should ideally stop polling
+ * or unregister upcall_cbk function before calling glfs_fini(..).
+ * Hence making an assumption that 'fs' & ctx structures cannot be
+ * freed while in this routine.
+ */
+struct glfs_upcall;
+typedef struct glfs_upcall glfs_upcall_t;
+
+glfs_t *
+glfs_upcall_get_fs(glfs_upcall_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_get_fs, 3.7.16);
+
+enum glfs_upcall_reason {
+ GLFS_UPCALL_EVENT_NULL = 0,
+ GLFS_UPCALL_INODE_INVALIDATE, /* invalidate cache entry */
+ GLFS_UPCALL_RECALL_LEASE, /* recall lease */
+};
+typedef enum glfs_upcall_reason glfs_upcall_reason_t;
+
+glfs_upcall_reason_t
+glfs_upcall_get_reason(glfs_upcall_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_get_reason, 3.7.16);
+
+/*
+ * Applications first need to make use of above API i.e,
+ * "glfs_upcall_get_reason" to determine which upcall event it has
+ * received. Post that below API - "glfs_upcall_get_event" should
+ * be used to get corresponding upcall event object.
+ *
+ * Below are the upcall_reason and corresponding upcall_event objects:
+ * ==========================================================
+ * glfs_upcall_reason - event_object
+ * ==========================================================
+ * GLFS_UPCALL_EVENT_NULL - NULL
+ * GLFS_UPCALL_INODE_INVALIDATE - struct glfs_upcall_inode
+ * GLFS_UPCALL_RECALL_LEASE - struct glfs_upcall_lease
+ *
+ * After processing upcall event, glfs_free() should be called on the
+ * glfs_upcall.
+ */
+void *
+glfs_upcall_get_event(glfs_upcall_t *arg) __THROW
+ GFAPI_PUBLIC(glfs_upcall_get_event, 3.7.16);
+
+/*
+ * SYNOPSIS
+ *
+ * glfs_upcall_cbk: Upcall callback definition
+ *
+ * This is function type definition of the callback function pointer
+ * which has to be provided by the caller while registering for any
+ * upcall events.
+ *
+ * This function is called whenever any upcall which the application
+ * has registered for is received from the server.
+ *
+ * @up_arg: Upcall structure whose contents need to be interpreted by
+ * making use of glfs_upcall_* helper routines.
+ *
+ * @data: The same context pointer provided by the caller at the time of
+ * registering of upcall events. This may be used by the caller for any
+ * of its internal use while processing upcalls.
+ */
+typedef void (*glfs_upcall_cbk)(glfs_upcall_t *up_arg, void *data);
+
+/*
+ * List of upcall events supported by gluster/gfapi
+ */
+#define GLFS_EVENT_INODE_INVALIDATE 0x00000001 /* invalidate cache entry */
+#define GLFS_EVENT_RECALL_LEASE 0x00000002 /* Recall lease */
+#define GLFS_EVENT_ANY 0xffffffff /* for all the above events */
+
+/*
+ * SYNOPSIS
+ *
+ * glfs_upcall_register: Register for upcall events
+ *
+ * DESCRIPTION
+ *
+ * This function is used to register for various upcall events application
+ * is interested in and the callback function to be invoked when such
+ * events are triggered.
+ *
+ * Multiple calls of this routine shall override cbk function. That means
+ * only one cbk function can be used for all the upcall events registered
+ * and that shall be the one last updated.
+ *
+ * PARAMETERS:
+ *
+ * INPUT:
+ * @fs: The 'virtual mount' object
+ *
+ * @event_list: List of upcall events to be registered.
+ * Current available values are:
+ * - GLFS_EVENT_INODE_INVALIDATE
+ * - GLFS_EVENT_RECALL_LEASE
+ *
+ * @cbk: The cbk routine to be invoked in case of any upcall received
+ * @data: Any opaque pointer provided by caller which shall be using while
+ * making cbk calls. This pointer may be used by caller for any of its
+ * internal use while processing upcalls. Can be NULL.
+ *
+ * RETURN VALUE:
+ * >0: SUCCESS (value contains the events successfully registered)
+ * -1: FAILURE
+ */
+int
+glfs_upcall_register(glfs_t *fs, uint32_t event_list, glfs_upcall_cbk cbk,
+ void *data) __THROW
+ GFAPI_PUBLIC(glfs_upcall_register, 3.13.0);
+
+/*
+ * SYNOPSIS
+ *
+ * glfs_upcall_unregister: Unregister for upcall events
+ *
+ * DESCRIPTION
+ *
+ * This function is used to unregister the upcall events application
+ * is not interested in. In case if the caller unregisters all the events
+ * it has registered for, it shall no more receive any upcall event.
+ *
+ * PARAMETERS:
+ *
+ * INPUT:
+ * @fs: The 'virtual mount' object
+ *
+ * @event_list: List of upcall events to be unregistered.
+ * Current available values are:
+ * - GLFS_EVENT_INODE_INVALIDATE
+ * - GLFS_EVENT_RECALL_LEASE
+ * RETURN VALUE:
+ * >0: SUCCESS (value contains the events successfully unregistered)
+ * -1: FAILURE
+ */
+int
+glfs_upcall_unregister(glfs_t *fs, uint32_t event_list) __THROW
+ GFAPI_PUBLIC(glfs_upcall_unregister, 3.13.0);
+
+/* Lease Types */
+enum glfs_lease_types {
+ GLFS_LEASE_NONE = 0,
+ GLFS_RD_LEASE = 1,
+ GLFS_RW_LEASE = 2,
+};
+typedef enum glfs_lease_types glfs_lease_types_t;
+
+/* Lease cmds */
+enum glfs_lease_cmds {
+ GLFS_GET_LEASE = 1,
+ GLFS_SET_LEASE = 2,
+ GLFS_UNLK_LEASE = 3,
+};
+typedef enum glfs_lease_cmds glfs_lease_cmds_t;
+
+struct glfs_lease {
+ glfs_lease_cmds_t cmd;
+ glfs_lease_types_t lease_type;
+ glfs_leaseid_t lease_id;
+ unsigned int lease_flags;
+};
+typedef struct glfs_lease glfs_lease_t;
+
+typedef void (*glfs_recall_cbk)(glfs_lease_t lease, void *data);
+
+/*
+ SYNOPSIS
+
+ glfs_lease: Takes a lease on a file.
+
+ DESCRIPTION
+
+ This function takes lease on an open file.
+
+ PARAMETERS
+
+ @glfd: The fd of the file on which lease should be taken,
+ this fd is returned by glfs_open/glfs_create.
+
+ @lease: Struct that defines the lease operation to be performed
+ on the file.
+ @lease.cmd - Can be one of the following values
+ GF_GET_LEASE: Get the lease type currently present on the file,
+ lease.lease_type will contain GF_RD_LEASE
+ or GF_RW_LEASE or 0 if no leases.
+ GF_SET_LEASE: Set the lease of given lease.lease_type on the file.
+ GF_UNLK_LEASE: Unlock the lease present on the given fd.
+ Note that the every lease request should have
+ a corresponding unlk_lease.
+
+ @lease.lease_type - Can be one of the following values
+ GF_RD_LEASE: Read lease on a file, shared lease.
+ GF_RW_LEASE: Read-Write lease on a file, exclusive lease.
+
+ @lease.lease_id - A unique identification of lease, 128bits.
+
+ @fn: This is the function that is invoked when the lease has to be recalled
+ @data: It is a cookie, this pointer is returned as a part of recall
+
+ fn and data field are stored as a part of glfs_fd, hence if there are multiple
+ glfs_lease calls, each of them updates the fn and data fields. glfs_recall_cbk
+ will be invoked with the last updated fn and data
+
+ RETURN VALUES
+ 0: Successful completion
+ <0: Failure. @errno will be set with the type of failure
+*/
+
+int
+glfs_lease(glfs_fd_t *glfd, glfs_lease_t *lease, glfs_recall_cbk fn,
+ void *data) __THROW GFAPI_PUBLIC(glfs_lease, 4.0.0);
+
+/*
+ SYNOPSIS
+
+ glfs_fsetattr: Function to set attributes.
+ glfs_setattr: Function to set attributes
+
+ DESCRIPTION
+
+ The functions are used to set attributes on the file.
+
+ PARAMETERS
+
+ @glfs_fsetattr
+
+ @glfd: The fd of the file for which the attributes are to be set,
+ this fd is returned by glfs_open/glfs_create.
+
+ @glfs_setattr
+
+ @fs: File object.
+
+ @path: The path of the file that is being operated on.
+
+ @follow: Flag used to resolve symlink.
+
+
+ @stat: Struct that has information about the file.
+
+ @valid: This is the mask bit, that accepts GFAPI_SET_ATTR* masks.
+ Refer glfs.h to see the mask definitions.
+
+ Both functions are similar in functionality, just that the
+ func setattr() uses file path whereas the func fsetattr()
+ uses the fd.
+
+ RETURN VALUES
+ 0: Successful completion
+ <0: Failure. @errno will be set with the type of failure
+
+ */
+
+int
+glfs_fsetattr(struct glfs_fd *glfd, struct glfs_stat *stat) __THROW
+ GFAPI_PUBLIC(glfs_fsetattr, 6.0);
+
+int
+glfs_setattr(struct glfs *fs, const char *path, struct glfs_stat *stat,
+ int follow) __THROW GFAPI_PUBLIC(glfs_setattr, 6.0);
+
+/*
+ SYNOPSIS
+
+ glfs_set_statedump_path: Function to set statedump path.
+
+ DESCRIPTION
+
+ This function is used to set statedump directory
+
+ PARAMETERS
+
+ @fs: The 'virtual mount' object to be configured with the volume
+ specification file.
+
+ @path: statedump path. Should be a directory. But the API won't fail if the
+ directory doesn't exist yet, as one may create it later.
+
+ RETURN VALUES
+
+ 0 : Success.
+ -1 : Failure. @errno will be set with the type of failure.
+
+ */
+
+int
+glfs_set_statedump_path(struct glfs *fs, const char *path) __THROW
+ GFAPI_PUBLIC(glfs_set_statedump_path, 7.0);
+
+__END_DECLS
+#endif /* !_GLFS_H */
diff --git a/argp-standalone/Makefile.am b/argp-standalone/Makefile.am
deleted file mode 100644
index 4775d4876aa..00000000000
--- a/argp-standalone/Makefile.am
+++ /dev/null
@@ -1,38 +0,0 @@
-# From glibc
-
-# Copyright (C) 1997, 2003, 2004 Free Software Foundation, Inc.
-# This file is part of the GNU C Library.
-
-# The GNU C Library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Library General Public License as
-# published by the Free Software Foundation; either version 2 of the
-# License, or (at your option) any later version.
-
-# The GNU C Library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Library General Public License for more details.
-
-# You should have received a copy of the GNU Library General Public
-# License along with the GNU C Library; see the file COPYING.LIB. If
-# not, write to the Free Software Foundation, Inc.,
-# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-AUTOMAKE_OPTIONS = foreign
-SUBDIRS = .
-
-LIBOBJS = @LIBOBJS@
-
-noinst_LIBRARIES = libargp.a
-
-noinst_HEADERS = argp.h argp-fmtstream.h argp-namefrob.h
-
-EXTRA_DIST = mempcpy.c strchrnul.c strndup.c strcasecmp.c vsnprintf.c autogen.sh
-
-# Leaves out argp-fs-xinl.c and argp-xinl.c
-libargp_a_SOURCES = argp-ba.c argp-eexst.c argp-fmtstream.c \
- argp-help.c argp-parse.c argp-pv.c \
- argp-pvh.c
-
-libargp_a_LIBADD = $(LIBOBJS)
-
-
diff --git a/argp-standalone/acinclude.m4 b/argp-standalone/acinclude.m4
deleted file mode 100644
index fb61e957dfa..00000000000
--- a/argp-standalone/acinclude.m4
+++ /dev/null
@@ -1,1084 +0,0 @@
-dnl Try to detect the type of the third arg to getsockname() et al
-AC_DEFUN([LSH_TYPE_SOCKLEN_T],
-[AH_TEMPLATE([socklen_t], [Length type used by getsockopt])
-AC_CACHE_CHECK([for socklen_t in sys/socket.h], ac_cv_type_socklen_t,
-[AC_EGREP_HEADER(socklen_t, sys/socket.h,
- [ac_cv_type_socklen_t=yes], [ac_cv_type_socklen_t=no])])
-if test $ac_cv_type_socklen_t = no; then
- AC_MSG_CHECKING(for AIX)
- AC_EGREP_CPP(yes, [
-#ifdef _AIX
- yes
-#endi