summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/src/glfs-fops.c181
-rw-r--r--api/src/glfs-handleops.c15
-rw-r--r--api/src/glfs-internal.h18
-rw-r--r--api/src/glfs.c50
4 files changed, 224 insertions, 40 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c
index ce0cebc20c1..fdffc7b7cb3 100644
--- a/api/src/glfs-fops.c
+++ b/api/src/glfs-fops.c
@@ -28,6 +28,35 @@
#define READDIRBUF_SIZE (sizeof(struct dirent) + GF_NAME_MAX + 1)
/*
+ * This function will mark glfd for deletion and decrement its refcount.
+ */
+int
+glfs_mark_glfd_for_deletion (struct glfs_fd *glfd)
+{
+ glfd->state = GLFD_CLOSE;
+
+ GF_REF_PUT (glfd);
+
+ return 0;
+}
+
+/* This function is usefull 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)
+{
+ if (glfd->state != GLFD_CLOSE)
+ return _gf_true;
+
+ return _gf_false;
+}
+
+/*
* 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
@@ -190,9 +219,10 @@ out:
loc_wipe (&loc);
if (ret && glfd) {
- glfs_fd_destroy (glfd);
+ GF_REF_PUT (glfd);
glfd = NULL;
} else if (glfd) {
+ glfd->state = GLFD_OPEN;
fd_bind (glfd->fd);
glfs_fd_bind (glfd);
}
@@ -207,7 +237,6 @@ invalid_fs:
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_open, 3.4.0);
-
int
pub_glfs_close (struct glfs_fd *glfd)
{
@@ -237,11 +266,11 @@ pub_glfs_close (struct glfs_fd *glfd)
DECODE_SYNCOP_ERR (ret);
out:
fs = glfd->fs;
- glfs_fd_destroy (glfd);
- if (fd)
- fd_unref (fd);
+ if (fd)
+ fd_unref (fd);
+ glfs_mark_glfd_for_deletion (glfd);
glfs_subvol_done (fs, subvol);
__GLFS_EXIT_FS;
@@ -342,6 +371,8 @@ pub_glfs_fstat (struct glfs_fd *glfd, struct stat *stat)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -364,6 +395,8 @@ pub_glfs_fstat (struct glfs_fd *glfd, struct stat *stat)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -502,9 +535,10 @@ out:
dict_unref (xattr_req);
if (ret && glfd) {
- glfs_fd_destroy (glfd);
+ GF_REF_PUT (glfd);
glfd = NULL;
} else if (glfd) {
+ glfd->state = GLFD_OPEN;
fd_bind (glfd->fd);
glfs_fd_bind (glfd);
}
@@ -530,6 +564,8 @@ pub_glfs_lseek (struct glfs_fd *glfd, off_t offset, int whence)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
switch (whence) {
case SEEK_SET:
glfd->offset = offset;
@@ -551,6 +587,9 @@ pub_glfs_lseek (struct glfs_fd *glfd, off_t offset, int whence)
errno = EINVAL;
}
+ if (glfd)
+ GF_REF_PUT (glfd);
+
__GLFS_EXIT_FS;
if (ret != -1)
@@ -580,6 +619,8 @@ pub_glfs_preadv (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -615,6 +656,8 @@ out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -693,7 +736,18 @@ glfs_io_async_cbk (int ret, call_frame_t *frame, void *data)
{
struct glfs_io *gio = data;
- gio->fn (gio->glfd, ret, gio->data);
+ /* If the fd is already closed then
+ * no need to do the callback */
+ if (glfs_is_glfd_still_valid (gio->glfd)) {
+ gio->fn (gio->glfd, ret, gio->data);
+ }
+
+ /* Since the async operation is complete
+ * release the ref taken during the start
+ * of async operation
+ */
+ if (gio->glfd)
+ GF_REF_PUT (gio->glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
@@ -769,6 +823,9 @@ glfs_preadv_async_cbk (call_frame_t *frame, void *cookie, xlator_t *this,
glfd = gio->glfd;
fs = glfd->fs;
+ if (!glfs_is_glfd_still_valid (glfd))
+ goto err;
+
if (op_ret <= 0)
goto out;
@@ -779,6 +836,13 @@ out:
errno = op_errno;
gio->fn (gio->glfd, op_ret, gio->data);
+err:
+ /* 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);
@@ -803,6 +867,8 @@ pub_glfs_preadv_async (struct glfs_fd *glfd, const struct iovec *iovec,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -856,6 +922,8 @@ pub_glfs_preadv_async (struct glfs_fd *glfd, const struct iovec *iovec,
out:
if (ret) {
+ if (glfd)
+ GF_REF_PUT (glfd);
if (gio) {
GF_FREE (gio->iov);
GF_FREE (gio);
@@ -945,6 +1013,8 @@ pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -1005,6 +1075,8 @@ pub_glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt,
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -1100,11 +1172,17 @@ pub_glfs_pwritev_async (struct glfs_fd *glfd, const struct iovec *iovec,
gio->fn = fn;
gio->data = data;
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET (glfd);
+
ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
+ GF_REF_PUT (glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
}
@@ -1179,6 +1257,8 @@ pub_glfs_fsync (struct glfs_fd *glfd)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -1198,6 +1278,8 @@ pub_glfs_fsync (struct glfs_fd *glfd)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -1223,6 +1305,11 @@ glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data,
return -1;
}
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET (glfd);
+
gio->op = GF_FOP_FSYNC;
gio->glfd = glfd;
gio->flags = dataonly;
@@ -1234,6 +1321,7 @@ glfs_fsync_async_common (struct glfs_fd *glfd, glfs_io_cbk fn, void *data,
NULL, gio);
if (ret) {
+ GF_REF_PUT (glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
}
@@ -1272,6 +1360,8 @@ pub_glfs_fdatasync (struct glfs_fd *glfd)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -1291,6 +1381,8 @@ pub_glfs_fdatasync (struct glfs_fd *glfd)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -1332,6 +1424,8 @@ pub_glfs_ftruncate (struct glfs_fd *glfd, off_t offset)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -1351,6 +1445,8 @@ pub_glfs_ftruncate (struct glfs_fd *glfd, off_t offset)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -1385,11 +1481,17 @@ pub_glfs_ftruncate_async (struct glfs_fd *glfd, off_t offset, glfs_io_cbk fn,
gio->fn = fn;
gio->data = data;
+ /* Need to take explicit ref so that the fd
+ * is not destroyed before the fop is complete
+ */
+ GF_REF_GET (glfd);
+
ret = synctask_new (pub_glfs_from_glfd (glfd)->ctx->env,
glfs_io_async_task, glfs_io_async_cbk,
NULL, gio);
if (ret) {
+ GF_REF_PUT (glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
}
@@ -2095,9 +2197,10 @@ out:
loc_wipe (&loc);
if (ret && glfd) {
- glfs_fd_destroy (glfd);
+ GF_REF_PUT (glfd);
glfd = NULL;
} else if (glfd) {
+ glfd->state = GLFD_OPEN;
fd_bind (glfd->fd);
glfs_fd_bind (glfd);
}
@@ -2123,7 +2226,7 @@ pub_glfs_closedir (struct glfs_fd *glfd)
gf_dirent_free (list_entry (&glfd->entries, gf_dirent_t, list));
- glfs_fd_destroy (glfd);
+ glfs_mark_glfd_for_deletion (glfd);
__GLFS_EXIT_FS;
@@ -2185,6 +2288,11 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
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);
+
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
@@ -2203,6 +2311,7 @@ pub_glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len,
NULL, gio);
if (ret) {
+ GF_REF_PUT (glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
}
@@ -2227,6 +2336,11 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len,
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);
+
gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t);
if (!gio) {
errno = ENOMEM;
@@ -2245,6 +2359,7 @@ pub_glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, off_t len,
NULL, gio);
if (ret) {
+ GF_REF_PUT (glfd);
GF_FREE (gio->iov);
GF_FREE (gio);
}
@@ -2424,6 +2539,8 @@ pub_glfs_readdirplus_r (struct glfs_fd *glfd, struct stat *stat,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
errno = 0;
if (ext)
@@ -2455,6 +2572,9 @@ pub_glfs_readdirplus_r (struct glfs_fd *glfd, struct stat *stat,
}
out:
+ if (glfd)
+ GF_REF_PUT (glfd);
+
__GLFS_EXIT_FS;
return ret;
@@ -2601,6 +2721,8 @@ glfs_fsetattr (struct glfs_fd *glfd, struct iatt *iatt, int valid)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -2620,6 +2742,8 @@ glfs_fsetattr (struct glfs_fd *glfd, struct iatt *iatt, int valid)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -2939,6 +3063,8 @@ pub_glfs_fgetxattr (struct glfs_fd *glfd, const char *name, void *value,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
if (!name || *name == '\0') {
ret = -1;
errno = EINVAL;
@@ -2974,6 +3100,8 @@ pub_glfs_fgetxattr (struct glfs_fd *glfd, const char *name, void *value,
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3096,6 +3224,8 @@ pub_glfs_flistxattr (struct glfs_fd *glfd, void *value, size_t size)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3119,6 +3249,8 @@ pub_glfs_flistxattr (struct glfs_fd *glfd, void *value, size_t size)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3232,6 +3364,8 @@ pub_glfs_fsetxattr (struct glfs_fd *glfd, const char *name, const void *value,
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
if (!name || *name == '\0') {
ret = -1;
errno = EINVAL;
@@ -3273,6 +3407,8 @@ out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3360,6 +3496,8 @@ pub_glfs_fremovexattr (struct glfs_fd *glfd, const char *name)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3379,6 +3517,8 @@ pub_glfs_fremovexattr (struct glfs_fd *glfd, const char *name)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3401,6 +3541,8 @@ pub_glfs_fallocate (struct glfs_fd *glfd, int keep_size, off_t offset, size_t le
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3420,6 +3562,8 @@ pub_glfs_fallocate (struct glfs_fd *glfd, int keep_size, off_t offset, size_t le
out:
if (fd)
fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3442,6 +3586,8 @@ pub_glfs_discard (struct glfs_fd *glfd, off_t offset, size_t len)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3461,6 +3607,8 @@ pub_glfs_discard (struct glfs_fd *glfd, off_t offset, size_t len)
out:
if (fd)
fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3483,6 +3631,8 @@ pub_glfs_zerofill (struct glfs_fd *glfd, off_t offset, off_t len)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
errno = EIO;
@@ -3500,6 +3650,8 @@ pub_glfs_zerofill (struct glfs_fd *glfd, off_t offset, off_t len)
out:
if (fd)
fd_unref(fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3571,6 +3723,8 @@ pub_glfs_fchdir (struct glfs_fd *glfd)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3598,6 +3752,8 @@ pub_glfs_fchdir (struct glfs_fd *glfd)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3759,6 +3915,7 @@ pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
subvol = glfs_active_subvol (glfd->fs);
if (!subvol) {
ret = -1;
@@ -3784,6 +3941,8 @@ pub_glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock)
out:
if (fd)
fd_unref (fd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (glfd->fs, subvol);
@@ -3807,6 +3966,8 @@ pub_glfs_dup (struct glfs_fd *glfd)
DECLARE_OLD_THIS;
__GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs);
+ GF_REF_GET (glfd);
+
fs = glfd->fs;
subvol = glfs_active_subvol (fs);
if (!subvol) {
@@ -3832,6 +3993,8 @@ out:
fd_unref (fd);
if (dupfd)
glfs_fd_bind (dupfd);
+ if (glfd)
+ GF_REF_PUT (glfd);
glfs_subvol_done (fs, subvol);
diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c
index cd0f6b3e950..a230578b615 100644
--- a/api/src/glfs-handleops.c
+++ b/api/src/glfs-handleops.c
@@ -686,8 +686,10 @@ out:
inode_unref (inode);
if (ret && glfd) {
- glfs_fd_destroy (glfd);
+ GF_REF_PUT (glfd);
glfd = NULL;
+ } else if (glfd) {
+ glfd->state = GLFD_OPEN;
}
glfs_subvol_done (fs, subvol);
@@ -808,9 +810,11 @@ out:
if (xattr_req)
dict_unref (xattr_req);
- if (glfd) {
- glfs_fd_destroy (glfd);
+ if (ret && glfd) {
+ GF_REF_PUT (glfd);
glfd = NULL;
+ } else if (glfd) {
+ glfd->state = GLFD_OPEN;
}
glfs_subvol_done (fs, subvol);
@@ -1151,9 +1155,10 @@ out:
inode_unref (inode);
if (ret && glfd) {
- glfs_fd_destroy (glfd);
+ GF_REF_PUT (glfd);
glfd = NULL;
- } else {
+ } else if (glfd) {
+ glfd->state = GLFD_OPEN;
fd_bind (glfd->fd);
glfs_fd_bind (glfd);
}
diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h
index dbf17918888..e1b8c8ac5f2 100644
--- a/api/src/glfs-internal.h
+++ b/api/src/glfs-internal.h
@@ -16,6 +16,7 @@
#include "glusterfs.h"
#include "upcall-utils.h"
#include "glfs-handles.h"
+#include "refcount.h"
#define GLFS_SYMLINK_MAX_FOLLOW 2048
@@ -208,9 +209,20 @@ struct glfs {
uint32_t pthread_flags; /* GLFS_INIT_* # defines set this flag */
};
+/* 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;
+ 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;
@@ -269,7 +281,8 @@ do { \
#define __GLFS_ENTRY_VALIDATE_FD(glfd, label) \
do { \
- if (!glfd || !glfd->fd || !glfd->fd->inode) { \
+ if (!glfd || !glfd->fd || !glfd->fd->inode || \
+ glfd->state != GLFD_OPEN) { \
errno = EBADF; \
goto label; \
} \
@@ -308,9 +321,6 @@ glfs_unlock (struct glfs *fs)
pthread_mutex_unlock (&fs->mutex);
}
-
-void glfs_fd_destroy (struct glfs_fd *glfd);
-
struct glfs_fd *glfs_fd_new (struct glfs *fs);
void glfs_fd_bind (struct glfs_fd *glfd);
diff --git a/api/src/glfs.c b/api/src/glfs.c
index 10658ef3819..1fc1a30ac4c 100644
--- a/api/src/glfs.c
+++ b/api/src/glfs.c
@@ -516,6 +516,32 @@ pub_glfs_from_glfd (struct glfs_fd *glfd)
GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_from_glfd, 3.4.0);
+void
+glfs_fd_destroy (void *data)
+{
+ struct glfs_fd *glfd = NULL;
+
+ if (!data)
+ return;
+
+ glfd = (struct glfs_fd *)data;
+
+ glfs_lock (glfd->fs);
+ {
+ 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)
@@ -530,6 +556,8 @@ glfs_fd_new (struct glfs *fs)
INIT_LIST_HEAD (&glfd->openfds);
+ GF_REF_INIT (glfd, glfs_fd_destroy);
+
return glfd;
}
@@ -548,28 +576,6 @@ glfs_fd_bind (struct glfs_fd *glfd)
glfs_unlock (fs);
}
-void
-glfs_fd_destroy (struct glfs_fd *glfd)
-{
- if (!glfd)
- return;
-
- glfs_lock (glfd->fs);
- {
- 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);
-}
-
static void *
glfs_poller (void *data)