fs/v9fs: Set st_ino and d_ino from the qid path.

stat() returned st_ino 0 and readdir() returned d_ino 0 for every file
on a v9fs mount, although 9P identifies each file by its qid path.
Programs that skip directory entries with d_ino 0, or that compare
st_dev and st_ino to find out if two paths are the same file, do not
work on such a mount.

Fold the 64-bit qid path into ino_t the same way for both, so that they
match, and never return 0.

Assisted-by: Claude Code:claude-opus-5-5
Signed-off-by: Marco Casaroli <marco.casaroli@gmail.com>
This commit is contained in:
Marco Casaroli 2026-10-08 21:57:34 +02:00 • committed by Alan C. Assis
parent 3619c557a6
commit 9eb725fe9b

View file

@ -378,6 +378,24 @@ struct v9fs_fid_s
* Private Functions
****************************************************************************/
/****************************************************************************
* Name: v9fs_qid_ino
*
* Description:
* Return the file serial number (st_ino, d_ino) for a qid path. The
* qid path identifies the file on the server; it is folded into ino_t
* and never 0, because programs such as GNU make skip directory entries
* with d_ino 0.
*
****************************************************************************/
static inline ino_t v9fs_qid_ino(uint64_t path)
{
ino_t ino = (ino_t)(path ^ (path >> 32));
return ino != 0 ? ino : 1;
}
/****************************************************************************
* v9fs_get_tagid
****************************************************************************/
@ -814,6 +832,7 @@ int v9fs_client_stat(FAR struct v9fs_client_s *client, uint32_t fid,
return ret;
}
buf->st_ino = v9fs_qid_ino(response.qid.path);
buf->st_mode = response.mode;
buf->st_uid = response.uid;
buf->st_gid = response.gid;
@ -1016,6 +1035,7 @@ ssize_t v9fs_client_convertdir(FAR const uint8_t *buffer, size_t bufsize,
off_t head, FAR off_t *offset,
FAR struct dirent *entry)
{
uint64_t qidpath;
uint64_t off;
uint16_t name_len;
off_t next = head;
@ -1030,8 +1050,13 @@ ssize_t v9fs_client_convertdir(FAR const uint8_t *buffer, size_t bufsize,
return -EIO;
}
/* Skip the qid part (13 Bytes) */
/* The qid part (13 Bytes): type, version, then the path that identifies
* the file.
*/
memcpy(&qidpath, buffer + next + V9FS_BIT8SZ + V9FS_BIT32SZ,
sizeof(uint64_t));
entry->d_ino = v9fs_qid_ino(qidpath);
next += V9FS_QIDSZ;
/* Read the offset (8 bytes) */