Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
R
R128
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Deploy
Releases
Package Registry
Model registry
Operate
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Ermine
R128
Commits
ec108d3c
Commit
ec108d3c
authored
2 years ago
by
Anna Schumaker
Browse files
Options
Downloads
Patches
Plain Diff
NFS: Convert readdir page array functions to use a folio
Signed-off-by:
Anna Schumaker
<
Anna.Schumaker@Netapp.com
>
parent
61f02e0a
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
fs/nfs/dir.c
+99
-102
99 additions, 102 deletions
fs/nfs/dir.c
with
99 additions
and
102 deletions
fs/nfs/dir.c
+
99
−
102
View file @
ec108d3c
...
...
@@ -55,7 +55,7 @@ static int nfs_closedir(struct inode *, struct file *);
static
int
nfs_readdir
(
struct
file
*
,
struct
dir_context
*
);
static
int
nfs_fsync_dir
(
struct
file
*
,
loff_t
,
loff_t
,
int
);
static
loff_t
nfs_llseek_dir
(
struct
file
*
,
loff_t
,
int
);
static
void
nfs_readdir_
free_folio
(
struct
folio
*
);
static
void
nfs_readdir_
clear_array
(
struct
folio
*
);
const
struct
file_operations
nfs_dir_operations
=
{
.
llseek
=
nfs_llseek_dir
,
...
...
@@ -67,7 +67,7 @@ const struct file_operations nfs_dir_operations = {
};
const
struct
address_space_operations
nfs_dir_aops
=
{
.
free_folio
=
nfs_readdir_
free_folio
,
.
free_folio
=
nfs_readdir_
clear_array
,
};
#define NFS_INIT_DTSIZE PAGE_SIZE
...
...
@@ -146,8 +146,8 @@ struct nfs_cache_array {
u64
change_attr
;
u64
last_cookie
;
unsigned
int
size
;
unsigned
char
page
_full
:
1
,
page
_is_eof
:
1
,
unsigned
char
folio
_full
:
1
,
folio
_is_eof
:
1
,
cookies_are_ordered
:
1
;
struct
nfs_cache_array_entry
array
[];
};
...
...
@@ -198,17 +198,17 @@ static void nfs_grow_dtsize(struct nfs_readdir_descriptor *desc)
nfs_set_dtsize
(
desc
,
desc
->
dtsize
<<
1
);
}
static
void
nfs_readdir_
page
_init_array
(
struct
page
*
page
,
u64
last_cookie
,
u64
change_attr
)
static
void
nfs_readdir_
folio
_init_array
(
struct
folio
*
folio
,
u64
last_cookie
,
u64
change_attr
)
{
struct
nfs_cache_array
*
array
;
array
=
kmap_local_
page
(
page
);
array
=
kmap_local_
folio
(
folio
,
0
);
array
->
change_attr
=
change_attr
;
array
->
last_cookie
=
last_cookie
;
array
->
size
=
0
;
array
->
page
_full
=
0
;
array
->
page
_is_eof
=
0
;
array
->
folio
_full
=
0
;
array
->
folio
_is_eof
=
0
;
array
->
cookies_are_ordered
=
1
;
kunmap_local
(
array
);
}
...
...
@@ -216,44 +216,39 @@ static void nfs_readdir_page_init_array(struct page *page, u64 last_cookie,
/*
* we are freeing strings created by nfs_add_to_readdir_array()
*/
static
void
nfs_readdir_clear_array
(
struct
page
*
page
)
static
void
nfs_readdir_clear_array
(
struct
folio
*
folio
)
{
struct
nfs_cache_array
*
array
;
unsigned
int
i
;
array
=
kmap_local_
page
(
page
);
array
=
kmap_local_
folio
(
folio
,
0
);
for
(
i
=
0
;
i
<
array
->
size
;
i
++
)
kfree
(
array
->
array
[
i
].
name
);
array
->
size
=
0
;
kunmap_local
(
array
);
}
static
void
nfs_readdir_free_folio
(
struct
folio
*
folio
)
static
void
nfs_readdir_folio_reinit_array
(
struct
folio
*
folio
,
u64
last_cookie
,
u64
change_attr
)
{
nfs_readdir_clear_array
(
&
folio
->
page
);
nfs_readdir_clear_array
(
folio
);
nfs_readdir_folio_init_array
(
folio
,
last_cookie
,
change_attr
);
}
static
void
nfs_readdir_page_reinit_array
(
struct
page
*
page
,
u64
last_cookie
,
u64
change_attr
)
{
nfs_readdir_clear_array
(
page
);
nfs_readdir_page_init_array
(
page
,
last_cookie
,
change_attr
);
}
static
struct
page
*
nfs_readdir_page_array_alloc
(
u64
last_cookie
,
gfp_t
gfp_flags
)
static
struct
folio
*
nfs_readdir_folio_array_alloc
(
u64
last_cookie
,
gfp_t
gfp_flags
)
{
struct
page
*
page
=
alloc_page
(
gfp_flags
);
if
(
page
)
nfs_readdir_
page
_init_array
(
page
,
last_cookie
,
0
);
return
page
;
struct
folio
*
folio
=
folio_alloc
(
gfp_flags
,
0
);
if
(
folio
)
nfs_readdir_
folio
_init_array
(
folio
,
last_cookie
,
0
);
return
folio
;
}
static
void
nfs_readdir_
page
_array_free
(
struct
page
*
page
)
static
void
nfs_readdir_
folio
_array_free
(
struct
folio
*
folio
)
{
if
(
page
)
{
nfs_readdir_clear_array
(
page
);
put_page
(
page
);
if
(
folio
)
{
nfs_readdir_clear_array
(
folio
);
folio_put
(
folio
);
}
}
...
...
@@ -264,13 +259,13 @@ static u64 nfs_readdir_array_index_cookie(struct nfs_cache_array *array)
static
void
nfs_readdir_array_set_eof
(
struct
nfs_cache_array
*
array
)
{
array
->
page
_is_eof
=
1
;
array
->
page
_full
=
1
;
array
->
folio
_is_eof
=
1
;
array
->
folio
_full
=
1
;
}
static
bool
nfs_readdir_array_is_full
(
struct
nfs_cache_array
*
array
)
{
return
array
->
page
_full
;
return
array
->
folio
_full
;
}
/*
...
...
@@ -302,16 +297,16 @@ static size_t nfs_readdir_array_maxentries(void)
*/
static
int
nfs_readdir_array_can_expand
(
struct
nfs_cache_array
*
array
)
{
if
(
array
->
page
_full
)
if
(
array
->
folio
_full
)
return
-
ENOSPC
;
if
(
array
->
size
==
nfs_readdir_array_maxentries
())
{
array
->
page
_full
=
1
;
array
->
folio
_full
=
1
;
return
-
ENOSPC
;
}
return
0
;
}
static
int
nfs_readdir_
page
_array_append
(
struct
page
*
page
,
static
int
nfs_readdir_
folio
_array_append
(
struct
folio
*
folio
,
const
struct
nfs_entry
*
entry
,
u64
*
cookie
)
{
...
...
@@ -322,7 +317,7 @@ static int nfs_readdir_page_array_append(struct page *page,
name
=
nfs_readdir_copy_name
(
entry
->
name
,
entry
->
len
);
array
=
kmap_atomic
(
page
);
array
=
kmap_atomic
(
folio_page
(
folio
,
0
)
);
if
(
!
name
)
goto
out
;
ret
=
nfs_readdir_array_can_expand
(
array
);
...
...
@@ -361,17 +356,17 @@ static int nfs_readdir_page_array_append(struct page *page,
* 127 readdir entries for a typical 64-bit system, that works out to a
* cache of ~ 33 million entries per directory.
*/
static
pgoff_t
nfs_readdir_
page
_cookie_hash
(
u64
cookie
)
static
pgoff_t
nfs_readdir_
folio
_cookie_hash
(
u64
cookie
)
{
if
(
cookie
==
0
)
return
0
;
return
hash_64
(
cookie
,
18
);
}
static
bool
nfs_readdir_
page
_validate
(
struct
page
*
page
,
u64
last_cookie
,
u64
change_attr
)
static
bool
nfs_readdir_
folio
_validate
(
struct
folio
*
folio
,
u64
last_cookie
,
u64
change_attr
)
{
struct
nfs_cache_array
*
array
=
kmap_local_
page
(
page
);
struct
nfs_cache_array
*
array
=
kmap_local_
folio
(
folio
,
0
);
int
ret
=
true
;
if
(
array
->
change_attr
!=
change_attr
)
...
...
@@ -382,81 +377,83 @@ static bool nfs_readdir_page_validate(struct page *page, u64 last_cookie,
return
ret
;
}
static
void
nfs_readdir_
page
_unlock_and_put
(
struct
page
*
page
)
static
void
nfs_readdir_
folio
_unlock_and_put
(
struct
folio
*
folio
)
{
unlock_page
(
page
);
put_page
(
page
);
folio_unlock
(
folio
);
folio_put
(
folio
);
}
static
void
nfs_readdir_
page
_init_and_validate
(
struct
page
*
page
,
u64
cookie
,
u64
change_attr
)
static
void
nfs_readdir_
folio
_init_and_validate
(
struct
folio
*
folio
,
u64
cookie
,
u64
change_attr
)
{
if
(
PageU
ptodate
(
page
))
{
if
(
nfs_readdir_
page
_validate
(
page
,
cookie
,
change_attr
))
if
(
folio_test_u
ptodate
(
folio
))
{
if
(
nfs_readdir_
folio
_validate
(
folio
,
cookie
,
change_attr
))
return
;
nfs_readdir_clear_array
(
page
);
nfs_readdir_clear_array
(
folio
);
}
nfs_readdir_
page
_init_array
(
page
,
cookie
,
change_attr
);
SetPageU
ptodate
(
page
);
nfs_readdir_
folio
_init_array
(
folio
,
cookie
,
change_attr
);
folio_mark_u
ptodate
(
folio
);
}
static
struct
page
*
nfs_readdir_
page
_get_locked
(
struct
address_space
*
mapping
,
u64
cookie
,
u64
change_attr
)
static
struct
folio
*
nfs_readdir_
folio
_get_locked
(
struct
address_space
*
mapping
,
u64
cookie
,
u64
change_attr
)
{
pgoff_t
index
=
nfs_readdir_
page
_cookie_hash
(
cookie
);
struct
page
*
page
;
pgoff_t
index
=
nfs_readdir_
folio
_cookie_hash
(
cookie
);
struct
folio
*
folio
;
page
=
grab_cache_page
(
mapping
,
index
);
if
(
!
page
)
folio
=
filemap_grab_folio
(
mapping
,
index
);
if
(
!
folio
)
return
NULL
;
nfs_readdir_
page
_init_and_validate
(
page
,
cookie
,
change_attr
);
return
page
;
nfs_readdir_
folio
_init_and_validate
(
folio
,
cookie
,
change_attr
);
return
folio
;
}
static
u64
nfs_readdir_
page
_last_cookie
(
struct
page
*
page
)
static
u64
nfs_readdir_
folio
_last_cookie
(
struct
folio
*
folio
)
{
struct
nfs_cache_array
*
array
;
u64
ret
;
array
=
kmap_local_
page
(
page
);
array
=
kmap_local_
folio
(
folio
,
0
);
ret
=
array
->
last_cookie
;
kunmap_local
(
array
);
return
ret
;
}
static
bool
nfs_readdir_
page
_needs_filling
(
struct
page
*
page
)
static
bool
nfs_readdir_
folio
_needs_filling
(
struct
folio
*
folio
)
{
struct
nfs_cache_array
*
array
;
bool
ret
;
array
=
kmap_local_
page
(
page
);
array
=
kmap_local_
folio
(
folio
,
0
);
ret
=
!
nfs_readdir_array_is_full
(
array
);
kunmap_local
(
array
);
return
ret
;
}
static
void
nfs_readdir_
page
_set_eof
(
struct
page
*
page
)
static
void
nfs_readdir_
folio
_set_eof
(
struct
folio
*
folio
)
{
struct
nfs_cache_array
*
array
;
array
=
kmap_local_
page
(
page
);
array
=
kmap_local_
folio
(
folio
,
0
);
nfs_readdir_array_set_eof
(
array
);
kunmap_local
(
array
);
}
static
struct
page
*
nfs_readdir_
page
_get_next
(
struct
address_space
*
mapping
,
u64
cookie
,
u64
change_attr
)
static
struct
folio
*
nfs_readdir_
folio
_get_next
(
struct
address_space
*
mapping
,
u64
cookie
,
u64
change_attr
)
{
pgoff_t
index
=
nfs_readdir_
page
_cookie_hash
(
cookie
);
struct
page
*
page
;
pgoff_t
index
=
nfs_readdir_
folio
_cookie_hash
(
cookie
);
struct
folio
*
folio
;
page
=
grab_cache_page_nowait
(
mapping
,
index
);
if
(
!
page
)
folio
=
__filemap_get_folio
(
mapping
,
index
,
FGP_LOCK
|
FGP_CREAT
|
FGP_NOFS
|
FGP_NOWAIT
,
mapping_gfp_mask
(
mapping
));
if
(
!
folio
)
return
NULL
;
nfs_readdir_
page
_init_and_validate
(
page
,
cookie
,
change_attr
);
if
(
nfs_readdir_
page
_last_cookie
(
page
)
!=
cookie
)
nfs_readdir_
page
_reinit_array
(
page
,
cookie
,
change_attr
);
return
page
;
nfs_readdir_
folio
_init_and_validate
(
folio
,
cookie
,
change_attr
);
if
(
nfs_readdir_
folio
_last_cookie
(
folio
)
!=
cookie
)
nfs_readdir_
folio
_reinit_array
(
folio
,
cookie
,
change_attr
);
return
folio
;
}
static
inline
...
...
@@ -481,7 +478,7 @@ bool nfs_readdir_use_cookie(const struct file *filp)
static
void
nfs_readdir_seek_next_array
(
struct
nfs_cache_array
*
array
,
struct
nfs_readdir_descriptor
*
desc
)
{
if
(
array
->
page
_full
)
{
if
(
array
->
folio
_full
)
{
desc
->
last_cookie
=
array
->
last_cookie
;
desc
->
current_index
+=
array
->
size
;
desc
->
cache_entry_index
=
0
;
...
...
@@ -506,7 +503,7 @@ static int nfs_readdir_search_for_pos(struct nfs_cache_array *array,
if
(
diff
<
0
)
goto
out_eof
;
if
(
diff
>=
array
->
size
)
{
if
(
array
->
page
_is_eof
)
if
(
array
->
folio
_is_eof
)
goto
out_eof
;
nfs_readdir_seek_next_array
(
array
,
desc
);
return
-
EAGAIN
;
...
...
@@ -554,7 +551,7 @@ static int nfs_readdir_search_for_cookie(struct nfs_cache_array *array,
}
}
check_eof:
if
(
array
->
page
_is_eof
)
{
if
(
array
->
folio
_is_eof
)
{
status
=
-
EBADCOOKIE
;
if
(
desc
->
dir_cookie
==
array
->
last_cookie
)
desc
->
eof
=
true
;
...
...
@@ -826,9 +823,9 @@ static int nfs_readdir_folio_filler(struct nfs_readdir_descriptor *desc,
u64
change_attr
)
{
struct
address_space
*
mapping
=
desc
->
file
->
f_mapping
;
struct
folio
*
folio
=
*
arrays
;
struct
folio
*
new
,
*
folio
=
*
arrays
;
struct
xdr_stream
stream
;
struct
page
*
scratch
,
*
new
;
struct
page
*
scratch
;
struct
xdr_buf
buf
;
u64
cookie
;
int
status
;
...
...
@@ -845,36 +842,36 @@ static int nfs_readdir_folio_filler(struct nfs_readdir_descriptor *desc,
if
(
status
!=
0
)
break
;
status
=
nfs_readdir_
page
_array_append
(
folio
_page
(
folio
,
0
)
,
entry
,
&
cookie
);
status
=
nfs_readdir_
folio
_array_append
(
folio
,
entry
,
&
cookie
);
if
(
status
!=
-
ENOSPC
)
continue
;
if
(
folio
->
mapping
!=
mapping
)
{
if
(
!--
narrays
)
break
;
new
=
nfs_readdir_
page
_array_alloc
(
cookie
,
GFP_KERNEL
);
new
=
nfs_readdir_
folio
_array_alloc
(
cookie
,
GFP_KERNEL
);
if
(
!
new
)
break
;
arrays
++
;
*
arrays
=
folio
=
page_folio
(
new
)
;
*
arrays
=
folio
=
new
;
}
else
{
new
=
nfs_readdir_
page
_get_next
(
mapping
,
cookie
,
change_attr
);
new
=
nfs_readdir_
folio
_get_next
(
mapping
,
cookie
,
change_attr
);
if
(
!
new
)
break
;
if
(
folio
!=
*
arrays
)
nfs_readdir_
page
_unlock_and_put
(
folio
_page
(
folio
,
0
)
);
folio
=
page_folio
(
new
)
;
nfs_readdir_
folio
_unlock_and_put
(
folio
);
folio
=
new
;
}
desc
->
folio_index_max
++
;
status
=
nfs_readdir_
page
_array_append
(
folio
_page
(
folio
,
0
)
,
entry
,
&
cookie
);
status
=
nfs_readdir_
folio
_array_append
(
folio
,
entry
,
&
cookie
);
}
while
(
!
status
&&
!
entry
->
eof
);
switch
(
status
)
{
case
-
EBADCOOKIE
:
if
(
!
entry
->
eof
)
break
;
nfs_readdir_
page
_set_eof
(
folio
_page
(
folio
,
0
)
);
nfs_readdir_
folio
_set_eof
(
folio
);
fallthrough
;
case
-
EAGAIN
:
status
=
0
;
...
...
@@ -888,7 +885,7 @@ static int nfs_readdir_folio_filler(struct nfs_readdir_descriptor *desc,
}
if
(
folio
!=
*
arrays
)
nfs_readdir_
page
_unlock_and_put
(
folio
_page
(
folio
,
0
)
);
nfs_readdir_
folio
_unlock_and_put
(
folio
);
put_page
(
scratch
);
return
status
;
...
...
@@ -943,7 +940,7 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
entry
=
kzalloc
(
sizeof
(
*
entry
),
GFP_KERNEL
);
if
(
!
entry
)
return
-
ENOMEM
;
entry
->
cookie
=
nfs_readdir_
page
_last_cookie
(
folio
_page
(
folio
,
0
)
);
entry
->
cookie
=
nfs_readdir_
folio
_last_cookie
(
folio
);
entry
->
fh
=
nfs_alloc_fhandle
();
entry
->
fattr
=
nfs_alloc_fattr_with_label
(
NFS_SERVER
(
inode
));
entry
->
server
=
NFS_SERVER
(
inode
);
...
...
@@ -966,7 +963,7 @@ static int nfs_readdir_xdr_to_array(struct nfs_readdir_descriptor *desc,
status
=
nfs_readdir_folio_filler
(
desc
,
entry
,
pages
,
pglen
,
arrays
,
narrays
,
change_attr
);
else
nfs_readdir_
page
_set_eof
(
folio
_page
(
folio
,
0
)
);
nfs_readdir_
folio
_set_eof
(
folio
);
desc
->
buffer_fills
++
;
free_pages:
...
...
@@ -997,14 +994,14 @@ nfs_readdir_folio_get_cached(struct nfs_readdir_descriptor *desc)
struct
address_space
*
mapping
=
desc
->
file
->
f_mapping
;
u64
change_attr
=
inode_peek_iversion_raw
(
mapping
->
host
);
u64
cookie
=
desc
->
last_cookie
;
struct
page
*
page
;
struct
folio
*
folio
;
page
=
nfs_readdir_
page
_get_locked
(
mapping
,
cookie
,
change_attr
);
if
(
!
page
)
folio
=
nfs_readdir_
folio
_get_locked
(
mapping
,
cookie
,
change_attr
);
if
(
!
folio
)
return
NULL
;
if
(
desc
->
clear_cache
&&
!
nfs_readdir_
page
_needs_filling
(
page
))
nfs_readdir_
page
_reinit_array
(
page
,
cookie
,
change_attr
);
return
page_folio
(
page
)
;
if
(
desc
->
clear_cache
&&
!
nfs_readdir_
folio
_needs_filling
(
folio
))
nfs_readdir_
folio
_reinit_array
(
folio
,
cookie
,
change_attr
);
return
folio
;
}
/*
...
...
@@ -1021,7 +1018,7 @@ static int find_and_lock_cache_page(struct nfs_readdir_descriptor *desc)
desc
->
folio
=
nfs_readdir_folio_get_cached
(
desc
);
if
(
!
desc
->
folio
)
return
-
ENOMEM
;
if
(
nfs_readdir_
page
_needs_filling
(
folio_page
(
desc
->
folio
,
0
)
))
{
if
(
nfs_readdir_
folio
_needs_filling
(
desc
->
folio
))
{
/* Grow the dtsize if we had to go back for more pages */
if
(
desc
->
folio_index
==
desc
->
folio_index_max
)
nfs_grow_dtsize
(
desc
);
...
...
@@ -1115,7 +1112,7 @@ static void nfs_do_filldir(struct nfs_readdir_descriptor *desc,
break
;
}
}
if
(
array
->
page
_is_eof
)
if
(
array
->
folio
_is_eof
)
desc
->
eof
=
!
desc
->
eob
;
kunmap_local
(
array
);
...
...
@@ -1148,7 +1145,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
arrays
=
kcalloc
(
sz
,
sizeof
(
*
arrays
),
GFP_KERNEL
);
if
(
!
arrays
)
goto
out
;
arrays
[
0
]
=
page_folio
(
nfs_readdir_
page
_array_alloc
(
desc
->
dir_cookie
,
GFP_KERNEL
)
)
;
arrays
[
0
]
=
nfs_readdir_
folio
_array_alloc
(
desc
->
dir_cookie
,
GFP_KERNEL
);
if
(
!
arrays
[
0
])
goto
out
;
...
...
@@ -1185,7 +1182,7 @@ static int uncached_readdir(struct nfs_readdir_descriptor *desc)
}
out_free:
for
(
i
=
0
;
i
<
sz
&&
arrays
[
i
];
i
++
)
nfs_readdir_
page
_array_free
(
folio_page
(
arrays
[
i
]
,
0
)
);
nfs_readdir_
folio
_array_free
(
arrays
[
i
]);
out:
if
(
!
nfs_readdir_use_cookie
(
desc
->
file
))
nfs_readdir_rewind_search
(
desc
);
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment