Skip to content

Commit 782b76d

Browse files
weiny2jankara
authored andcommitted
fs/ext2: Replace kmap() with kmap_local_page()
The k[un]map() calls in ext2_[get|put]_page() are localized to a single thread. kmap_local_page() is more efficient. Replace the kmap/kunmap calls with kmap_local_page()/kunmap_local(). kunmap_local() requires the mapping address so return that address from ext2_get_page() to be used in ext2_put_page(). This works well because many of the callers need the address anyway so it is not bad to return it along with the page. In addition, kmap_local_page()/kunmap_local() require strict nesting rules to be followed. Document the new nesting requirements of ext2_get_page() and ext2_put_page() as well as the relationship between ext2_get_page(), ext2_find_entry(), and ext2_dotdot(). Adjust one ext2_put_page() call site in ext2_rename() to ensure the new nesting requirements are met. Finally, adjust code style for checkpatch. To: Jan Kara <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Ira Weiny <[email protected]> Signed-off-by: Jan Kara <[email protected]>
1 parent e2ebb12 commit 782b76d

File tree

3 files changed

+87
-49
lines changed

3 files changed

+87
-49
lines changed

fs/ext2/dir.c

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -190,13 +190,20 @@ static bool ext2_check_page(struct page *page, int quiet)
190190
return false;
191191
}
192192

