summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--fs/erofs/dir.c5
-rw-r--r--fs/erofs/erofs_fs.h1
-rw-r--r--fs/erofs/inode.c4
-rw-r--r--fs/erofs/internal.h1
4 files changed, 10 insertions, 1 deletions
diff --git a/fs/erofs/dir.c b/fs/erofs/dir.c
index fa3c2d380cc9..2fae209d0274 100644
--- a/fs/erofs/dir.c
+++ b/fs/erofs/dir.c
@@ -90,6 +90,11 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
ofs = 0;
}
erofs_put_metabuf(&buf);
+ if (EROFS_I(dir)->dot_omitted && ctx->pos == dir->i_size) {
+ if (!dir_emit_dot(f, ctx))
+ return 0;
+ ++ctx->pos;
+ }
return err < 0 ? err : 0;
}
diff --git a/fs/erofs/erofs_fs.h b/fs/erofs/erofs_fs.h
index 8330ca3b18d3..791124b3f57c 100644
--- a/fs/erofs/erofs_fs.h
+++ b/fs/erofs/erofs_fs.h
@@ -116,6 +116,7 @@ static inline bool erofs_inode_is_data_compressed(unsigned int datamode)
#define EROFS_I_VERSION_BIT 0
#define EROFS_I_DATALAYOUT_BIT 1
#define EROFS_I_NLINK_1_BIT 4 /* non-directory compact inodes only */
+#define EROFS_I_DOT_OMITTED_BIT 4 /* (directories) omit the `.` dirent */
#define EROFS_I_ALL ((1 << (EROFS_I_NLINK_1_BIT + 1)) - 1)
/* indicate chunk blkbits, thus 'chunksize = blocksize << chunk blkbits' */
diff --git a/fs/erofs/inode.c b/fs/erofs/inode.c
index 6de281312ea7..a0ae0b4f7b01 100644
--- a/fs/erofs/inode.c
+++ b/fs/erofs/inode.c
@@ -136,8 +136,10 @@ static int erofs_read_inode(struct inode *inode)
goto err_out;
}
switch (inode->i_mode & S_IFMT) {
- case S_IFREG:
case S_IFDIR:
+ vi->dot_omitted = (ifmt >> EROFS_I_DOT_OMITTED_BIT) & 1;
+ fallthrough;
+ case S_IFREG:
case S_IFLNK:
vi->startblk = le32_to_cpu(copied.i_u.startblk_lo) |
((u64)le16_to_cpu(copied.i_nb.startblk_hi) << 32);
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 07515a6f2534..91d0b400459c 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -245,6 +245,7 @@ struct erofs_inode {
unsigned char datalayout;
unsigned char inode_isize;
+ bool dot_omitted;
unsigned int xattr_isize;
unsigned int xattr_name_filter;