diff options
Diffstat (limited to 'api/src/glfs-fops.c')
| -rw-r--r-- | api/src/glfs-fops.c | 1356 |
1 files changed, 1235 insertions, 121 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index be26dc121..10bb7d38b 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -13,6 +13,56 @@ #include "glfs-mem-types.h" #include "syncop.h" #include "glfs.h" +#include <limits.h> + +#ifdef NAME_MAX +#define GF_NAME_MAX NAME_MAX +#else +#define GF_NAME_MAX 255 +#endif + +#define READDIRBUF_SIZE (sizeof(struct dirent) + GF_NAME_MAX + 1) + +int +glfs_loc_link (loc_t *loc, struct iatt *iatt) +{ + int ret = -1; + inode_t *linked_inode = NULL; + + if (!loc->inode) { + errno = EINVAL; + return -1; + } + + linked_inode = inode_link (loc->inode, loc->parent, loc->name, iatt); + if (linked_inode) { + inode_lookup (linked_inode); + inode_unref (linked_inode); + ret = 0; + } else { + ret = -1; + errno = ENOMEM; + } + + 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; +} + + +int +glfs_loc_unlink (loc_t *loc) +{ + inode_unlink (loc->inode, loc->parent, loc->name); + + return 0; +} struct glfs_fd * @@ -23,6 +73,7 @@ glfs_open (struct glfs *fs, const char *path, int flags) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -33,11 +84,15 @@ glfs_open (struct glfs *fs, const char *path, int flags) goto out; } - glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t); + glfd = glfs_fd_new (fs); if (!glfd) goto out; - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); +retry: + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + if (ret) goto out; @@ -53,6 +108,14 @@ glfs_open (struct glfs *fs, const char *path, int flags) 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; @@ -61,14 +124,22 @@ glfs_open (struct glfs *fs, const char *path, int flags) } ret = syncop_open (subvol, &loc, flags, glfd->fd); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); if (ret && glfd) { glfs_fd_destroy (glfd); glfd = NULL; + } else if (glfd) { + glfd->fd->flags = flags; + fd_bind (glfd->fd); + glfs_fd_bind (glfd); } + glfs_subvol_done (fs, subvol); + return glfd; } @@ -78,15 +149,35 @@ glfs_close (struct glfs_fd *glfd) { xlator_t *subvol = NULL; int ret = -1; + fd_t *fd = NULL; + struct glfs *fs = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); + if (!subvol) { + ret = -1; + errno = EIO; + goto out; + } - ret = syncop_flush (subvol, glfd->fd); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + ret = syncop_flush (subvol, fd); +out: + fs = glfd->fs; glfs_fd_destroy (glfd); + if (fd) + fd_unref (fd); + + glfs_subvol_done (fs, subvol); + return ret; } @@ -98,6 +189,7 @@ glfs_lstat (struct glfs *fs, const char *path, struct stat *stat) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -107,14 +199,18 @@ glfs_lstat (struct glfs *fs, const char *path, struct stat *stat) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (ret == 0 && stat) - iatt_to_stat (&iatt, stat); + glfs_iatt_to_stat (fs, &iatt, stat); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -126,6 +222,7 @@ glfs_stat (struct glfs *fs, const char *path, struct stat *stat) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -135,14 +232,18 @@ glfs_stat (struct glfs *fs, const char *path, struct stat *stat) errno = EIO; goto out; } +retry: + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (ret == 0 && stat) - iatt_to_stat (&iatt, stat); + glfs_iatt_to_stat (fs, &iatt, stat); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -153,21 +254,34 @@ glfs_fstat (struct glfs_fd *glfd, struct stat *stat) int ret = -1; xlator_t *subvol = NULL; struct iatt iatt = {0, }; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fstat (subvol, glfd->fd, &iatt); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fstat (subvol, fd, &iatt); if (ret == 0 && stat) - iatt_to_stat (&iatt, stat); + glfs_iatt_to_stat (glfd->fs, &iatt, stat); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -182,6 +296,7 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) struct iatt iatt = {0, }; uuid_t gfid; dict_t *xattr_req = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -207,7 +322,7 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) goto out; } - glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t); + glfd = glfs_fd_new (fs); if (!glfd) goto out; @@ -216,7 +331,11 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) is a danging symlink must create the dangling destinataion. */ - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); +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; @@ -256,6 +375,14 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) } } + 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; @@ -263,18 +390,34 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) goto out; } - ret = syncop_create (subvol, &loc, flags, mode, glfd->fd, xattr_req); + if (ret == 0) { + ret = syncop_open (subvol, &loc, flags, glfd->fd); + } else { + ret = syncop_create (subvol, &loc, flags, mode, glfd->fd, + xattr_req, &iatt); + } + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_link (&loc, &iatt); out: loc_wipe (&loc); if (xattr_req) - dict_destroy (xattr_req); + dict_unref (xattr_req); if (ret && glfd) { glfs_fd_destroy (glfd); glfd = NULL; + } else if (glfd) { + glfd->fd->flags = flags; + fd_bind (glfd->fd); + glfs_fd_bind (glfd); } + glfs_subvol_done (fs, subvol); + return glfd; } @@ -315,33 +458,52 @@ glfs_preadv (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, off_t offset, int flags) { xlator_t *subvol = NULL; - int ret = -1; - size_t size = -1; + ssize_t ret = -1; + ssize_t size = -1; struct iovec *iov = NULL; int cnt = 0; struct iobref *iobref = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (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 = syncop_readv (subvol, glfd->fd, size, offset, - 0, &iov, &cnt, &iobref); + ret = syncop_readv (subvol, fd, size, offset, 0, &iov, &cnt, &iobref); if (ret <= 0) - return ret; + goto out; size = iov_copy (iovec, iovcnt, iov, cnt); /* FIXME!!! */ glfd->offset = (offset + size); - if (iov) - GF_FREE (iov); - if (iobref) - iobref_unref (iobref); + ret = size; +out: + if (iov) + GF_FREE (iov); + if (iobref) + iobref_unref (iobref); - return size; + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; } @@ -421,10 +583,6 @@ glfs_io_async_task (void *data) ssize_t ret = 0; switch (gio->op) { - case GF_FOP_READ: - ret = glfs_preadv (gio->glfd, gio->iov, gio->count, - gio->offset, gio->flags); - break; case GF_FOP_WRITE: ret = glfs_pwritev (gio->glfd, gio->iov, gio->count, gio->offset, gio->flags); @@ -438,6 +596,12 @@ glfs_io_async_task (void *data) else ret = glfs_fsync (gio->glfd); break; + case GF_FOP_DISCARD: + ret = glfs_discard (gio->glfd, gio->offset, gio->count); + break; + case GF_FOP_ZEROFILL: + ret = glfs_zerofill(gio->glfd, gio->offset, gio->count); + break; } return (int) ret; @@ -445,23 +609,90 @@ glfs_io_async_task (void *data) 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) +{ + struct glfs_io *gio = NULL; + xlator_t *subvol = NULL; + struct glfs *fs = NULL; + struct glfs_fd *glfd = NULL; + + + gio = frame->local; + frame->local = NULL; + subvol = cookie; + glfd = gio->glfd; + fs = glfd->fs; + + if (op_ret <= 0) + goto out; + + op_ret = iov_copy (gio->iov, gio->count, iovec, count); + + glfd->offset = gio->offset + op_ret; +out: + errno = op_errno; + gio->fn (gio->glfd, op_ret, gio->data); + + GF_FREE (gio->iov); + GF_FREE (gio); + STACK_DESTROY (frame->root); + glfs_subvol_done (fs, subvol); + + return 0; +} + + +int glfs_preadv_async (struct glfs_fd *glfd, const struct iovec *iovec, int count, off_t offset, int flags, glfs_io_cbk fn, void *data) { struct glfs_io *gio = NULL; int ret = 0; + call_frame_t *frame = NULL; + xlator_t *subvol = NULL; + glfs_t *fs = NULL; + fd_t *fd = NULL; + + __glfs_entry_fd (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; - return -1; + goto out; } gio->iov = iov_dup (iovec, count); if (!gio->iov) { - GF_FREE (gio); + ret = -1; errno = ENOMEM; - return -1; + goto out; } gio->op = GF_FOP_READ; @@ -472,15 +703,23 @@ glfs_preadv_async (struct glfs_fd *glfd, const struct iovec *iovec, int count, gio->fn = fn; gio->data = data; - ret = synctask_new (glfs_from_glfd (glfd)->ctx->env, - glfs_io_async_task, glfs_io_async_cbk, - NULL, gio); + frame->local = gio; + STACK_WIND_COOKIE (frame, glfs_preadv_async_cbk, subvol, subvol, + subvol->fops->readv, fd, iov_length (iovec, count), + offset, flags, NULL); + +out: if (ret) { GF_FREE (gio->iov); GF_FREE (gio); + STACK_DESTROY (frame->root); + glfs_subvol_done (fs, subvol); } + if (fd) + fd_unref (fd); + return ret; } @@ -540,24 +779,39 @@ glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, struct iobref *iobref = NULL; struct iobuf *iobuf = NULL; struct iovec iov = {0, }; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (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); iobuf = iobuf_get2 (subvol->ctx->iobuf_pool, size); if (!iobuf) { + ret = -1; errno = ENOMEM; - return -1; + goto out; } iobref = iobref_new (); if (!iobref) { iobuf_unref (iobuf); errno = ENOMEM; - return -1; + ret = -1; + goto out; } ret = iobref_add (iobref, iobuf); @@ -565,7 +819,8 @@ glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, iobuf_unref (iobuf); iobref_unref (iobref); errno = ENOMEM; - return -1; + ret = -1; + goto out; } iov_unload (iobuf_ptr (iobuf), iovec, iovcnt); /* FIXME!!! */ @@ -573,17 +828,22 @@ glfs_pwritev (struct glfs_fd *glfd, const struct iovec *iovec, int iovcnt, iov.iov_base = iobuf_ptr (iobuf); iov.iov_len = size; - ret = syncop_writev (subvol, glfd->fd, &iov, 1, offset, - iobref, flags); + ret = syncop_writev (subvol, fd, &iov, 1, offset, iobref, flags); iobuf_unref (iobuf); iobref_unref (iobref); if (ret <= 0) - return ret; + goto out; glfd->offset = (offset + size); +out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -722,18 +982,31 @@ glfs_fsync (struct glfs_fd *glfd) { int ret = -1; xlator_t *subvol = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fsync (subvol, glfd->fd, 0); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fsync (subvol, fd, 0); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -783,18 +1056,31 @@ glfs_fdatasync (struct glfs_fd *glfd) { int ret = -1; xlator_t *subvol = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fsync (subvol, glfd->fd, 1); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fsync (subvol, fd, 1); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -811,18 +1097,31 @@ glfs_ftruncate (struct glfs_fd *glfd, off_t offset) { int ret = -1; xlator_t *subvol = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_ftruncate (subvol, glfd->fd, offset); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_ftruncate (subvol, fd, offset); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -866,6 +1165,7 @@ glfs_access (struct glfs *fs, const char *path, int mode) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -875,15 +1175,22 @@ glfs_access (struct glfs *fs, const char *path, int mode) errno = EIO; goto out; } +retry: + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; ret = syncop_access (subvol, &loc, mode); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -897,6 +1204,7 @@ glfs_symlink (struct glfs *fs, const char *data, const char *path) struct iatt iatt = {0, }; uuid_t gfid; dict_t *xattr_req = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -921,8 +1229,10 @@ glfs_symlink (struct glfs *fs, const char *data, const char *path) errno = ENOMEM; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (loc.inode) { errno = EEXIST; @@ -948,12 +1258,19 @@ glfs_symlink (struct glfs *fs, const char *data, const char *path) goto out; } - ret = syncop_symlink (subvol, &loc, data, xattr_req); + ret = syncop_symlink (subvol, &loc, data, xattr_req, &iatt); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_link (&loc, &iatt); out: loc_wipe (&loc); if (xattr_req) - dict_destroy (xattr_req); + dict_unref (xattr_req); + + glfs_subvol_done (fs, subvol); return ret; } @@ -966,6 +1283,8 @@ glfs_readlink (struct glfs *fs, const char *path, char *buf, size_t bufsiz) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; + char *linkval = NULL; __glfs_entry_fs (fs); @@ -975,8 +1294,11 @@ glfs_readlink (struct glfs *fs, const char *path, char *buf, size_t bufsiz) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; @@ -986,10 +1308,18 @@ glfs_readlink (struct glfs *fs, const char *path, char *buf, size_t bufsiz) goto out; } - ret = syncop_readlink (subvol, &loc, &buf, bufsiz); + ret = syncop_readlink (subvol, &loc, &linkval, bufsiz); + 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); + return ret; } @@ -1003,6 +1333,7 @@ glfs_mknod (struct glfs *fs, const char *path, mode_t mode, dev_t dev) struct iatt iatt = {0, }; uuid_t gfid; dict_t *xattr_req = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -1027,8 +1358,10 @@ glfs_mknod (struct glfs *fs, const char *path, mode_t mode, dev_t dev) errno = ENOMEM; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (loc.inode) { errno = EEXIST; @@ -1054,12 +1387,19 @@ glfs_mknod (struct glfs *fs, const char *path, mode_t mode, dev_t dev) goto out; } - ret = syncop_mknod (subvol, &loc, mode, dev, xattr_req); + ret = syncop_mknod (subvol, &loc, mode, dev, xattr_req, &iatt); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_link (&loc, &iatt); out: loc_wipe (&loc); if (xattr_req) - dict_destroy (xattr_req); + dict_unref (xattr_req); + + glfs_subvol_done (fs, subvol); return ret; } @@ -1074,6 +1414,7 @@ glfs_mkdir (struct glfs *fs, const char *path, mode_t mode) struct iatt iatt = {0, }; uuid_t gfid; dict_t *xattr_req = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -1098,8 +1439,10 @@ glfs_mkdir (struct glfs *fs, const char *path, mode_t mode) errno = ENOMEM; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (loc.inode) { errno = EEXIST; @@ -1125,12 +1468,19 @@ glfs_mkdir (struct glfs *fs, const char *path, mode_t mode) goto out; } - ret = syncop_mkdir (subvol, &loc, mode, xattr_req); + ret = syncop_mkdir (subvol, &loc, mode, xattr_req, &iatt); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_link (&loc, &iatt); out: loc_wipe (&loc); if (xattr_req) - dict_destroy (xattr_req); + dict_unref (xattr_req); + + glfs_subvol_done (fs, subvol); return ret; } @@ -1143,6 +1493,7 @@ glfs_unlink (struct glfs *fs, const char *path) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1152,8 +1503,11 @@ glfs_unlink (struct glfs *fs, const char *path) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; @@ -1164,9 +1518,16 @@ glfs_unlink (struct glfs *fs, const char *path) } ret = syncop_unlink (subvol, &loc); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_unlink (&loc); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1178,6 +1539,7 @@ glfs_rmdir (struct glfs *fs, const char *path) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1187,8 +1549,11 @@ glfs_rmdir (struct glfs *fs, const char *path) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; @@ -1199,9 +1564,16 @@ glfs_rmdir (struct glfs *fs, const char *path) } ret = syncop_rmdir (subvol, &loc); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + + if (ret == 0) + ret = glfs_loc_unlink (&loc); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1215,6 +1587,7 @@ glfs_rename (struct glfs *fs, const char *oldpath, const char *newpath) loc_t newloc = {0, }; struct iatt oldiatt = {0, }; struct iatt newiatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1224,31 +1597,56 @@ glfs_rename (struct glfs *fs, const char *oldpath, const char *newpath) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, oldpath, &oldloc, &oldiatt, reval); + + ESTALE_RETRY (ret, errno, reval, &oldloc, retry); - ret = glfs_lresolve (fs, subvol, oldpath, &oldloc, &oldiatt); if (ret) goto out; +retrynew: + ret = glfs_lresolve (fs, subvol, newpath, &newloc, &newiatt, reval); + + ESTALE_RETRY (ret, errno, reval, &newloc, retrynew); - ret = glfs_lresolve (fs, subvol, newpath, &newloc, &newiatt); if (ret && errno != ENOENT && newloc.parent) goto out; - 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; - } + 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 */ ret = syncop_rename (subvol, &oldloc, &newloc); + + 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); out: loc_wipe (&oldloc); loc_wipe (&newloc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1262,6 +1660,7 @@ glfs_link (struct glfs *fs, const char *oldpath, const char *newpath) loc_t newloc = {0, }; struct iatt oldiatt = {0, }; struct iatt newiatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1271,12 +1670,18 @@ glfs_link (struct glfs *fs, const char *oldpath, const char *newpath) errno = EIO; goto out; } +retry: + ret = glfs_lresolve (fs, subvol, oldpath, &oldloc, &oldiatt, reval); + + ESTALE_RETRY (ret, errno, reval, &oldloc, retry); - ret = glfs_lresolve (fs, subvol, oldpath, &oldloc, &oldiatt); if (ret) goto out; +retrynew: + ret = glfs_lresolve (fs, subvol, newpath, &newloc, &newiatt, reval); + + ESTALE_RETRY (ret, errno, reval, &newloc, retrynew); - ret = glfs_lresolve (fs, subvol, newpath, &newloc, &newiatt); if (ret == 0) { ret = -1; errno = EEXIST; @@ -1289,11 +1694,32 @@ glfs_link (struct glfs *fs, const char *oldpath, const char *newpath) 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); + + if (ret == -1 && errno == ESTALE) { + loc_wipe (&oldloc); + loc_wipe (&newloc); + if (reval--) + goto retry; + } + + if (ret == 0) + ret = glfs_loc_link (&newloc, &oldiatt); out: loc_wipe (&oldloc); loc_wipe (&newloc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1306,6 +1732,7 @@ glfs_opendir (struct glfs *fs, const char *path) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1316,12 +1743,16 @@ glfs_opendir (struct glfs *fs, const char *path) goto out; } - glfd = GF_CALLOC (1, sizeof (*glfd), glfs_mt_glfs_fd_t); + 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); - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; @@ -1331,6 +1762,14 @@ glfs_opendir (struct glfs *fs, const char *path) 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; @@ -1339,14 +1778,21 @@ glfs_opendir (struct glfs *fs, const char *path) } ret = syncop_opendir (subvol, &loc, glfd->fd); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); if (ret && glfd) { glfs_fd_destroy (glfd); glfd = NULL; + } else { + fd_bind (glfd->fd); + glfs_fd_bind (glfd); } + glfs_subvol_done (fs, subvol); + return glfd; } @@ -1398,6 +1844,70 @@ glfs_seekdir (struct glfs_fd *fd, long offset) */ } +int +glfs_discard_async (struct glfs_fd *glfd, off_t offset, size_t len, + glfs_io_cbk fn, void *data) +{ + struct glfs_io *gio = NULL; + int ret = 0; + + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); + if (!gio) { + errno = ENOMEM; + return -1; + } + + gio->op = GF_FOP_DISCARD; + gio->glfd = glfd; + gio->offset = offset; + gio->count = len; + gio->fn = fn; + gio->data = data; + + ret = synctask_new (glfs_from_glfd (glfd)->ctx->env, + glfs_io_async_task, glfs_io_async_cbk, + NULL, gio); + + if (ret) { + GF_FREE (gio->iov); + GF_FREE (gio); + } + + return ret; +} + +int +glfs_zerofill_async (struct glfs_fd *glfd, off_t offset, size_t len, + glfs_io_cbk fn, void *data) +{ + struct glfs_io *gio = NULL; + int ret = 0; + + gio = GF_CALLOC (1, sizeof (*gio), glfs_mt_glfs_io_t); + if (!gio) { + errno = ENOMEM; + return -1; + } + + gio->op = GF_FOP_ZEROFILL; + gio->glfd = glfd; + gio->offset = offset; + gio->count = len; + gio->fn = fn; + gio->data = data; + + ret = synctask_new (glfs_from_glfd (glfd)->ctx->env, + glfs_io_async_task, glfs_io_async_cbk, + NULL, gio); + + if (ret) { + GF_FREE (gio->iov); + GF_FREE (gio); + } + + return ret; +} + void gf_dirent_to_dirent (gf_dirent_t *gf_dirent, struct dirent *dirent) @@ -1416,54 +1926,81 @@ gf_dirent_to_dirent (gf_dirent_t *gf_dirent, struct dirent *dirent) dirent->d_namlen = strlen (gf_dirent->d_name); #endif - strncpy (dirent->d_name, gf_dirent->d_name, 256); + strncpy (dirent->d_name, gf_dirent->d_name, GF_NAME_MAX + 1); } int -glfd_entry_refresh (struct glfs_fd *glfd) +glfd_entry_refresh (struct glfs_fd *glfd, int plus) { xlator_t *subvol = NULL; gf_dirent_t entries; gf_dirent_t old; int ret = -1; + fd_t *fd = NULL; - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { + ret = -1; errno = EIO; - return -1; + 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); - ret = syncop_readdir (subvol, glfd->fd, 131072, glfd->offset, - &entries); + if (plus) + ret = syncop_readdirp (subvol, fd, 131072, glfd->offset, + NULL, &entries); + else + ret = syncop_readdir (subvol, fd, 131072, glfd->offset, + &entries); if (ret >= 0) { - /* spurious errno is dangerous for glfd_entry_next() */ - errno = 0; + if (plus) + 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) +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); + ret = glfd_entry_refresh (glfd, plus); if (ret < 0) return NULL; } @@ -1483,22 +2020,57 @@ glfd_entry_next (struct glfs_fd *glfd) } +static 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; +} + + int -glfs_readdir_r (struct glfs_fd *glfd, struct dirent *buf, struct dirent **res) +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; __glfs_entry_fd (glfd); - if (glfd->fd->inode->ia_type != IA_IFDIR) { - ret = -1; - errno = EBADF; - goto out; + errno = 0; + + if (ext) + buf = ext; + else + buf = glfs_readdirbuf_get (glfd); + + if (!buf) { + errno = ENOMEM; + return -1; } - errno = 0; - entry = glfd_entry_next (glfd); + entry = glfd_entry_next (glfd, !!stat); if (errno) ret = -1; @@ -1509,20 +2081,53 @@ glfs_readdir_r (struct glfs_fd *glfd, struct dirent *buf, struct dirent **res) *res = NULL; } - if (entry) + if (entry) { gf_dirent_to_dirent (entry, buf); -out: + if (stat) + glfs_iatt_to_stat (glfd->fs, &entry->d_stat, stat); + } + return ret; } int +glfs_readdir_r (struct glfs_fd *glfd, struct dirent *buf, struct dirent **res) +{ + return glfs_readdirplus_r (glfd, 0, buf, res); +} + + +struct dirent * +glfs_readdirplus (struct glfs_fd *glfd, struct stat *stat) +{ + struct dirent *res = NULL; + int ret = -1; + + ret = glfs_readdirplus_r (glfd, stat, NULL, &res); + if (ret) + return NULL; + + return res; +} + + + +struct dirent * +glfs_readdir (struct glfs_fd *glfd) +{ + return glfs_readdirplus (glfd, NULL); +} + + +int 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; __glfs_entry_fs (fs); @@ -1532,15 +2137,22 @@ glfs_statvfs (struct glfs *fs, const char *path, struct statvfs *buf) errno = EIO; goto out; } +retry: + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); if (ret) goto out; ret = syncop_statfs (subvol, &loc, buf); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1553,6 +2165,7 @@ glfs_setattr (struct glfs *fs, const char *path, struct iatt *iatt, xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt riatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1562,19 +2175,25 @@ glfs_setattr (struct glfs *fs, const char *path, struct iatt *iatt, errno = EIO; goto out; } - +retry: if (follow) - ret = glfs_resolve (fs, subvol, path, &loc, &riatt); + ret = glfs_resolve (fs, subvol, path, &loc, &riatt, reval); else - ret = glfs_lresolve (fs, subvol, path, &loc, &riatt); + ret = glfs_lresolve (fs, subvol, path, &loc, &riatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); if (ret) goto out; ret = syncop_setattr (subvol, &loc, iatt, valid, 0, 0); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1584,18 +2203,31 @@ glfs_fsetattr (struct glfs_fd *glfd, struct iatt *iatt, int valid) { int ret = -1; xlator_t *subvol = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fsetattr (subvol, glfd->fd, iatt, valid, 0, 0); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fsetattr (subvol, fd, iatt, valid, 0, 0); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -1784,6 +2416,7 @@ glfs_getxattr_common (struct glfs *fs, const char *path, const char *name, loc_t loc = {0, }; struct iatt iatt = {0, }; dict_t *xattr = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -1793,15 +2426,21 @@ glfs_getxattr_common (struct glfs *fs, const char *path, const char *name, errno = EIO; goto out; } - +retry: if (follow) - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); else - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + 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); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + if (ret) goto out; @@ -1809,6 +2448,8 @@ glfs_getxattr_common (struct glfs *fs, const char *path, const char *name, out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1836,22 +2477,35 @@ glfs_fgetxattr (struct glfs_fd *glfd, const char *name, void *value, int ret = -1; xlator_t *subvol = NULL; dict_t *xattr = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fgetxattr (subvol, glfd->fd, &xattr, name); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fgetxattr (subvol, fd, &xattr, name); if (ret) goto out; ret = glfs_getxattr_process (value, size, xattr, name); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -1889,6 +2543,7 @@ glfs_listxattr_common (struct glfs *fs, const char *path, void *value, loc_t loc = {0, }; struct iatt iatt = {0, }; dict_t *xattr = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -1899,14 +2554,21 @@ glfs_listxattr_common (struct glfs *fs, const char *path, void *value, goto out; } +retry: if (follow) - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); else - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + 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); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + if (ret) goto out; @@ -1914,6 +2576,8 @@ glfs_listxattr_common (struct glfs *fs, const char *path, void *value, out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -1938,22 +2602,35 @@ 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; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fgetxattr (subvol, glfd->fd, &xattr, NULL); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + ret = syncop_fgetxattr (subvol, fd, &xattr, NULL); if (ret) goto out; ret = glfs_listxattr_process (value, size, xattr); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -1987,6 +2664,7 @@ glfs_setxattr_common (struct glfs *fs, const char *path, const char *name, loc_t loc = {0, }; struct iatt iatt = {0, }; dict_t *xattr = NULL; + int reval = 0; __glfs_entry_fs (fs); @@ -1996,11 +2674,14 @@ glfs_setxattr_common (struct glfs *fs, const char *path, const char *name, errno = EIO; goto out; } - +retry: if (follow) - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); else - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + ret = glfs_lresolve (fs, subvol, path, &loc, &iatt, reval); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + if (ret) goto out; @@ -2012,11 +2693,16 @@ glfs_setxattr_common (struct glfs *fs, const char *path, const char *name, } ret = syncop_setxattr (subvol, &loc, xattr, flags); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + out: loc_wipe (&loc); if (xattr) dict_unref (xattr); + glfs_subvol_done (fs, subvol); + return ret; } @@ -2044,16 +2730,24 @@ glfs_fsetxattr (struct glfs_fd *glfd, const char *name, const void *value, int ret = -1; xlator_t *subvol = NULL; dict_t *xattr = NULL; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (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; + } + xattr = dict_for_key_value (name, value, size); if (!xattr) { ret = -1; @@ -2061,11 +2755,16 @@ glfs_fsetxattr (struct glfs_fd *glfd, const char *name, const void *value, goto out; } - ret = syncop_fsetxattr (subvol, glfd->fd, xattr, flags); + ret = syncop_fsetxattr (subvol, fd, xattr, flags); out: if (xattr) dict_unref (xattr); + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } @@ -2078,6 +2777,7 @@ glfs_removexattr_common (struct glfs *fs, const char *path, const char *name, xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -2087,18 +2787,26 @@ glfs_removexattr_common (struct glfs *fs, const char *path, const char *name, errno = EIO; goto out; } - +retry: if (follow) - ret = glfs_resolve (fs, subvol, path, &loc, &iatt); + ret = glfs_resolve (fs, subvol, path, &loc, &iatt, reval); else - ret = glfs_lresolve (fs, subvol, path, &loc, &iatt); + 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); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); + out: loc_wipe (&loc); + glfs_subvol_done (fs, subvol); + return ret; } @@ -2122,17 +2830,423 @@ glfs_fremovexattr (struct glfs_fd *glfd, const char *name) { int ret = -1; xlator_t *subvol = NULL; + fd_t *fd = NULL; + + __glfs_entry_fd (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); +out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; +} + + +int +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; + + __glfs_entry_fd (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_fallocate (subvol, fd, keep_size, offset, len); +out: + if (fd) + fd_unref(fd); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; +} + + +int +glfs_discard (struct glfs_fd *glfd, off_t offset, size_t len) +{ + int ret = -1; + xlator_t *subvol = NULL; + fd_t *fd = NULL; + + __glfs_entry_fd (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_discard (subvol, fd, offset, len); +out: + if (fd) + fd_unref(fd); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; +} + +int +glfs_zerofill (struct glfs_fd *glfd, off_t offset, size_t len) +{ + int ret = -1; + xlator_t *subvol = NULL; + fd_t *fd = NULL; + + __glfs_entry_fd (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 = syncop_zerofill (subvol, fd, offset, len); +out: + if (fd) + fd_unref(fd); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; +} + +int +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; + + __glfs_entry_fs (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); + + return ret; +} + + +int +glfs_fchdir (struct glfs_fd *glfd) +{ + int ret = -1; + inode_t *inode = NULL; + xlator_t *subvol = NULL; + fd_t *fd = NULL; + + __glfs_entry_fd (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); + + glfs_subvol_done (glfd->fs, subvol); + + return ret; +} + + +char * +glfs_realpath (struct glfs *fs, const char *path, char *resolved_path) +{ + int ret = -1; + char *retpath = NULL; + char *allocpath = NULL; + xlator_t *subvol = NULL; + loc_t loc = {0, }; + struct iatt iatt = {0, }; + int reval = 0; + + __glfs_entry_fs (fs); + + if (resolved_path) + retpath = resolved_path; + else + retpath = allocpath = malloc (PATH_MAX + 1); + + 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) { + strncpy (retpath, loc.path, PATH_MAX); + retpath[PATH_MAX] = 0; + } + +out: + loc_wipe (&loc); + + if (ret == -1) { + if (allocpath) + free (allocpath); + retpath = NULL; + } + + glfs_subvol_done (fs, subvol); + + return retpath; +} + + +char * +glfs_getcwd (struct glfs *fs, char *buf, size_t n) +{ + int ret = -1; + inode_t *inode = NULL; + char *path = NULL; + + __glfs_entry_fs (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); + + 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; +} + + +int +glfs_posix_lock (struct glfs_fd *glfd, int cmd, struct flock *flock) +{ + int ret = -1; + xlator_t *subvol = NULL; + struct gf_flock gf_flock = {0, }; + struct gf_flock saved_flock = {0, }; + fd_t *fd = NULL; __glfs_entry_fd (glfd); - subvol = glfs_fd_subvol (glfd); + subvol = glfs_active_subvol (glfd->fs); if (!subvol) { ret = -1; errno = EIO; goto out; } - ret = syncop_fremovexattr (subvol, glfd->fd, name); + fd = glfs_resolve_fd (glfd->fs, subvol, glfd); + if (!fd) { + ret = -1; + errno = EBADFD; + goto out; + } + + gf_flock_from_flock (&gf_flock, flock); + gf_flock_from_flock (&saved_flock, flock); + ret = syncop_lk (subvol, fd, cmd, &gf_flock); + gf_flock_to_flock (&gf_flock, flock); + + if (ret == 0 && (cmd == F_SETLK || cmd == F_SETLKW)) + fd_lk_insert_and_merge (fd, cmd, &saved_flock); out: + if (fd) + fd_unref (fd); + + glfs_subvol_done (glfd->fs, subvol); + return ret; } + + +struct glfs_fd * +glfs_dup (struct glfs_fd *glfd) +{ + xlator_t *subvol = NULL; + fd_t *fd = NULL; + glfs_fd_t *dupfd = NULL; + struct glfs *fs = NULL; + + __glfs_entry_fd (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); +out: + if (fd) + fd_unref (fd); + if (dupfd) + glfs_fd_bind (dupfd); + + glfs_subvol_done (fs, subvol); + + return dupfd; +} |
