Message ID | 20230921200746.3303942-7-willy@infradead.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [01/10] highmem: Add folio_release_kmap() | expand |
On Thu 21-09-23 21:07:44, Matthew Wilcox (Oracle) wrote: > If the block size is > PAGE_SIZE, we need to calculate these offsets > relative to the start of the folio, not the page. > > Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> So I had a fresh look at the patches and I like them so I'll take them into my tree for the merge window. Just this patch has somewhat surprising subject and changelog - I guess it should be standard "convert to folios" kind of thing, shouldn't it? Because a lot of dir code is not prepared for "large block size" so it is strange to speak about it in ext2_delete_entry(). I can fix it up on commit. Honza > --- > fs/ext2/dir.c | 30 +++++++++++++++++------------- > 1 file changed, 17 insertions(+), 13 deletions(-) > > diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c > index 2fc910e99234..7e75cfaa709c 100644 > --- a/fs/ext2/dir.c > +++ b/fs/ext2/dir.c > @@ -586,16 +586,20 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) > */ > int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page) > { > - struct inode *inode = page->mapping->host; > - char *kaddr = (char *)((unsigned long)dir & PAGE_MASK); > - unsigned from = offset_in_page(dir) & ~(ext2_chunk_size(inode)-1); > - unsigned to = offset_in_page(dir) + > - ext2_rec_len_from_disk(dir->rec_len); > + struct folio *folio = page_folio(page); > + struct inode *inode = folio->mapping->host; > + size_t from, to; > + char *kaddr; > loff_t pos; > - ext2_dirent *pde = NULL; > - ext2_dirent *de = (ext2_dirent *)(kaddr + from); > + ext2_dirent *de, *pde = NULL; > int err; > > + from = offset_in_folio(folio, dir); > + to = from + ext2_rec_len_from_disk(dir->rec_len); > + kaddr = (char *)dir - from; > + from &= ~(ext2_chunk_size(inode)-1); > + de = (ext2_dirent *)(kaddr + from); > + > while ((char*)de < (char*)dir) { > if (de->rec_len == 0) { > ext2_error(inode->i_sb, __func__, > @@ -606,18 +610,18 @@ int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page) > de = ext2_next_entry(de); > } > if (pde) > - from = offset_in_page(pde); > - pos = page_offset(page) + from; > - lock_page(page); > - err = ext2_prepare_chunk(page, pos, to - from); > + from = offset_in_folio(folio, pde); > + pos = folio_pos(folio) + from; > + folio_lock(folio); > + err = ext2_prepare_chunk(&folio->page, pos, to - from); > if (err) { > - unlock_page(page); > + folio_unlock(folio); > return err; > } > if (pde) > pde->rec_len = ext2_rec_len_to_disk(to - from); > dir->inode = 0; > - ext2_commit_chunk(page, pos, to - from); > + ext2_commit_chunk(&folio->page, pos, to - from); > inode->i_mtime = inode_set_ctime_current(inode); > EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; > mark_inode_dirty(inode); > -- > 2.40.1 >
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 2fc910e99234..7e75cfaa709c 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -586,16 +586,20 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) */ int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page) { - struct inode *inode = page->mapping->host; - char *kaddr = (char *)((unsigned long)dir & PAGE_MASK); - unsigned from = offset_in_page(dir) & ~(ext2_chunk_size(inode)-1); - unsigned to = offset_in_page(dir) + - ext2_rec_len_from_disk(dir->rec_len); + struct folio *folio = page_folio(page); + struct inode *inode = folio->mapping->host; + size_t from, to; + char *kaddr; loff_t pos; - ext2_dirent *pde = NULL; - ext2_dirent *de = (ext2_dirent *)(kaddr + from); + ext2_dirent *de, *pde = NULL; int err; + from = offset_in_folio(folio, dir); + to = from + ext2_rec_len_from_disk(dir->rec_len); + kaddr = (char *)dir - from; + from &= ~(ext2_chunk_size(inode)-1); + de = (ext2_dirent *)(kaddr + from); + while ((char*)de < (char*)dir) { if (de->rec_len == 0) { ext2_error(inode->i_sb, __func__, @@ -606,18 +610,18 @@ int ext2_delete_entry(struct ext2_dir_entry_2 *dir, struct page *page) de = ext2_next_entry(de); } if (pde) - from = offset_in_page(pde); - pos = page_offset(page) + from; - lock_page(page); - err = ext2_prepare_chunk(page, pos, to - from); + from = offset_in_folio(folio, pde); + pos = folio_pos(folio) + from; + folio_lock(folio); + err = ext2_prepare_chunk(&folio->page, pos, to - from); if (err) { - unlock_page(page); + folio_unlock(folio); return err; } if (pde) pde->rec_len = ext2_rec_len_to_disk(to - from); dir->inode = 0; - ext2_commit_chunk(page, pos, to - from); + ext2_commit_chunk(&folio->page, pos, to - from); inode->i_mtime = inode_set_ctime_current(inode); EXT2_I(inode)->i_flags &= ~EXT2_BTREE_FL; mark_inode_dirty(inode);
If the block size is > PAGE_SIZE, we need to calculate these offsets relative to the start of the folio, not the page. Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org> --- fs/ext2/dir.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-)