193+
/*
194+
* Calls to ext2_get_page()/ext2_put_page() must be nested according to the
195+
* rules documented in kmap_local_page()/kunmap_local().
196+
*
197+
* NOTE: ext2_find_entry() and ext2_dotdot() act as a call to ext2_get_page()
198+
* and should be treated as a call to ext2_get_page() for nesting purposes.
199+
*/
193200
static struct page * ext2_get_page(struct inode *dir, unsigned long n,
194-
int quiet)
201+
int quiet, void **page_addr)
195202
{
196203
struct address_space *mapping = dir->i_mapping;
197204
struct page *page = read_mapping_page(mapping, n, NULL);
198205
if (!IS_ERR(page)) {
199-
kmap(page);
206+
*page_addr = kmap_local_page(page);
200207
if (unlikely(!PageChecked(page))) {
201208
if (PageError(page) || !ext2_check_page(page, quiet))
202209
goto fail;
@@ -205,7 +212,7 @@ static struct page * ext2_get_page(struct inode *dir, unsigned long n,
205212
return page;
206213

207214
fail:
208-
ext2_put_page(page);
215+
ext2_put_page(page, *page_addr);
209216
return ERR_PTR(-EIO);
210217
}
211218

@@ -276,7 +283,7 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
276283
for ( ; n < npages; n++, offset = 0) {
277284
char *kaddr, *limit;
278285
ext2_dirent *de;
279-
struct page *page = ext2_get_page(inode, n, 0);
286+
struct page *page = ext2_get_page(inode, n, 0, (void **)&kaddr);
280287

281288
if (IS_ERR(page)) {
282289
ext2_error(sb, __func__,
@@ -285,7 +292,6 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
285292
ctx->pos += PAGE_SIZE - offset;
286293
return PTR_ERR(page);
287294
}
288-
kaddr = page_address(page);
289295
if (unlikely(need_revalidate)) {
290296
if (offset) {
291297
offset = ext2_validate_entry(kaddr, offset, chunk_mask);
@@ -300,7 +306,7 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
300306
if (de->rec_len == 0) {
301307
ext2_error(sb, __func__,
302308
"zero-length directory entry");
303-
ext2_put_page(page);
309+
ext2_put_page(page, kaddr);
304310
return -EIO;
305311
}
306312
if (de->inode) {
@@ -312,13 +318,13 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
312318
if (!dir_emit(ctx, de->name, de->name_len,
313319
le32_to_cpu(de->inode),
314320
d_type)) {
315-
ext2_put_page(page);
321+
ext2_put_page(page, kaddr);
316322
return 0;
317323
}
318324
}
319325
ctx->pos += ext2_rec_len_from_disk(de->rec_len);
320326
}
321-
ext2_put_page(page);
327+
ext2_put_page(page, kaddr);
322328
}
323329
return 0;
324330
}
@@ -332,9 +338,16 @@ ext2_readdir(struct file *file, struct dir_context *ctx)
332338
* Entry is guaranteed to be valid.
333339
*
334340
* On Success ext2_put_page() should be called on *res_page.
341+
*
342+
* NOTE: Calls to ext2_get_page()/ext2_put_page() must be nested according to
343+
* the rules documented in kmap_local_page()/kunmap_local().
344+
*
345+
* ext2_find_entry() and ext2_dotdot() act as a call to ext2_get_page() and
346+
* should be treated as a call to ext2_get_page() for nesting purposes.
335347
*/
336348
struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
337-
const struct qstr *child, struct page **res_page)
349+
const struct qstr *child, struct page **res_page,
350+
void **res_page_addr)
338351
{
339352
const char *name = child->name;
340353
int namelen = child->len;
@@ -344,38 +357,40 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
344357
struct page *page = NULL;
345358
struct ext2_inode_info *ei = EXT2_I(dir);
346359
ext2_dirent * de;
360+
void *page_addr;
347361

348362
if (npages == 0)
349363
goto out;
350364

351365
/* OFFSET_CACHE */
352366
*res_page = NULL;
367+
*res_page_addr = NULL;
353368

354369
start = ei->i_dir_start_lookup;
355370
if (start >= npages)
356371
start = 0;
357372
n = start;
358373
do {
359374
char *kaddr;
360-
page = ext2_get_page(dir, n, 0);
375+
page = ext2_get_page(dir, n, 0, &page_addr);
361376
if (IS_ERR(page))
362377
return ERR_CAST(page);
363378

364-
kaddr = page_address(page);
379+
kaddr = page_addr;
365380
de = (ext2_dirent *) kaddr;
366381
kaddr += ext2_last_byte(dir, n) - reclen;
367382
while ((char *) de <= kaddr) {
368383
if (de->rec_len == 0) {
369384
ext2_error(dir->i_sb, __func__,
370385
"zero-length directory entry");
371-
ext2_put_page(page);
386+
ext2_put_page(page, page_addr);
372387
goto out;
373388
}
374389
if (ext2_match(namelen, name, de))
375390
goto found;
376391
de = ext2_next_entry(de);
377392
}
378-
ext2_put_page(page);
393+
ext2_put_page(page, page_addr);
379394

380395
if (++n >= npages)
381396
n = 0;
@@ -393,6 +408,7 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
393408

394409
found:
395410
*res_page = page;
411+
*res_page_addr = page_addr;
396412
ei->i_dir_start_lookup = n;
397413
return de;
398414
}
@@ -402,15 +418,24 @@ struct ext2_dir_entry_2 *ext2_find_entry (struct inode *dir,
402418
* (as a parameter - p).
403419
*
404420
* On Success ext2_put_page() should be called on *p.
421+
*
422+
* NOTE: Calls to ext2_get_page()/ext2_put_page() must be nested according to
423+
* the rules documented in kmap_local_page()/kunmap_local().
424+
*
425+
* ext2_find_entry() and ext2_dotdot() act as a call to ext2_get_page() and
426+
* should be treated as a call to ext2_get_page() for nesting purposes.
405427
*/
406-
struct ext2_dir_entry_2 * ext2_dotdot (struct inode *dir, struct page **p)
428+
struct ext2_dir_entry_2 *ext2_dotdot(struct inode *dir, struct page **p,
429+
void **pa)
407430
{
408-
struct page *page = ext2_get_page(dir, 0, 0);
431+
void *page_addr;
432+
struct page *page = ext2_get_page(dir, 0, 0, &page_addr);
409433
ext2_dirent *de = NULL;
410434

411435
if (!IS_ERR(page)) {
412-
de = ext2_next_entry((ext2_dirent *) page_address(page));
436+
de = ext2_next_entry((ext2_dirent *) page_addr);
413437
*p = page;
438+
*pa = page_addr;
414439
}
415440
return de;
416441
}
@@ -419,13 +444,14 @@ int ext2_inode_by_name(struct inode *dir, const struct qstr *child, ino_t *ino)
419444
{
420445
struct ext2_dir_entry_2 *de;
421446
struct page *page;
447+
void *page_addr;
422448

423-
de = ext2_find_entry(dir, child, &page);
449+
de = ext2_find_entry(dir, child, &page, &page_addr);
424450
if (IS_ERR(de))
425451
return PTR_ERR(de);
426452

427453
*ino = le32_to_cpu(de->inode);
428-
ext2_put_page(page);
454+
ext2_put_page(page, page_addr);
429455
return 0;
430456
}
431457

@@ -435,10 +461,11 @@ static int ext2_prepare_chunk(struct page *page, loff_t pos, unsigned len)
435461
}
436462

437463
void ext2_set_link(struct inode *dir, struct ext2_dir_entry_2 *de,
438-
struct page *page, struct inode *inode, int update_times)
464+
struct page *page, void *page_addr, struct inode *inode,
465+
int update_times)
439466
{
440467
loff_t pos = page_offset(page) +
441-
(char *) de - (char *) page_address(page);
468+
(char *) de - (char *) page_addr;
442469
unsigned len = ext2_rec_len_from_disk(de->rec_len);
443470
int err;
444471

@@ -466,10 +493,10 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
466493
unsigned reclen = EXT2_DIR_REC_LEN(namelen);
467494
unsigned short rec_len, name_len;
468495
struct page *page = NULL;
496+
void *page_addr = NULL;
469497
ext2_dirent * de;
470498
unsigned long npages = dir_pages(dir);
471499
unsigned long n;
472-
char *kaddr;
473500
loff_t pos;
474501
int err;
475502

@@ -479,14 +506,15 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
479506
* to protect that region.
480507
*/
481508
for (n = 0; n <= npages; n++) {
509+
char *kaddr;
482510
char *dir_end;
483511

484-
page = ext2_get_page(dir, n, 0);
512+
page = ext2_get_page(dir, n, 0, &page_addr);
485513
err = PTR_ERR(page);
486514
if (IS_ERR(page))
487515
goto out;
488516
lock_page(page);
489-
kaddr = page_address(page);
517+
kaddr = page_addr;
490518
dir_end = kaddr + ext2_last_byte(dir, n);
491519
de = (ext2_dirent *)kaddr;
492520
kaddr += PAGE_SIZE - reclen;
@@ -517,14 +545,14 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
517545
de = (ext2_dirent *) ((char *) de + rec_len);
518546
}
519547
unlock_page(page);
520-
ext2_put_page(page);
548+
ext2_put_page(page, page_addr);
521549
}
522550
BUG();
523551
return -EINVAL;
524552

525553
got_it:
526554
pos = page_offset(page) +
527-
(char*)de - (char*)page_address(page);
555+
(char *)de - (char *)page_addr;
528556
err = ext2_prepare_chunk(page, pos, rec_len);
529557
if (err)
530558
goto out_unlock;
@@ -544,7 +572,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode)
544572
mark_inode_dirty(dir);
545573
/* OFFSET_CACHE */
546574
out_put:
547-
ext2_put_page(page);
575+
ext2_put_page(page, page_addr);
548576
out:
549577
return err;
550578
out_unlock:
@@ -641,21 +669,22 @@ int ext2_make_empty(struct inode *inode, struct inode *parent)
641669
*/
642670
int ext2_empty_dir (struct inode * inode)
643671
{
672+
void *page_addr = NULL;
644673
struct page *page = NULL;
645674
unsigned long i, npages = dir_pages(inode);
646675
int dir_has_error = 0;
647676

648677
for (i = 0; i < npages; i++) {
649678
char *kaddr;
650679
ext2_dirent * de;
651-
page = ext2_get_page(inode, i, dir_has_error);
680+
page = ext2_get_page(inode, i, dir_has_error, &page_addr);
652681

653682
if (IS_ERR(page)) {
654683
dir_has_error = 1;
655684
continue;
656685
}
657686

658-
kaddr = page_address(page);
687+
kaddr = page_addr;
659688
de = (ext2_dirent *)kaddr;
660689
kaddr += ext2_last_byte(inode, i) - EXT2_DIR_REC_LEN(1);
661690

@@ -681,12 +710,12 @@ int ext2_empty_dir (struct inode * inode)
681710
}
682711
de = ext2_next_entry(de);
683712
}
684-
ext2_put_page(page);
713+
ext2_put_page(page, page_addr);
685714
}
686715
return 1;
687716

