Skip to content

Commit aab4ed5

Browse files
committed
Merge tag 'erofs-for-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs
Pull erofs updates from Gao Xiang: "In this cycle, we continue converting to use meta buffers for all remaining uncompressed paths to prepare for the upcoming subpage, folio and fscache features. We also fixed a double-free issue when sysfs initialization fails, which was reported by syzbot. Besides, in order for the userspace to control per-file timestamp easier, we now switch to record mtime instead of ctime with a compatible feature marked. And there are also some code cleanups and documentation update as usual. Summary: - Avoid using page structure directly for all uncompressed paths - Fix a double-free issue when sysfs initialization fails - Complete DAX description for erofs - Use mtime instead since there's no (easy) way for users to control ctime - Several code cleanups" * tag 'erofs-for-5.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs: erofs: rename ctime to mtime erofs: use meta buffers for inode lookup erofs: use meta buffers for reading directories fs: erofs: add sanity check for kobject in erofs_unregister_sysfs erofs: refine managed inode stuffs erofs: clean up z_erofs_extent_lookback erofs: silence warnings related to impossible m_plen Documentation/filesystem/dax: update DAX description on erofs erofs: clean up preload_compressed_pages() erofs: get rid of `struct z_erofs_collector' erofs: use meta buffers for erofs_read_superblock()
2 parents 881b568 + a1108dc commit aab4ed5

File tree

12 files changed

+189
-201
lines changed

12 files changed

+189
-201
lines changed

Documentation/filesystems/dax.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,11 @@ on it as usual. The `DAX` code currently only supports files with a block
2323
size equal to your kernel's `PAGE_SIZE`, so you may need to specify a block
2424
size when creating the filesystem.
2525

26-
Currently 4 filesystems support `DAX`: ext2, ext4, xfs and virtiofs.
26+
Currently 5 filesystems support `DAX`: ext2, ext4, xfs, virtiofs and erofs.
2727
Enabling `DAX` on them is different.
2828

29-
Enabling DAX on ext2
30-
--------------------
29+
Enabling DAX on ext2 and erofs
30+
------------------------------
3131

3232
When mounting the filesystem, use the ``-o dax`` option on the command line or
3333
add 'dax' to the options in ``/etc/fstab``. This works to enable `DAX` on all files

Documentation/filesystems/erofs.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ Here is the main features of EROFS:
4040
Inode metadata size 32 bytes 64 bytes
4141
Max file size 4 GB 16 EB (also limited by max. vol size)
4242
Max uids/gids 65536 4294967296
43-
File change time no yes (64 + 32-bit timestamp)
43+
Per-inode timestamp no yes (64 + 32-bit timestamp)
4444
Max hardlinks 65536 4294967296
4545
Metadata reserved 4 bytes 14 bytes
4646
===================== ============ =====================================

fs/erofs/data.c

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,10 @@ void erofs_put_metabuf(struct erofs_buf *buf)
2828
buf->page = NULL;
2929
}
3030

31-
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
32-
erofs_blk_t blkaddr, enum erofs_kmap_type type)
31+
void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
32+
erofs_blk_t blkaddr, enum erofs_kmap_type type)
3333
{
34-
struct address_space *const mapping = sb->s_bdev->bd_inode->i_mapping;
34+
struct address_space *const mapping = inode->i_mapping;
3535
erofs_off_t offset = blknr_to_addr(blkaddr);
3636
pgoff_t index = offset >> PAGE_SHIFT;
3737
struct page *page = buf->page;
@@ -60,6 +60,12 @@ void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
6060
return buf->base + (offset & ~PAGE_MASK);
6161
}
6262

63+
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
64+
erofs_blk_t blkaddr, enum erofs_kmap_type type)
65+
{
66+
return erofs_bread(buf, sb->s_bdev->bd_inode, blkaddr, type);
67+
}
68+
6369
static int erofs_map_blocks_flatmode(struct inode *inode,
6470
struct erofs_map_blocks *map,
6571
int flags)

fs/erofs/dir.c

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (C) 2017-2018 HUAWEI, Inc.
44
* https://www.huawei.com/
5+
* Copyright (C) 2022, Alibaba Cloud
56
*/
67
#include "internal.h"
78

