Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

proc: less code duplication in /proc/*/cmdline

After staring at this code for a while I've figured using small 2-entry
array describing ARGV and ENVP is the way to address code duplication
critique.

Link: http://lkml.kernel.org/r/20170105185724.GA12027@avx2
Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

authored by

Alexey Dobriyan and committed by
Linus Torvalds
a0a07b87 4e4a7fb7

+54 -86
+54 -86
fs/proc/base.c
··· 292 292 } 293 293 } else { 294 294 /* 295 - * Command line (1 string) occupies ARGV and maybe 296 - * extends into ENVP. 297 - */ 298 - if (len1 + len2 <= *pos) 299 - goto skip_argv_envp; 300 - if (len1 <= *pos) 301 - goto skip_argv; 302 - 303 - p = arg_start + *pos; 304 - len = len1 - *pos; 305 - while (count > 0 && len > 0) { 306 - unsigned int _count, l; 307 - int nr_read; 308 - bool final; 309 - 310 - _count = min3(count, len, PAGE_SIZE); 311 - nr_read = access_remote_vm(mm, p, page, _count, 0); 312 - if (nr_read < 0) 313 - rv = nr_read; 314 - if (nr_read <= 0) 315 - goto out_free_page; 316 - 317 - /* 318 - * Command line can be shorter than whole ARGV 319 - * even if last "marker" byte says it is not. 320 - */ 321 - final = false; 322 - l = strnlen(page, nr_read); 323 - if (l < nr_read) { 324 - nr_read = l; 325 - final = true; 326 - } 327 - 328 - if (copy_to_user(buf, page, nr_read)) { 329 - rv = -EFAULT; 330 - goto out_free_page; 331 - } 332 - 333 - p += nr_read; 334 - len -= nr_read; 335 - buf += nr_read; 336 - count -= nr_read; 337 - rv += nr_read; 338 - 339 - if (final) 340 - goto out_free_page; 341 - } 342 - skip_argv: 343 - /* 344 295 * Command line (1 string) occupies ARGV and 345 296 * extends into ENVP. 346 297 */ 347 - if (len1 <= *pos) { 348 - p = env_start + *pos - len1; 349 - len = len1 + len2 - *pos; 350 - } else { 351 - p = env_start; 352 - len = len2; 298 + struct { 299 + unsigned long p; 300 + unsigned long len; 301 + } cmdline[2] = { 302 + { .p = arg_start, .len = len1 }, 303 + { .p = env_start, .len = len2 }, 304 + }; 305 + loff_t pos1 = *pos; 306 + unsigned int i; 307 + 308 + i = 0; 309 + while (i < 2 && pos1 >= cmdline[i].len) { 310 + pos1 -= cmdline[i].len; 311 + i++; 353 312 } 354 - while (count > 0 && len > 0) { 355 - unsigned int _count, l; 356 - int nr_read; 357 - bool final; 313 + while (i < 2) { 314 + p = cmdline[i].p + pos1; 315 + len = cmdline[i].len - pos1; 316 + while (count > 0 && len > 0) { 317 + unsigned int _count, l; 318 + int nr_read; 319 + bool final; 358 320 359 - _count = min3(count, len, PAGE_SIZE); 360 - nr_read = access_remote_vm(mm, p, page, _count, 0); 361 - if (nr_read < 0) 362 - rv = nr_read; 363 - if (nr_read <= 0) 364 - goto out_free_page; 321 + _count = min3(count, len, PAGE_SIZE); 322 + nr_read = access_remote_vm(mm, p, page, _count, 0); 323 + if (nr_read < 0) 324 + rv = nr_read; 325 + if (nr_read <= 0) 326 + goto out_free_page; 365 327 366 - /* Find EOS. */ 367 - final = false; 368 - l = strnlen(page, nr_read); 369 - if (l < nr_read) { 370 - nr_read = l; 371 - final = true; 328 + /* 329 + * Command line can be shorter than whole ARGV 330 + * even if last "marker" byte says it is not. 331 + */ 332 + final = false; 333 + l = strnlen(page, nr_read); 334 + if (l < nr_read) { 335 + nr_read = l; 336 + final = true; 337 + } 338 + 339 + if (copy_to_user(buf, page, nr_read)) { 340 + rv = -EFAULT; 341 + goto out_free_page; 342 + } 343 + 344 + p += nr_read; 345 + len -= nr_read; 346 + buf += nr_read; 347 + count -= nr_read; 348 + rv += nr_read; 349 + 350 + if (final) 351 + goto out_free_page; 372 352 } 373 353 374 - if (copy_to_user(buf, page, nr_read)) { 375 - rv = -EFAULT; 376 - goto out_free_page; 377 - } 378 - 379 - p += nr_read; 380 - len -= nr_read; 381 - buf += nr_read; 382 - count -= nr_read; 383 - rv += nr_read; 384 - 385 - if (final) 386 - goto out_free_page; 354 + /* Only first chunk can be read partially. */ 355 + pos1 = 0; 356 + i++; 387 357 } 388 - skip_argv_envp: 389 - ; 390 358 } 391 359 392 360 out_free_page: