diff options
author | Anand Avati <avati@redhat.com> | 2013-04-27 21:40:19 -0700 |
---|---|---|
committer | Vijay Bellur <vbellur@redhat.com> | 2013-05-25 11:35:06 -0700 |
commit | e9ac9d4d5c1c3e9f3f0b5c80a881d67a675eccef (patch) | |
tree | 362ad5dce509fe2a92ea622b3736ed23c4e11161 /api | |
parent | 4f63b631dce4cb97525ee13fab0b2a789bcf6b15 (diff) |
gfapi: optimistic resolution with ESTALE detection
Enhance the path resolver to be optimistic. Instead of performing
a wasteful ->lookup() fop for every component in every API call,
build in speculation logic to consider the previous resolution
result temporarily, and if it results in ESTALE either later in
the path resolution or in the FOP, then retry resolution with
->lookup() at every level and retry the FOP.
This is the same optimistic resolution/retry logic Linux kernel
resolver is proposing to use.
Change-Id: Iecbc25248754caf0915cd7205910563ff88ce5e7
BUG: 953694
Signed-off-by: Anand Avati <avati@redhat.com>
Reviewed-on: http://review.gluster.org/4928
Tested-by: Gluster Build System <jenkins@build.gluster.com>
Reviewed-by: Vijay Bellur <vbellur@redhat.com>
Diffstat (limited to 'api')
-rw-r--r-- | api/src/glfs-fops.c | 237 | ||||
-rw-r--r-- | api/src/glfs-internal.h | 4 | ||||
-rw-r--r-- | api/src/glfs-resolve.c | 67 |
3 files changed, 248 insertions, 60 deletions
diff --git a/api/src/glfs-fops.c b/api/src/glfs-fops.c index 61c524eaf..fe230e6a9 100644 --- a/api/src/glfs-fops.c +++ b/api/src/glfs-fops.c @@ -14,6 +14,17 @@ #include "syncop.h" #include "glfs.h" +#define DEFAULT_REVAL_COUNT 1 + +#define ESTALE_RETRY(ret,errno,reval,loc,label) do { \ + if (ret == -1 && errno == ESTALE) { \ + if (reval < DEFAULT_REVAL_COUNT) { \ + reval++; \ + loc_wipe (loc); \ + goto label; \ + } \ + } \ + } while (0) struct glfs_fd * glfs_open (struct glfs *fs, const char *path, int flags) @@ -23,6 +34,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); @@ -37,7 +49,11 @@ glfs_open (struct glfs *fs, const char *path, int flags) 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 +69,11 @@ glfs_open (struct glfs *fs, const char *path, int flags) goto out; } + if (glfd->fd) { + fd_unref (glfd->fd); + glfd->fd = NULL; + } + glfd->fd = fd_create (loc.inode, getpid()); if (!glfd->fd) { ret = -1; @@ -61,6 +82,8 @@ 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); @@ -98,6 +121,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,8 +131,10 @@ 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); @@ -126,6 +152,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,8 +162,10 @@ 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); @@ -182,6 +211,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); @@ -216,7 +246,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 +290,11 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) } } + if (glfd->fd) { + fd_unref (glfd->fd); + glfd->fd = NULL; + } + glfd->fd = fd_create (loc.inode, getpid()); if (!glfd->fd) { ret = -1; @@ -264,6 +303,8 @@ glfs_creat (struct glfs *fs, const char *path, int flags, mode_t mode) } ret = syncop_create (subvol, &loc, flags, mode, glfd->fd, xattr_req); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -866,6 +907,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,12 +917,17 @@ 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); @@ -897,6 +944,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 +969,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; @@ -949,6 +999,8 @@ glfs_symlink (struct glfs *fs, const char *data, const char *path) } ret = syncop_symlink (subvol, &loc, data, xattr_req); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -966,6 +1018,7 @@ 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; __glfs_entry_fs (fs); @@ -975,8 +1028,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; @@ -987,6 +1043,8 @@ glfs_readlink (struct glfs *fs, const char *path, char *buf, size_t bufsiz) } ret = syncop_readlink (subvol, &loc, &buf, bufsiz); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -1003,6 +1061,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 +1086,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; @@ -1055,6 +1116,8 @@ glfs_mknod (struct glfs *fs, const char *path, mode_t mode, dev_t dev) } ret = syncop_mknod (subvol, &loc, mode, dev, xattr_req); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -1074,6 +1137,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 +1162,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; @@ -1126,6 +1192,8 @@ glfs_mkdir (struct glfs *fs, const char *path, mode_t mode) } ret = syncop_mkdir (subvol, &loc, mode, xattr_req); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -1143,6 +1211,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 +1221,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,6 +1236,8 @@ glfs_unlink (struct glfs *fs, const char *path) } ret = syncop_unlink (subvol, &loc); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -1178,6 +1252,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 +1262,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,6 +1277,8 @@ glfs_rmdir (struct glfs *fs, const char *path) } ret = syncop_rmdir (subvol, &loc); + + ESTALE_RETRY (ret, errno, reval, &loc, retry); out: loc_wipe (&loc); @@ -1215,6 +1295,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,12 +1305,18 @@ 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; @@ -1245,6 +1332,15 @@ glfs_rename (struct glfs *fs, const char *oldpath, const char *newpath) /* 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; + } + } out: loc_wipe (&oldloc); loc_wipe (&newloc); @@ -1262,6 +1358,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 +1368,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; @@ -1290,6 +1393,14 @@ glfs_link (struct glfs *fs, const char *oldpath, const char *newpath) } ret = syncop_link (subvol, &oldloc, &newloc); + + if (ret == -1 && errno == ESTALE) { + loc_wipe (&oldloc); + loc_wipe (&newloc); + if (reval--) + goto retry; + } + out: loc_wipe (&oldloc); loc_wipe (&newloc); @@ -1306,6 +1417,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); @@ -1319,9 +1431,13 @@ glfs_opendir (struct glfs *fs, const char *path) 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 +1447,11 @@ glfs_opendir (struct glfs *fs, const char *path) goto out; } + if (glfd->fd) { + fd_unref (glfd->fd); + glfd->fd = NULL; + } + glfd->fd = fd_create (loc.inode, getpid()); if (!glfd->fd) { ret = -1; @@ -1339,6 +1460,8 @@ 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); @@ -1538,6 +1661,7 @@ glfs_statvfs (struct glfs *fs, const char *path, struct statvfs *buf) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -1547,12 +1671,17 @@ 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); @@ -1568,6 +1697,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); @@ -1577,16 +1707,20 @@ 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); @@ -1799,6 +1933,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); @@ -1808,15 +1943,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; @@ -1904,6 +2045,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); @@ -1914,14 +2056,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; @@ -2002,6 +2151,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); @@ -2011,11 +2161,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; @@ -2027,6 +2180,9 @@ 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) @@ -2093,6 +2249,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); @@ -2102,15 +2259,21 @@ 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); @@ -2172,6 +2335,7 @@ glfs_chdir (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); @@ -2181,8 +2345,11 @@ glfs_chdir (struct glfs *fs, const char *path) 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; @@ -2233,6 +2400,7 @@ glfs_realpath (struct glfs *fs, const char *path, char *resolved_path) xlator_t *subvol = NULL; loc_t loc = {0, }; struct iatt iatt = {0, }; + int reval = 0; __glfs_entry_fs (fs); @@ -2253,8 +2421,11 @@ glfs_realpath (struct glfs *fs, const char *path, char *resolved_path) 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; diff --git a/api/src/glfs-internal.h b/api/src/glfs-internal.h index 082b8fa5c..7c622637d 100644 --- a/api/src/glfs-internal.h +++ b/api/src/glfs-internal.h @@ -57,9 +57,9 @@ int glfs_mgmt_init (struct glfs *fs); void glfs_init_done (struct glfs *fs, int ret); int glfs_process_volfp (struct glfs *fs, FILE *fp); int glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc, - struct iatt *iatt); + struct iatt *iatt, int reval); int glfs_lresolve (struct glfs *fs, xlator_t *subvol, const char *path, loc_t *loc, - struct iatt *iatt); + struct iatt *iatt, int reval); void glfs_first_lookup (xlator_t *subvol); static inline void diff --git a/api/src/glfs-resolve.c b/api/src/glfs-resolve.c index 17cf19d0f..07fc1b7c5 100644 --- a/api/src/glfs-resolve.c +++ b/api/src/glfs-resolve.c @@ -136,7 +136,8 @@ out: inode_t * glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, - const char *component, struct iatt *iatt) + const char *component, struct iatt *iatt, + int force_lookup) { loc_t loc = {0, }; inode_t *inode = NULL; @@ -152,17 +153,6 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, loc.parent = inode_ref (parent); uuid_copy (loc.pargfid, parent->gfid); - xattr_req = dict_new (); - if (!xattr_req) { - errno = ENOMEM; - goto out; - } - - ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16); - if (ret) { - errno = ENOMEM; - goto out; - } if (strcmp (component, ".") == 0) loc.inode = inode_ref (parent); @@ -174,6 +164,12 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, if (loc.inode) { uuid_copy (loc.gfid, loc.inode->gfid); reval = 1; + + if (!force_lookup) { + inode = inode_ref (loc.inode); + ciatt.ia_type = inode->ia_type; + goto found; + } } else { uuid_generate (gfid); loc.inode = inode_new (parent->table); @@ -182,20 +178,35 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, if (!loc.inode) goto out; - glret = glfs_loc_touchup (&loc); if (glret < 0) { ret = -1; goto out; } - ret = syncop_lookup (subvol, &loc, xattr_req, &ciatt, NULL, NULL); + ret = syncop_lookup (subvol, &loc, NULL, &ciatt, NULL, NULL); if (ret && reval) { inode_unref (loc.inode); loc.inode = inode_new (parent->table); - if (!loc.inode) + if (!loc.inode) { + errno = ENOMEM; goto out; + } + + xattr_req = dict_new (); + if (!xattr_req) { + errno = ENOMEM; + goto out; + } + uuid_generate (gfid); + + ret = dict_set_static_bin (xattr_req, "gfid-req", gfid, 16); + if (ret) { + errno = ENOMEM; + goto out; + } + ret = syncop_lookup (subvol, &loc, xattr_req, &ciatt, NULL, NULL); } @@ -203,6 +214,7 @@ glfs_resolve_component (struct glfs *fs, xlator_t *subvol, inode_t *parent, goto out; inode = inode_link (loc.inode, loc.parent, component, &ciatt); +found: if (inode) inode_lookup (inode); if (iatt) @@ -220,7 +232,7 @@ out: int glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, const char *origpath, loc_t *loc, struct iatt *iatt, - int follow) + int follow, int reval) { inode_t *inode = NULL; inode_t *parent = NULL; @@ -260,7 +272,12 @@ glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, parent = inode; inode = glfs_resolve_component (fs, subvol, parent, - component, &ciatt); + component, &ciatt, + /* force hard lookup on the last + component, as the caller + wants proper iatt filled + */ + (reval || !next_component)); if (!inode) break; @@ -287,7 +304,7 @@ glfs_resolve_at (struct glfs *fs, xlator_t *subvol, inode_t *at, /* always recurisvely follow while following symlink */ - 1); + 1, reval); if (ret == 0) inode = inode_ref (sym_loc.inode); loc_wipe (&sym_loc); @@ -344,16 +361,16 @@ out: int glfs_resolve_path (struct glfs *fs, xlator_t *subvol, const char *origpath, - loc_t *loc, struct iatt *iatt, int follow) + loc_t *loc, struct iatt *iatt, int follow, int reval) { int ret = -1; if (origpath[0] == '/') ret = glfs_resolve_at (fs, subvol, NULL, origpath, loc, iatt, - follow); + follow, reval); else ret = glfs_resolve_at (fs, subvol, fs->cwd, origpath, loc, iatt, - follow); + follow, reval); return ret; } @@ -361,11 +378,11 @@ glfs_resolve_path (struct glfs *fs, xlator_t *subvol, const char *origpath, int glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, - loc_t *loc, struct iatt *iatt) + loc_t *loc, struct iatt *iatt, int reval) { int ret = -1; - ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 1); + ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 1, reval); return ret; } @@ -373,11 +390,11 @@ glfs_resolve (struct glfs *fs, xlator_t *subvol, const char *origpath, int glfs_lresolve (struct glfs *fs, xlator_t *subvol, const char *origpath, - loc_t *loc, struct iatt *iatt) + loc_t *loc, struct iatt *iatt, int reval) { int ret = -1; - ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 0); + ret = glfs_resolve_path (fs, subvol, origpath, loc, iatt, 0, reval); return ret; } |