dir.c (ed09222d651dbd30e707f96180628229146b885c) dir.c (a52a8a6adad99e1162c27f70cd6495626a48064d)
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/fs/nfs/dir.c
4 *
5 * Copyright (C) 1992 Rick Sladkey
6 *
7 * nfs directory handling functions
8 *

--- 119 unchanged lines hidden (view full) ---

128{
129 put_nfs_open_dir_context(file_inode(filp), filp->private_data);
130 return 0;
131}
132
133struct nfs_cache_array_entry {
134 u64 cookie;
135 u64 ino;
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * linux/fs/nfs/dir.c
4 *
5 * Copyright (C) 1992 Rick Sladkey
6 *
7 * nfs directory handling functions
8 *

--- 119 unchanged lines hidden (view full) ---

128{
129 put_nfs_open_dir_context(file_inode(filp), filp->private_data);
130 return 0;
131}
132
133struct nfs_cache_array_entry {
134 u64 cookie;
135 u64 ino;
136 struct qstr string;
136 const char *name;
137 unsigned int name_len;
137 unsigned char d_type;
138};
139
140struct nfs_cache_array {
141 u64 last_cookie;
142 unsigned int size;
143 unsigned char page_full : 1,
144 page_is_eof : 1;

--- 42 unchanged lines hidden (view full) ---

187static
188void nfs_readdir_clear_array(struct page *page)
189{
190 struct nfs_cache_array *array;
191 int i;
192
193 array = kmap_atomic(page);
194 for (i = 0; i < array->size; i++)
138 unsigned char d_type;
139};
140
141struct nfs_cache_array {
142 u64 last_cookie;
143 unsigned int size;
144 unsigned char page_full : 1,
145 page_is_eof : 1;

--- 42 unchanged lines hidden (view full) ---

188static
189void nfs_readdir_clear_array(struct page *page)
190{
191 struct nfs_cache_array *array;
192 int i;
193
194 array = kmap_atomic(page);
195 for (i = 0; i < array->size; i++)
195 kfree(array->array[i].string.name);
196 kfree(array->array[i].name);
196 nfs_readdir_array_init(array);
197 kunmap_atomic(array);
198}
199
200static void nfs_readdir_array_set_eof(struct nfs_cache_array *array)
201{
202 array->page_is_eof = 1;
203 array->page_full = 1;

--- 4 unchanged lines hidden (view full) ---

208 return array->page_full;
209}
210
211/*
212 * the caller is responsible for freeing qstr.name
213 * when called by nfs_readdir_add_to_array, the strings will be freed in
214 * nfs_clear_readdir_array()
215 */
197 nfs_readdir_array_init(array);
198 kunmap_atomic(array);
199}
200
201static void nfs_readdir_array_set_eof(struct nfs_cache_array *array)
202{
203 array->page_is_eof = 1;
204 array->page_full = 1;

--- 4 unchanged lines hidden (view full) ---

209 return array->page_full;
210}
211
212/*
213 * the caller is responsible for freeing qstr.name
214 * when called by nfs_readdir_add_to_array, the strings will be freed in
215 * nfs_clear_readdir_array()
216 */
216static
217int nfs_readdir_make_qstr(struct qstr *string, const char *name, unsigned int len)
217static const char *nfs_readdir_copy_name(const char *name, unsigned int len)
218{
218{
219 string->len = len;
220 string->name = kmemdup_nul(name, len, GFP_KERNEL);
221 if (string->name == NULL)
222 return -ENOMEM;
219 const char *ret = kmemdup_nul(name, len, GFP_KERNEL);
220
223 /*
224 * Avoid a kmemleak false positive. The pointer to the name is stored
225 * in a page cache page which kmemleak does not scan.
226 */
221 /*
222 * Avoid a kmemleak false positive. The pointer to the name is stored
223 * in a page cache page which kmemleak does not scan.
224 */
227 kmemleak_not_leak(string->name);
228 string->hash = full_name_hash(NULL, name, len);
229 return 0;
225 if (ret != NULL)
226 kmemleak_not_leak(ret);
227 return ret;
230}
231
232/*
233 * Check that the next array entry lies entirely within the page bounds
234 */
235static int nfs_readdir_array_can_expand(struct nfs_cache_array *array)
236{
237 struct nfs_cache_array_entry *cache_entry;

--- 6 unchanged lines hidden (view full) ---

244 return -ENOSPC;
245 }
246 return 0;
247}
248
249static
250int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
251{
228}
229
230/*
231 * Check that the next array entry lies entirely within the page bounds
232 */
233static int nfs_readdir_array_can_expand(struct nfs_cache_array *array)
234{
235 struct nfs_cache_array_entry *cache_entry;

--- 6 unchanged lines hidden (view full) ---

242 return -ENOSPC;
243 }
244 return 0;
245}
246
247static
248int nfs_readdir_add_to_array(struct nfs_entry *entry, struct page *page)
249{
252 struct nfs_cache_array *array = kmap(page);
250 struct nfs_cache_array *array;
253 struct nfs_cache_array_entry *cache_entry;
251 struct nfs_cache_array_entry *cache_entry;
252 const char *name;
254 int ret;
255
253 int ret;
254
255 name = nfs_readdir_copy_name(entry->name, entry->len);
256 if (!name)
257 return -ENOMEM;
258
259 array = kmap_atomic(page);
256 ret = nfs_readdir_array_can_expand(array);
260 ret = nfs_readdir_array_can_expand(array);
257 if (ret)
261 if (ret) {
262 kfree(name);
258 goto out;
263 goto out;
264 }
259
260 cache_entry = &array->array[array->size];
261 cache_entry->cookie = entry->prev_cookie;
262 cache_entry->ino = entry->ino;
263 cache_entry->d_type = entry->d_type;
265
266 cache_entry = &array->array[array->size];
267 cache_entry->cookie = entry->prev_cookie;
268 cache_entry->ino = entry->ino;
269 cache_entry->d_type = entry->d_type;
264 ret = nfs_readdir_make_qstr(&cache_entry->string, entry->name, entry->len);
265 if (ret)
266 goto out;
270 cache_entry->name_len = entry->len;
271 cache_entry->name = name;
267 array->last_cookie = entry->cookie;
268 array->size++;
269 if (entry->eof != 0)
270 nfs_readdir_array_set_eof(array);
271out:
272 array->last_cookie = entry->cookie;
273 array->size++;
274 if (entry->eof != 0)
275 nfs_readdir_array_set_eof(array);
276out:
272 kunmap(page);
277 kunmap_atomic(array);
273 return ret;
274}
275
276static struct page *nfs_readdir_page_get_locked(struct address_space *mapping,
277 pgoff_t index, u64 last_cookie)
278{
279 struct page *page;
280

--- 127 unchanged lines hidden (view full) ---

408 desc->duped = 0;
409 desc->attr_gencount = nfsi->attr_gencount;
410 } else if (new_pos < desc->prev_index) {
411 if (desc->duped > 0
412 && desc->dup_cookie == desc->dir_cookie) {
413 if (printk_ratelimit()) {
414 pr_notice("NFS: directory %pD2 contains a readdir loop."
415 "Please contact your server vendor. "
278 return ret;
279}
280
281static struct page *nfs_readdir_page_get_locked(struct address_space *mapping,
282 pgoff_t index, u64 last_cookie)
283{
284 struct page *page;
285

--- 127 unchanged lines hidden (view full) ---

413 desc->duped = 0;
414 desc->attr_gencount = nfsi->attr_gencount;
415 } else if (new_pos < desc->prev_index) {
416 if (desc->duped > 0
417 && desc->dup_cookie == desc->dir_cookie) {
418 if (printk_ratelimit()) {
419 pr_notice("NFS: directory %pD2 contains a readdir loop."
420 "Please contact your server vendor. "
416 "The file: %.*s has duplicate cookie %llu\n",
417 desc->file, array->array[i].string.len,
418 array->array[i].string.name, desc->dir_cookie);
421 "The file: %s has duplicate cookie %llu\n",
422 desc->file, array->array[i].name, desc->dir_cookie);
419 }
420 status = -ELOOP;
421 goto out;
422 }
423 desc->dup_cookie = desc->dir_cookie;
424 desc->duped = -1;
425 }
426 if (nfs_readdir_use_cookie(desc->file))

--- 456 unchanged lines hidden (view full) ---

883 int res = 0;
884 struct nfs_cache_array *array = NULL;
885
886 array = kmap(desc->page);
887 for (i = desc->cache_entry_index; i < array->size; i++) {
888 struct nfs_cache_array_entry *ent;
889
890 ent = &array->array[i];
423 }
424 status = -ELOOP;
425 goto out;
426 }
427 desc->dup_cookie = desc->dir_cookie;
428 desc->duped = -1;
429 }
430 if (nfs_readdir_use_cookie(desc->file))

--- 456 unchanged lines hidden (view full) ---

887 int res = 0;
888 struct nfs_cache_array *array = NULL;
889
890 array = kmap(desc->page);
891 for (i = desc->cache_entry_index; i < array->size; i++) {
892 struct nfs_cache_array_entry *ent;
893
894 ent = &array->array[i];
891 if (!dir_emit(desc->ctx, ent->string.name, ent->string.len,
895 if (!dir_emit(desc->ctx, ent->name, ent->name_len,
892 nfs_compat_user_ino64(ent->ino), ent->d_type)) {
893 desc->eof = true;
894 break;
895 }
896 if (i < (array->size-1))
897 desc->dir_cookie = array->array[i+1].cookie;
898 else
899 desc->dir_cookie = array->last_cookie;

--- 1995 unchanged lines hidden ---
896 nfs_compat_user_ino64(ent->ino), ent->d_type)) {
897 desc->eof = true;
898 break;
899 }
900 if (i < (array->size-1))
901 desc->dir_cookie = array->array[i+1].cookie;
902 else
903 desc->dir_cookie = array->last_cookie;

--- 1995 unchanged lines hidden ---