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 --- |