diff options
-rw-r--r-- | api/src/gfapi.aliases | 1 | ||||
-rw-r--r-- | api/src/gfapi.map | 1 | ||||
-rw-r--r-- | api/src/glfs-fops.c | 411 | ||||
-rw-r--r-- | api/src/glfs-handleops.c | 7 | ||||
-rw-r--r-- | api/src/glfs-handles.h | 4 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 25 | ||||
-rw-r--r-- | api/src/glfs.c | 103 | ||||
-rw-r--r-- | api/src/glfs.h | 8 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.c | 12 | ||||
-rw-r--r-- | libglusterfs/src/common-utils.h | 2 | ||||
-rw-r--r-- | libglusterfs/src/globals.c | 6 | ||||
-rw-r--r-- | libglusterfs/src/globals.h | 1 | ||||
-rw-r--r-- | libglusterfs/src/libglusterfs.sym | 3 |
13 files changed, 556 insertions, 28 deletions
diff --git a/api/src/gfapi.aliases b/api/src/gfapi.aliases index 42256726f63..a05b8dd1f55 100644 --- a/api/src/gfapi.aliases +++ b/api/src/gfapi.aliases @@ -164,6 +164,7 @@ _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_recall_lease _glfs_recall_lease$GFAPI_4.0.0 _pub_glfs_read_async _glfs_read_async$GFAPI_4.0.0 _pub_glfs_write_async _glfs_write_async$GFAPI_4.0.0 _pub_glfs_readv_async _glfs_readv_async$GFAPI_4.0.0 diff --git a/api/src/gfapi.map b/api/src/gfapi.map index e9b5f88037f..6fa0326d78a 100644 --- a/api/src/gfapi.map +++ b/api/src/gfapi.map @@ -207,6 +207,7 @@ GFAPI_4.0.0 { glfs_file_lock; glfs_lease; glfs_h_lease; + glfs_recall_lease; glfs_read_async; glfs_write_async; glfs_readv_async; diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 726574714e2..66b764dd0da 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -135,6 +135,41 @@ out: } 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_msg (THIS->name, GF_LOG_ERROR, errno, + API_MSG_ALLOC_FAILED, + "Upcall entry allocation failed."); + 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; @@ -192,6 +227,7 @@ pub_glfs_open (struct glfs *fs, const char *path, int flags) 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); @@ -243,13 +279,20 @@ retry: } glfd->fd->flags = flags; - ret = syncop_open (subvol, &loc, flags, glfd->fd, NULL, NULL); + 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; @@ -274,6 +317,7 @@ pub_glfs_close (struct glfs_fd *glfd) 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); @@ -297,14 +341,20 @@ pub_glfs_close (struct glfs_fd *glfd) 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, NULL, NULL); + 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); @@ -551,8 +601,10 @@ retry: } 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, NULL, NULL); + 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, @@ -708,6 +760,7 @@ glfs_preadv_common (struct glfs_fd *glfd, const struct iovec *iovec, 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); @@ -730,8 +783,12 @@ glfs_preadv_common (struct glfs_fd *glfd, const struct iovec *iovec, 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, NULL, NULL); + &iatt, fop_attr, NULL); DECODE_SYNCOP_ERR (ret); if (ret >= 0 && poststat) @@ -755,6 +812,8 @@ out: fd_unref (fd); if (glfd) GF_REF_PUT (glfd); + if (fop_attr) + dict_unref (fop_attr); glfs_subvol_done (glfd->fs, subvol); @@ -956,6 +1015,7 @@ glfs_preadv_async_common (struct glfs_fd *glfd, const struct iovec *iovec, xlator_t *subvol = NULL; glfs_t *fs = NULL; fd_t *fd = NULL; + dict_t *fop_attr = NULL; DECLARE_OLD_THIS; __GLFS_ENTRY_VALIDATE_FD (glfd, invalid_fs); @@ -1010,9 +1070,13 @@ glfs_preadv_async_common (struct glfs_fd *glfd, const struct iovec *iovec, 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, NULL); + offset, flags, fop_attr); out: if (ret) { @@ -1029,6 +1093,8 @@ out: } glfs_subvol_done (fs, subvol); } + if (fop_attr) + dict_unref (fop_attr); __GLFS_EXIT_FS; @@ -1222,6 +1288,7 @@ glfs_pwritev_common (struct glfs_fd *glfd, const struct iovec *iovec, 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); @@ -1246,8 +1313,12 @@ glfs_pwritev_common (struct glfs_fd *glfd, const struct iovec *iovec, 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, NULL, NULL); + &preiatt, &postiatt, fop_attr, NULL); DECODE_SYNCOP_ERR (ret); if (ret >= 0) { @@ -1270,6 +1341,8 @@ out: fd_unref (fd); if (glfd) GF_REF_PUT (glfd); + if (fop_attr) + dict_unref (fop_attr); glfs_subvol_done (glfd->fs, subvol); @@ -1383,6 +1456,7 @@ glfs_pwritev_async_common (struct glfs_fd *glfd, const struct iovec *iovec, 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); @@ -1438,9 +1512,13 @@ glfs_pwritev_async_common (struct glfs_fd *glfd, const struct iovec *iovec, 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, NULL); + gio->count, offset, flags, iobref, fop_attr); ret = 0; out: @@ -1456,6 +1534,8 @@ out: */ glfs_subvol_done (glfd->fs, subvol); } + if (fop_attr) + dict_unref (fop_attr); if (iobuf) iobuf_unref (iobuf); @@ -1604,6 +1684,7 @@ glfs_fsync_common (struct glfs_fd *glfd, struct stat *prestat, 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); @@ -1624,7 +1705,11 @@ glfs_fsync_common (struct glfs_fd *glfd, struct stat *prestat, goto out; } - ret = syncop_fsync (subvol, fd, 0, &preiatt, &postiatt, NULL, NULL); + 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) { @@ -1638,6 +1723,8 @@ out: fd_unref (fd); if (glfd) GF_REF_PUT (glfd); + if (fop_attr) + dict_unref (fop_attr); glfs_subvol_done (glfd->fs, subvol); @@ -1794,6 +1881,7 @@ glfs_fdatasync_common (struct glfs_fd *glfd, struct stat *prestat, 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); @@ -1814,7 +1902,11 @@ glfs_fdatasync_common (struct glfs_fd *glfd, struct stat *prestat, goto out; } - ret = syncop_fsync (subvol, fd, 1, &preiatt, &postiatt, NULL, NULL); + 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) { @@ -1828,6 +1920,8 @@ out: fd_unref (fd); if (glfd) GF_REF_PUT (glfd); + if (fop_attr) + dict_unref (fop_attr); glfs_subvol_done (glfd->fs, subvol); @@ -1902,6 +1996,7 @@ glfs_ftruncate_common (struct glfs_fd *glfd, off_t offset, 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); @@ -1922,8 +2017,12 @@ glfs_ftruncate_common (struct glfs_fd *glfd, off_t offset, 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, - NULL, NULL); + fop_attr, NULL); DECODE_SYNCOP_ERR (ret); if (ret >= 0) { @@ -1937,6 +2036,8 @@ out: fd_unref (fd); if (glfd) GF_REF_PUT (glfd); + if (fop_attr) + dict_unref (fop_attr); glfs_subvol_done (glfd->fs, subvol); @@ -2030,6 +2131,7 @@ glfs_ftruncate_async_common (struct glfs_fd *glfd, off_t offset, 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); @@ -2072,8 +2174,12 @@ glfs_ftruncate_async_common (struct glfs_fd *glfd, off_t offset, 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, NULL); + subvol->fops->ftruncate, fd, offset, fop_attr); ret = 0; @@ -2088,6 +2194,8 @@ out: STACK_DESTROY (frame->root); glfs_subvol_done (glfd->fs, subvol); } + if (fop_attr) + dict_unref (fop_attr); __GLFS_EXIT_FS; @@ -2511,6 +2619,7 @@ retry: goto out; } + /* TODO: Add leaseid */ ret = syncop_unlink (subvol, &loc, NULL, NULL); DECODE_SYNCOP_ERR (ret); @@ -2632,7 +2741,8 @@ retrynew: } } - /* TODO: check if new or old is a prefix of the other, and fail EINVAL */ + /* 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); @@ -2906,6 +3016,7 @@ glfs_discard_async_common (struct glfs_fd *glfd, off_t offset, size_t len, 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); @@ -2948,9 +3059,12 @@ glfs_discard_async_common (struct glfs_fd *glfd, off_t offset, size_t len, 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, NULL); + subvol->fops->discard, fd, offset, len, fop_attr); ret = 0; out: @@ -3015,6 +3129,7 @@ glfs_zerofill_async_common (struct glfs_fd *glfd, off_t offset, off_t len, 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); @@ -3058,8 +3173,12 @@ glfs_zerofill_async_common (struct glfs_fd *glfd, off_t offset, off_t len, 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, NULL); + subvol->fops->zerofill, fd, offset, len, fop_attr); ret = 0; out: if (ret) { @@ -3072,6 +3191,8 @@ out: STACK_DESTROY (frame->root); glfs_subvol_done (glfd->fs, subvol); } + if (fop_attr) + dict_unref (fop_attr); __GLFS_EXIT_FS; @@ -3427,6 +3548,7 @@ retry: if (ret) goto out; + /* TODO : Add leaseid */ ret = syncop_setattr (subvol, &loc, iatt, valid, 0, 0, NULL, NULL); DECODE_SYNCOP_ERR (ret); @@ -3469,6 +3591,7 @@ glfs_fsetattr (struct glfs_fd *glfd, struct iatt *iatt, int valid) goto out; } + /* TODO : Add leaseid */ ret = syncop_fsetattr (subvol, fd, iatt, valid, 0, 0, NULL, NULL); DECODE_SYNCOP_ERR (ret); out: @@ -4286,6 +4409,7 @@ pub_glfs_fallocate (struct glfs_fd *glfd, int keep_size, off_t offset, size_t le 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); @@ -4306,13 +4430,19 @@ pub_glfs_fallocate (struct glfs_fd *glfd, int keep_size, off_t offset, size_t le goto out; } - ret = syncop_fallocate (subvol, fd, keep_size, offset, len, NULL, NULL); + 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); @@ -4331,6 +4461,7 @@ 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); @@ -4351,13 +4482,19 @@ pub_glfs_discard (struct glfs_fd *glfd, off_t offset, size_t len) goto out; } - ret = syncop_discard (subvol, fd, offset, len, NULL, NULL); + 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); @@ -4376,6 +4513,7 @@ 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); @@ -4394,13 +4532,19 @@ pub_glfs_zerofill (struct glfs_fd *glfd, off_t offset, off_t len) goto out; } - ret = syncop_zerofill (subvol, fd, offset, len, NULL, NULL); + 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); @@ -4730,6 +4874,10 @@ glfs_lock_common (struct glfs_fd *glfd, int cmd, struct flock *flock, 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); @@ -4926,6 +5074,10 @@ glfs_enqueue_upcall_data (struct glfs *fs, struct gf_upcall *upcall_data) 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; } @@ -4954,6 +5106,172 @@ out: } 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); + + 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_msg (THIS->name, GF_LOG_ERROR, errno, + API_MSG_INODE_FIND_FAILED, + "Unable to find inode entry for gfid:%s graph id:%d", + uuid_utoa(up_data->gfid), subvol->graph->id); + goto out; + } + + LOCK (&inode->lock); + { + list_for_each_entry (fd, &inode->fd_list, inode_list) { + ret = fd_ctx_get (fd, subvol, &value); + glfd = (void *) 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); + + 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; +} + +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 = 0; + 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) { + ret = -1; + 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_msg (THIS->name, GF_LOG_DEBUG, errno, + API_MSG_CREATE_HANDLE_FAILED, + "handle creation of %s failed", + uuid_utoa (up_data->gfid)); + 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 = GF_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 void glfs_cbk_upcall_data (struct glfs *fs, struct gf_upcall *upcall_data) { int ret = -1; @@ -4980,6 +5298,9 @@ glfs_cbk_upcall_data (struct glfs *fs, struct gf_upcall *upcall_data) 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; } @@ -5069,9 +5390,14 @@ priv_glfs_process_upcall_event (struct glfs *fs, void *data) (char *)(upcall_data->gfid)); /* * - * TODO: RECALL LEASE - * Refer issue #350 - * Proposed patch https://review.gluster.org/#/c/14019/ + * 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 */ @@ -5165,6 +5491,7 @@ glfs_anonymous_pwritev (struct glfs *fs, struct glfs_object *object, 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); @@ -5234,6 +5561,7 @@ glfs_anonymous_preadv (struct glfs *fs, struct glfs_object *object, 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); @@ -5427,7 +5755,8 @@ glfs_lease_to_gf_lease (struct glfs_lease *lease, struct gf_lease *gf_lease) } int -pub_glfs_lease (struct glfs_fd *glfd, struct glfs_lease *lease) +pub_glfs_lease (struct glfs_fd *glfd, struct glfs_lease *lease, + glfs_recall_cbk fn, void *data) { int ret = -1; loc_t loc = {0, }; @@ -5460,6 +5789,30 @@ pub_glfs_lease (struct glfs_fd *glfd, struct glfs_lease *lease) 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); @@ -5474,15 +5827,21 @@ pub_glfs_lease (struct glfs_fd *glfd, struct glfs_lease *lease) 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_msg (subvol->name, GF_LOG_ERROR, ENOMEM, API_MSG_FDCTX_SET_FAILED, + "Setting fd ctx failed for fd(%p)", glfd->fd); + goto out; + } + glfd->cbk = fn; + glfd->cookie = data; + } out: - if (fd) - fd_unref (fd); - if (glfd) { + if (glfd) GF_REF_PUT (glfd); - glfd = NULL; - } if (subvol) glfs_subvol_done (glfd->fs, subvol); diff --git a/api/src/glfs-handleops.c b/api/src/glfs-handleops.c index f8193408ec0..cb37de30e4a 100644 --- a/api/src/glfs-handleops.c +++ b/api/src/glfs-handleops.c @@ -622,6 +622,7 @@ pub_glfs_h_open (struct glfs *fs, struct glfs_object *object, int flags) 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)) { @@ -678,6 +679,10 @@ pub_glfs_h_open (struct glfs *fs, struct glfs_object *object, int flags) 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, NULL, NULL); DECODE_SYNCOP_ERR (ret); @@ -688,6 +693,8 @@ out: if (inode) inode_unref (inode); + if (fop_attr) + dict_unref (fop_attr); if (ret && glfd) { GF_REF_PUT (glfd); diff --git a/api/src/glfs-handles.h b/api/src/glfs-handles.h index 97c058a11c7..b89d09c3404 100644 --- a/api/src/glfs-handles.h +++ b/api/src/glfs-handles.h @@ -332,6 +332,10 @@ int glfs_h_lease (struct glfs *fs, struct glfs_object *object, struct glfs_lease *lease) __THROW GFAPI_PUBLIC(glfs_h_lease, 4.0.0); +struct glfs_object * +glfs_h_find_handle (struct glfs *fs, unsigned char *handle, + int len) __THROW + GFAPI_PUBLIC(glfs_h_lease, 4.0.0); __END_DECLS #endif /* !_GLFS_HANDLES_H */ diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 145509c3caf..788c6b00545 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -213,6 +213,7 @@ enum glfs_fd_state { struct glfs_fd { struct list_head openfds; + struct list_head list; GF_REF_DECL; struct glfs *fs; enum glfs_fd_state state; @@ -224,6 +225,8 @@ struct glfs_fd { 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 @@ -254,6 +257,16 @@ struct glfs_upcall_inode { 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 */ @@ -614,4 +627,16 @@ 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); #endif /* !_GLFS_INTERNAL_H */ diff --git a/api/src/glfs.c b/api/src/glfs.c index 6724534fb31..da6bc3a07ba 100644 --- a/api/src/glfs.c +++ b/api/src/glfs.c @@ -578,7 +578,7 @@ pub_glfs_setfsleaseid (glfs_leaseid_t leaseid) GF_VALIDATE_OR_GOTO (THIS->name, leaseid, out); - gleaseid = glusterfs_leaseid_buf_get(); + gleaseid = gf_leaseid_get(); if (gleaseid) { memcpy (gleaseid, leaseid, LEASE_ID_SIZE); ret = 0; @@ -589,6 +589,87 @@ out: GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_setfsleaseid, 4.0.0); +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_CALLOC (1, 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_static_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 *lease_id = NULL; + int ret = 0; + gf_boolean_t dict_create = _gf_false; + + lease_id = gf_existing_leaseid (); + if (lease_id) { + 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", gf_strdup (lease_id), + LEASE_ID_SIZE); + } + +out: + if (ret && 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; + } +} struct glfs * pub_glfs_from_glfd (struct glfs_fd *glfd) { @@ -1486,6 +1567,22 @@ pub_glfs_upcall_inode_get_oldpstat (struct glfs_upcall_inode *arg) GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_inode_get_oldpstat, 3.7.16); +/*struct glfs_object* +pub_glfs_upcall_lease_get_object (struct glfs_upcall_recall_inode *arg) +{ + return arg->object; +} + +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_object, 4.0.0); +*/ + +uint32_t +pub_glfs_upcall_lease_get_lease_type (struct glfs_upcall_lease *arg) +{ + return arg->lease_type; +} +GFAPI_SYMVER_PUBLIC_DEFAULT(glfs_upcall_lease_get_lease_type, 4.0.0); + /* definitions of the GLFS_SYSRQ_* chars are in glfs.h */ static struct glfs_sysrq_help { char sysrq; @@ -1578,8 +1675,10 @@ glfs_upcall_register (struct glfs *fs, uint32_t event_list, */ fs->upcall_events |= GF_UPCALL_CACHE_INVALIDATION; ret |= GF_UPCALL_CACHE_INVALIDATION; + } else if (event_list & GLFS_EVENT_INODE_INVALIDATE) { + fs->upcall_events |= GF_UPCALL_RECALL_LEASE; + ret |= GF_UPCALL_RECALL_LEASE; } - /* Override cbk function if existing */ fs->up_cbk = cbk; fs->up_data = data; diff --git a/api/src/glfs.h b/api/src/glfs.h index 59e5784f91f..f9f8d4f36a2 100644 --- a/api/src/glfs.h +++ b/api/src/glfs.h @@ -1151,10 +1151,18 @@ typedef void (*glfs_recall_cbk) (struct glfs_lease lease, void *data); 0: Successfull completion <0: Failure. @errno will be set with the type of failure */ +struct gf_upcall; int glfs_lease (struct glfs_fd *glfd, struct glfs_lease *lease, glfs_recall_cbk fn, void *data) __THROW GFAPI_PUBLIC(glfs_lease, 4.0.0); +int +glfs_recall_lease_fd (struct glfs *fs, struct gf_upcall *up_data) __THROW + GFAPI_PUBLIC(glfs_recall_lease_fd, 4.0.0); +int +glfs_recall_lease_upcall (struct glfs *fs, struct glfs_upcall *up_arg, + struct gf_upcall *up_data) __THROW + GFAPI_PUBLIC(glfs_recall_lease_upcall, 4.0.0); __END_DECLS #endif /* !_GLFS_H */ diff --git a/libglusterfs/src/common-utils.c b/libglusterfs/src/common-utils.c index ea8903b5b4a..56fc0495572 100644 --- a/libglusterfs/src/common-utils.c +++ b/libglusterfs/src/common-utils.c @@ -2775,6 +2775,18 @@ out: return buf; } +char * +gf_leaseid_get () +{ + return glusterfs_leaseid_buf_get (); +} + +char * +gf_existing_leaseid () +{ + return glusterfs_leaseid_exist (); +} + void* gf_array_elem (void *a, int index, size_t elem_size) { uint8_t* ptr = a; diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h index b1adc9fbe0a..2bad5b4736e 100644 --- a/libglusterfs/src/common-utils.h +++ b/libglusterfs/src/common-utils.h @@ -824,6 +824,8 @@ char *lkowner_utoa (gf_lkowner_t *lkowner); char *lkowner_utoa_r (gf_lkowner_t *lkowner, char *dst, int len); char *leaseid_utoa (const char *lease_id); gf_boolean_t is_valid_lease_id (const char *lease_id); +char *gf_leaseid_get (void); +char *gf_existing_leaseid (void); void gf_array_insertionsort (void *a, int l, int r, size_t elem_size, gf_cmp cmp); diff --git a/libglusterfs/src/globals.c b/libglusterfs/src/globals.c index f1eaccc9305..3506d482bda 100644 --- a/libglusterfs/src/globals.c +++ b/libglusterfs/src/globals.c @@ -483,6 +483,12 @@ glusterfs_leaseid_buf_get () return buf; } +char * +glusterfs_leaseid_exist () +{ + return pthread_getspecific (leaseid_buf_key); +} + static void gf_globals_init_once () { diff --git a/libglusterfs/src/globals.h b/libglusterfs/src/globals.h index 487facd9183..5404780e456 100644 --- a/libglusterfs/src/globals.h +++ b/libglusterfs/src/globals.h @@ -138,6 +138,7 @@ char *glusterfs_uuid_buf_get (void); char *glusterfs_lkowner_buf_get (void); /* leaseid buf */ char *glusterfs_leaseid_buf_get (void); +char *glusterfs_leaseid_exist (void); /* init */ int glusterfs_globals_init (glusterfs_ctx_t *ctx); diff --git a/libglusterfs/src/libglusterfs.sym b/libglusterfs/src/libglusterfs.sym index 8b2567a4c62..17651e47e36 100644 --- a/libglusterfs/src/libglusterfs.sym +++ b/libglusterfs/src/libglusterfs.sym @@ -823,6 +823,8 @@ is_graph_topology_equal __is_root_gfid is_valid_lease_id leaseid_utoa +gf_existing_leaseid +gf_leaseid_get list_node_add list_node_add_order list_node_del @@ -1113,5 +1115,6 @@ global_xlator use_spinlocks dump_options glusterfs_leaseid_buf_get +glusterfs_leaseid_exist gf_replace_old_iatt_in_dict gf_replace_new_iatt_in_dict |