@@ -285,6 +285,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
285
285
if (!xent )
286
286
return - ENOMEM ;
287
287
288
+ down_write (& ubifs_inode (host )-> xattr_sem );
288
289
/*
289
290
* The extended attribute entries are stored in LNC, so multiple
290
291
* look-ups do not involve reading the flash.
@@ -319,6 +320,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
319
320
iput (inode );
320
321
321
322
out_free :
323
+ up_write (& ubifs_inode (host )-> xattr_sem );
322
324
kfree (xent );
323
325
return err ;
324
326
}
@@ -341,18 +343,19 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
341
343
if (!xent )
342
344
return - ENOMEM ;
343
345
346
+ down_read (& ubifs_inode (host )-> xattr_sem );
344
347
xent_key_init (c , & key , host -> i_ino , & nm );
345
348
err = ubifs_tnc_lookup_nm (c , & key , xent , & nm );
346
349
if (err ) {
347
350
if (err == - ENOENT )
348
351
err = - ENODATA ;
349
- goto out_unlock ;
352
+ goto out_cleanup ;
350
353
}
351
354
352
355
inode = iget_xattr (c , le64_to_cpu (xent -> inum ));
353
356
if (IS_ERR (inode )) {
354
357
err = PTR_ERR (inode );
355
- goto out_unlock ;
358
+ goto out_cleanup ;
356
359
}
357
360
358
361
ui = ubifs_inode (inode );
@@ -374,7 +377,8 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
374
377
out_iput :
375
378
mutex_unlock (& ui -> ui_mutex );
376
379
iput (inode );
377
- out_unlock :
380
+ out_cleanup :
381
+ up_read (& ubifs_inode (host )-> xattr_sem );
378
382
kfree (xent );
379
383
return err ;
380
384
}
@@ -406,16 +410,21 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
406
410
dbg_gen ("ino %lu ('%pd'), buffer size %zd" , host -> i_ino ,
407
411
dentry , size );
408
412
413
+ down_read (& host_ui -> xattr_sem );
409
414
len = host_ui -> xattr_names + host_ui -> xattr_cnt ;
410
- if (!buffer )
415
+ if (!buffer ) {
411
416
/*
412
417
* We should return the minimum buffer size which will fit a
413
418
* null-terminated list of all the extended attribute names.
414
419
*/
415
- return len ;
420
+ err = len ;
421
+ goto out_err ;
422
+ }
416
423
417
- if (len > size )
418
- return - ERANGE ;
424
+ if (len > size ) {
425
+ err = - ERANGE ;
426
+ goto out_err ;
427
+ }
419
428
420
429
lowest_xent_key (c , & key , host -> i_ino );
421
430
while (1 ) {
@@ -437,15 +446,20 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
437
446
pxent = xent ;
438
447
key_read (c , & xent -> key , & key );
439
448
}
440
-
441
449
kfree (pxent );
450
+ up_read (& host_ui -> xattr_sem );
451
+
442
452
if (err != - ENOENT ) {
443
453
ubifs_err (c , "cannot find next direntry, error %d" , err );
444
454
return err ;
445
455
}
446
456
447
457
ubifs_assert (c , written <= size );
448
458
return written ;
459
+
460
+ out_err :
461
+ up_read (& host_ui -> xattr_sem );
462
+ return err ;
449
463
}
450
464
451
465
static int remove_xattr (struct ubifs_info * c , struct inode * host ,
@@ -504,6 +518,7 @@ int ubifs_purge_xattrs(struct inode *host)
504
518
ubifs_warn (c , "inode %lu has too many xattrs, doing a non-atomic deletion" ,
505
519
host -> i_ino );
506
520
521
+ down_write (& ubifs_inode (host )-> xattr_sem );
507
522
lowest_xent_key (c , & key , host -> i_ino );
508
523
while (1 ) {
509
524
xent = ubifs_tnc_next_ent (c , & key , & nm );
@@ -523,7 +538,7 @@ int ubifs_purge_xattrs(struct inode *host)
523
538
ubifs_ro_mode (c , err );
524
539
kfree (pxent );
525
540
kfree (xent );
526
- return err ;
541
+ goto out_err ;
527
542
}
528
543
529
544
ubifs_assert (c , ubifs_inode (xino )-> xattr );
@@ -535,7 +550,7 @@ int ubifs_purge_xattrs(struct inode *host)
535
550
kfree (xent );
536
551
iput (xino );
537
552
ubifs_err (c , "cannot remove xattr, error %d" , err );
538
- return err ;
553
+ goto out_err ;
539
554
}
540
555
541
556
iput (xino );
@@ -544,14 +559,19 @@ int ubifs_purge_xattrs(struct inode *host)
544
559
pxent = xent ;
545
560
key_read (c , & xent -> key , & key );
546
561
}
547
-
548
562
kfree (pxent );
563
+ up_write (& ubifs_inode (host )-> xattr_sem );
564
+
549
565
if (err != - ENOENT ) {
550
566
ubifs_err (c , "cannot find next direntry, error %d" , err );
551
567
return err ;
552
568
}
553
569
554
570
return 0 ;
571
+
572
+ out_err :
573
+ up_write (& ubifs_inode (host )-> xattr_sem );
574
+ return err ;
555
575
}
556
576
557
577
/**
@@ -594,6 +614,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
594
614
if (!xent )
595
615
return - ENOMEM ;
596
616
617
+ down_write (& ubifs_inode (host )-> xattr_sem );
597
618
xent_key_init (c , & key , host -> i_ino , & nm );
598
619
err = ubifs_tnc_lookup_nm (c , & key , xent , & nm );
599
620
if (err ) {
@@ -618,6 +639,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
618
639
iput (inode );
619
640
620
641
out_free :
642
+ up_write (& ubifs_inode (host )-> xattr_sem );
621
643
kfree (xent );
622
644
return err ;
623
645
}
0 commit comments