@@ -1168,22 +1168,23 @@ out_err:
fuse_reply_err(req, saverr);
}
-static struct lo_inode *lo_find(struct lo_data *lo,
- const struct lo_fhandle *fhandle,
- struct stat *st, uint64_t mnt_id)
+/*
+ * get_ids() will be called to get the key for lo->inodes_by_ids if
+ * the lookup by file handle has failed.
+ */
+static struct lo_inode *lo_do_find(struct lo_data *lo,
+ const struct lo_fhandle *fhandle,
+ int (*get_ids)(struct lo_key *, const void *),
+ const void *get_ids_opaque)
{
struct lo_inode *p = NULL;
- struct lo_key ids_key = {
- .ino = st->st_ino,
- .dev = st->st_dev,
- .mnt_id = mnt_id,
- };
+ struct lo_key ids_key;
pthread_mutex_lock(&lo->mutex);
if (fhandle) {
p = g_hash_table_lookup(lo->inodes_by_handle, fhandle);
}
- if (!p) {
+ if (!p && get_ids(&ids_key, get_ids_opaque) == 0) {
p = g_hash_table_lookup(lo->inodes_by_ids, &ids_key);
/*
* When we had to fall back to looking up an inode by its IDs,
@@ -1211,6 +1212,36 @@ static struct lo_inode *lo_find(struct lo_data *lo,
return p;
}
+struct lo_find_get_ids_key_opaque {
+ const struct stat *st;
+ uint64_t mnt_id;
+};
+
+static int lo_find_get_ids_key(struct lo_key *ids_key, const void *opaque)
+{
+ const struct lo_find_get_ids_key_opaque *stat_info = opaque;
+
+ *ids_key = (struct lo_key){
+ .ino = stat_info->st->st_ino,
+ .dev = stat_info->st->st_dev,
+ .mnt_id = stat_info->mnt_id,
+ };
+
+ return 0;
+}
+
+static struct lo_inode *lo_find(struct lo_data *lo,
+ const struct lo_fhandle *fhandle,
+ struct stat *st, uint64_t mnt_id)
+{
+ const struct lo_find_get_ids_key_opaque stat_info = {
+ .st = st,
+ .mnt_id = mnt_id,
+ };
+
+ return lo_do_find(lo, fhandle, lo_find_get_ids_key, &stat_info);
+}
+
/* value_destroy_func for posix_locks GHashTable */
static void posix_locks_value_destroy(gpointer data)
{
@@ -1682,14 +1713,41 @@ out_err:
fuse_reply_err(req, saverr);
}
+struct lookup_name_get_ids_key_opaque {
+ struct lo_data *lo;
+ int parent_fd;
+ const char *name;
+};
+
+static int lookup_name_get_ids_key(struct lo_key *ids_key, const void *opaque)
+{
+ const struct lookup_name_get_ids_key_opaque *stat_params = opaque;
+ uint64_t mnt_id;
+ struct stat attr;
+ int res;
+
+ res = do_statx(stat_params->lo, stat_params->parent_fd, stat_params->name,
+ &attr, AT_SYMLINK_NOFOLLOW, &mnt_id);
+ if (res < 0) {
+ return -errno;
+ }
+
+ *ids_key = (struct lo_key){
+ .ino = attr.st_ino,
+ .dev = attr.st_dev,
+ .mnt_id = mnt_id,
+ };
+
+ return 0;
+}
+
/* Increments nlookup and caller must release refcount using lo_inode_put() */
static struct lo_inode *lookup_name(fuse_req_t req, fuse_ino_t parent,
const char *name)
{
g_auto(TempFd) dir_fd = TEMP_FD_INIT;
int res;
- uint64_t mnt_id;
- struct stat attr;
+ struct lookup_name_get_ids_key_opaque stat_params;
struct lo_fhandle *fh;
struct lo_data *lo = lo_data(req);
struct lo_inode *dir = lo_inode(req, parent);
@@ -1707,13 +1765,14 @@ static struct lo_inode *lookup_name(fuse_req_t req, fuse_ino_t parent,
fh = get_file_handle(lo, dir_fd.fd, name);
/* Ignore errors, this is just an optional key for the lookup */
- res = do_statx(lo, dir_fd.fd, name, &attr, AT_SYMLINK_NOFOLLOW, &mnt_id);
- lo_inode_put(lo, &dir);
- if (res == -1) {
- return NULL;
- }
+ stat_params = (struct lookup_name_get_ids_key_opaque){
+ .lo = lo,
+ .parent_fd = dir_fd.fd,
+ .name = name,
+ };
- inode = lo_find(lo, fh, &attr, mnt_id);
+ inode = lo_do_find(lo, fh, lookup_name_get_ids_key, &stat_params);
+ lo_inode_put(lo, &dir);
g_free(fh);
return inode;