@@ -67,34 +68,27 @@ static int erofs_fill_dentries(struct inode *dir, struct dir_context *ctx,
6768
static int erofs_readdir(struct file *f, struct dir_context *ctx)
6869
{
6970
struct inode *dir = file_inode(f);
70-
struct address_space *mapping = dir->i_mapping;
71+
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
7172
const size_t dirsize = i_size_read(dir);
7273
unsigned int i = ctx->pos / EROFS_BLKSIZ;
7374
unsigned int ofs = ctx->pos % EROFS_BLKSIZ;
7475
int err = 0;
7576
bool initial = true;
7677

7778
while (ctx->pos < dirsize) {
78-
struct page *dentry_page;
7979
struct erofs_dirent *de;
8080
unsigned int nameoff, maxsize;
8181

82-
dentry_page = read_mapping_page(mapping, i, NULL);
83-
if (dentry_page == ERR_PTR(-ENOMEM)) {
84-
err = -ENOMEM;
85-
break;
86-
} else if (IS_ERR(dentry_page)) {
82+
de = erofs_bread(&buf, dir, i, EROFS_KMAP);
83+
if (IS_ERR(de)) {
8784
erofs_err(dir->i_sb,
8885
"fail to readdir of logical block %u of nid %llu",
8986
i, EROFS_I(dir)->nid);
90-
err = -EFSCORRUPTED;
87+
err = PTR_ERR(de);
9188
break;
9289
}
9390

94-
de = (struct erofs_dirent *)kmap(dentry_page);
95-
9691
nameoff = le16_to_cpu(de->nameoff);
97-
9892
if (nameoff < sizeof(struct erofs_dirent) ||
9993
nameoff >= PAGE_SIZE) {
10094
erofs_err(dir->i_sb,
@@ -119,17 +113,14 @@ static int erofs_readdir(struct file *f, struct dir_context *ctx)
119113
err = erofs_fill_dentries(dir, ctx, de, &ofs,
120114
nameoff, maxsize);
121115
skip_this:
122-
kunmap(dentry_page);
123-
124-
put_page(dentry_page);
125-
126116
ctx->pos = blknr_to_addr(i) + ofs;
127117

128118
if (err)
129119
break;
130120
++i;
131121
ofs = 0;
132122
}
123+
erofs_put_metabuf(&buf);
133124
return err < 0 ? err : 0;
134125
}
135126

fs/erofs/erofs_fs.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#define EROFS_SUPER_OFFSET 1024
1313

1414
#define EROFS_FEATURE_COMPAT_SB_CHKSUM 0x00000001
15+
#define EROFS_FEATURE_COMPAT_MTIME 0x00000002
1516

1617
/*
1718
* Any bits that aren't in EROFS_ALL_FEATURE_INCOMPAT should
@@ -186,8 +187,8 @@ struct erofs_inode_extended {
186187

187188
__le32 i_uid;
188189
__le32 i_gid;
189-
__le64 i_ctime;
190-
__le32 i_ctime_nsec;
190+
__le64 i_mtime;
191+
__le32 i_mtime_nsec;
191192
__le32 i_nlink;
192193
__u8 i_reserved2[16];
193194
};

fs/erofs/inode.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,8 +113,8 @@ static void *erofs_read_inode(struct erofs_buf *buf,
113113
set_nlink(inode, le32_to_cpu(die->i_nlink));
114114

115115
/* extended inode has its own timestamp */
116-
inode->i_ctime.tv_sec = le64_to_cpu(die->i_ctime);
117-
inode->i_ctime.tv_nsec = le32_to_cpu(die->i_ctime_nsec);
116+
inode->i_ctime.tv_sec = le64_to_cpu(die->i_mtime);
117+
inode->i_ctime.tv_nsec = le32_to_cpu(die->i_mtime_nsec);
118118

119119
inode->i_size = le64_to_cpu(die->i_size);
120120

fs/erofs/internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,8 @@ struct erofs_map_dev {
479479
extern const struct file_operations erofs_file_fops;
480480
void erofs_unmap_metabuf(struct erofs_buf *buf);
481481
void erofs_put_metabuf(struct erofs_buf *buf);
482+
void *erofs_bread(struct erofs_buf *buf, struct inode *inode,
483+
erofs_blk_t blkaddr, enum erofs_kmap_type type);
482484
void *erofs_read_metabuf(struct erofs_buf *buf, struct super_block *sb,
483485
erofs_blk_t blkaddr, enum erofs_kmap_type type);
484486
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *dev);

fs/erofs/namei.c

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/*
33
* Copyright (C) 2017-2018 HUAWEI, Inc.
44
* https://www.huawei.com/
5+
* Copyright (C) 2022, Alibaba Cloud
56
*/
67
#include "xattr.h"
78

@@ -86,25 +87,26 @@ static struct erofs_dirent *find_target_dirent(struct erofs_qstr *name,
8687
return ERR_PTR(-ENOENT);
8788
}
8889

89-
static struct page *find_target_block_classic(struct inode *dir,
90-
struct erofs_qstr *name,
91-
int *_ndirents)
90+
static void *find_target_block_classic(struct erofs_buf *target,
91+
struct inode *dir,
92+
struct erofs_qstr *name,
93+
int *_ndirents)
9294
{
9395
unsigned int startprfx, endprfx;
9496
int head, back;
95-
struct address_space *const mapping = dir->i_mapping;
96-
struct page *candidate = ERR_PTR(-ENOENT);
97+
void *candidate = ERR_PTR(-ENOENT);
9798

9899
startprfx = endprfx = 0;
99100
head = 0;
100101
back = erofs_inode_datablocks(dir) - 1;
101102

102103
while (head <= back) {
103104
const int mid = head + (back - head) / 2;
104-
struct page *page = read_mapping_page(mapping, mid, NULL);
105+
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
106+
struct erofs_dirent *de;
105107

106-
if (!IS_ERR(page)) {
107-
struct erofs_dirent *de = kmap_atomic(page);
108+
de = erofs_bread(&buf, dir, mid, EROFS_KMAP);
109+
if (!IS_ERR(de)) {
108110
const int nameoff = nameoff_from_disk(de->nameoff,
109111
EROFS_BLKSIZ);
110112
const int ndirents = nameoff / sizeof(*de);
@@ -113,13 +115,12 @@ static struct page *find_target_block_classic(struct inode *dir,
113115
struct erofs_qstr dname;
114116

115117
if (!ndirents) {
116-
kunmap_atomic(de);
117-
put_page(page);
118+
erofs_put_metabuf(&buf);
118119
erofs_err(dir->i_sb,
119120
"corrupted dir block %d @ nid %llu",
120121
mid, EROFS_I(dir)->nid);
121122
DBG_BUGON(1);
122-
page = ERR_PTR(-EFSCORRUPTED);
123+
de = ERR_PTR(-EFSCORRUPTED);
123124
goto out;
124125
}
125126

@@ -135,7 +136,6 @@ static struct page *find_target_block_classic(struct inode *dir,
135136

136137
/* string comparison without already matched prefix */
137138
diff = erofs_dirnamecmp(name, &dname, &matched);
138-
kunmap_atomic(de);
139139

140140
if (!diff) {
141141
*_ndirents = 0;
@@ -145,11 +145,12 @@ static struct page *find_target_block_classic(struct inode *dir,
145145
startprfx = matched;
146146

147147
if (!IS_ERR(candidate))
148-
put_page(candidate);
149-
candidate = page;
148+
erofs_put_metabuf(target);
149+
*target = buf;
150+
candidate = de;
150151
*_ndirents = ndirents;
151152
} else {
152-
put_page(page);
153+
erofs_put_metabuf(&buf);
153154

154155
back = mid - 1;
155156
endprfx = matched;
@@ -158,8 +159,8 @@ static struct page *find_target_block_classic(struct inode *dir,
158159
}
159160
out: /* free if the candidate is valid */
160161
if (!IS_ERR(candidate))
161-
put_page(candidate);
162-
return page;
162+
erofs_put_metabuf(target);
163+
return de;
163164
}
164165
return candidate;
165166
}
@@ -169,8 +170,7 @@ int erofs_namei(struct inode *dir,
169170
erofs_nid_t *nid, unsigned int *d_type)
170171
{
171172
int ndirents;
172-
struct page *page;
173-
void *data;
173+
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
174174
struct erofs_dirent *de;
175175
struct erofs_qstr qn;
176176

@@ -181,26 +181,20 @@ int erofs_namei(struct inode *dir,
181181
qn.end = name->name + name->len;
182182

183183
ndirents = 0;
184-
page = find_target_block_classic(dir, &qn, &ndirents);
185184

186-
if (IS_ERR(page))
187-
return PTR_ERR(page);
185+
de = find_target_block_classic(&buf, dir, &qn, &ndirents);
186+
if (IS_ERR(de))
187+
return PTR_ERR(de);
188188

189-
data = kmap_atomic(page);
190189
/* the target page has been mapped */
191190
if (ndirents)
192-
de = find_target_dirent(&qn, data, EROFS_BLKSIZ, ndirents);
193-
else
194-
de = (struct erofs_dirent *)data;
191+
de = find_target_dirent(&qn, (u8 *)de, EROFS_BLKSIZ, ndirents);
195192

196193
if (!IS_ERR(de)) {
197194
*nid = le64_to_cpu(de->nid);
198195
*d_type = de->file_type;
199196
}
200-
201-
kunmap_atomic(data);
202-
put_page(page);
203-
197+
erofs_put_metabuf(&buf);
204198
return PTR_ERR_OR_ZERO(de);
205199
}
206200

fs/erofs/super.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,21 +281,19 @@ static int erofs_init_devices(struct super_block *sb,
281281
static int erofs_read_superblock(struct super_block *sb)
282282
{
283283
struct erofs_sb_info *sbi;
284-
struct page *page;
284+
struct erofs_buf buf = __EROFS_BUF_INITIALIZER;
285285
struct erofs_super_block *dsb;
286286
unsigned int blkszbits;
287287
void *data;
288288
int ret;
289289

290-
page = read_mapping_page(sb->s_bdev->bd_inode->i_mapping, 0, NULL);
291-
if (IS_ERR(page)) {
290+
data = erofs_read_metabuf(&buf, sb, 0, EROFS_KMAP);
291+
if (IS_ERR(data)) {
292292
erofs_err(sb, "cannot read erofs superblock");
293-
return PTR_ERR(page);
293+
return PTR_ERR(data);
294294
}
295295

296296
sbi = EROFS_SB(sb);
297-
298-
data = kmap(page);
299297
dsb = (struct erofs_super_block *)(data + EROFS_SUPER_OFFSET);
300298

301299
ret = -EINVAL;
@@ -365,8 +363,7 @@ static int erofs_read_superblock(struct super_block *sb)
365363
if (erofs_sb_has_ztailpacking(sbi))
366364
erofs_info(sb, "EXPERIMENTAL compressed inline data feature in use. Use at your own risk!");
367365
out:
368-
kunmap(page);
369-
put_page(page);
366+
erofs_put_metabuf(&buf);
370367
return ret;
371368
}
372369

@@ -535,6 +532,11 @@ static int erofs_managed_cache_releasepage(struct page *page, gfp_t gfp_mask)
535532
return ret;
536533
}
537534

535+
/*
536+
* It will be called only on inode eviction. In case that there are still some
537+
* decompression requests in progress, wait with rescheduling for a bit here.
538+
* We could introduce an extra locking instead but it seems unnecessary.
539+
*/
538540
static void erofs_managed_cache_invalidatepage(struct page *page,
539541
unsigned int offset,
540542
unsigned int length)
@@ -568,8 +570,7 @@ static int erofs_init_managed_cache(struct super_block *sb)
568570
inode->i_size = OFFSET_MAX;
569571

570572
inode->i_mapping->a_ops = &managed_cache_aops;
571-
mapping_set_gfp_mask(inode->i_mapping,
572-
GFP_NOFS | __GFP_HIGHMEM | __GFP_MOVABLE);
573+
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
573574
sbi->managed_cache = inode;
574575
return 0;
575576
}

fs/erofs/sysfs.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,11 @@ void erofs_unregister_sysfs(struct super_block *sb)
221221
{
222222
struct erofs_sb_info *sbi = EROFS_SB(sb);
223223

224-
kobject_del(&sbi->s_kobj);
225-
kobject_put(&sbi->s_kobj);
226-
wait_for_completion(&sbi->s_kobj_unregister);
224+
if (sbi->s_kobj.state_in_sysfs) {
225+
kobject_del(&sbi->s_kobj);
226+
kobject_put(&sbi->s_kobj);
227+
wait_for_completion(&sbi->s_kobj_unregister);
228+
}
227229
}
228230

229231
int __init erofs_init_sysfs(void)

0 commit comments

Comments
 (0)