688717
not_empty:
689-
ext2_put_page(page);
718+
ext2_put_page(page, page_addr);
690719
return 0;
691720
}
692721

fs/ext2/ext2.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -742,14 +742,16 @@ extern int ext2_add_link (struct dentry *, struct inode *);
742742
extern int ext2_inode_by_name(struct inode *dir,
743743
const struct qstr *child, ino_t *ino);
744744
extern int ext2_make_empty(struct inode *, struct inode *);
745-
extern struct ext2_dir_entry_2 * ext2_find_entry (struct inode *,const struct qstr *, struct page **);
745+
extern struct ext2_dir_entry_2 *ext2_find_entry(struct inode *, const struct qstr *,
746+
struct page **, void **res_page_addr);
746747
extern int ext2_delete_entry (struct ext2_dir_entry_2 *, struct page *);
747748
extern int ext2_empty_dir (struct inode *);
748-
extern struct ext2_dir_entry_2 * ext2_dotdot (struct inode *, struct page **);
749-
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, struct inode *, int);
750-
static inline void ext2_put_page(struct page *page)
749+
extern struct ext2_dir_entry_2 *ext2_dotdot(struct inode *dir, struct page **p, void **pa);
750+
extern void ext2_set_link(struct inode *, struct ext2_dir_entry_2 *, struct page *, void *,
751+
struct inode *, int);
752+
static inline void ext2_put_page(struct page *page, void *page_addr)
751753
{
752-
kunmap(page);
754+
kunmap_local(page_addr);
753755
put_page(page);
754756
}
755757

0 commit comments

Comments
 (0)