@@ -208,13 +208,11 @@ static int change_xattr(struct ubifs_info *c, struct inode *host,
208208 err = - ENOMEM ;
209209 goto out_free ;
210210 }
211- mutex_lock (& ui -> ui_mutex );
212211 kfree (ui -> data );
213212 ui -> data = buf ;
214213 inode -> i_size = ui -> ui_size = size ;
215214 old_size = ui -> data_len ;
216215 ui -> data_len = size ;
217- mutex_unlock (& ui -> ui_mutex );
218216
219217 mutex_lock (& host_ui -> ui_mutex );
220218 host -> i_ctime = current_time (host );
@@ -285,6 +283,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
285283 if (!xent )
286284 return - ENOMEM ;
287285
286+ down_write (& ubifs_inode (host )-> xattr_sem );
288287 /*
289288 * The extended attribute entries are stored in LNC, so multiple
290289 * look-ups do not involve reading the flash.
@@ -319,6 +318,7 @@ int ubifs_xattr_set(struct inode *host, const char *name, const void *value,
319318 iput (inode );
320319
321320out_free :
321+ up_write (& ubifs_inode (host )-> xattr_sem );
322322 kfree (xent );
323323 return err ;
324324}
@@ -341,25 +341,25 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
341341 if (!xent )
342342 return - ENOMEM ;
343343
344+ down_read (& ubifs_inode (host )-> xattr_sem );
344345 xent_key_init (c , & key , host -> i_ino , & nm );
345346 err = ubifs_tnc_lookup_nm (c , & key , xent , & nm );
346347 if (err ) {
347348 if (err == - ENOENT )
348349 err = - ENODATA ;
349- goto out_unlock ;
350+ goto out_cleanup ;
350351 }
351352
352353 inode = iget_xattr (c , le64_to_cpu (xent -> inum ));
353354 if (IS_ERR (inode )) {
354355 err = PTR_ERR (inode );
355- goto out_unlock ;
356+ goto out_cleanup ;
356357 }
357358
358359 ui = ubifs_inode (inode );
359360 ubifs_assert (c , inode -> i_size == ui -> data_len );
360361 ubifs_assert (c , ubifs_inode (host )-> xattr_size > ui -> data_len );
361362
362- mutex_lock (& ui -> ui_mutex );
363363 if (buf ) {
364364 /* If @buf is %NULL we are supposed to return the length */
365365 if (ui -> data_len > size ) {
@@ -372,9 +372,9 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
372372 err = ui -> data_len ;
373373
374374out_iput :
375- mutex_unlock (& ui -> ui_mutex );
376375 iput (inode );
377- out_unlock :
376+ out_cleanup :
377+ up_read (& ubifs_inode (host )-> xattr_sem );
378378 kfree (xent );
379379 return err ;
380380}
@@ -406,16 +406,21 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
406406 dbg_gen ("ino %lu ('%pd'), buffer size %zd" , host -> i_ino ,
407407 dentry , size );
408408
409+ down_read (& host_ui -> xattr_sem );
409410 len = host_ui -> xattr_names + host_ui -> xattr_cnt ;
410- if (!buffer )
411+ if (!buffer ) {
411412 /*
412413 * We should return the minimum buffer size which will fit a
413414 * null-terminated list of all the extended attribute names.
414415 */
415- return len ;
416+ err = len ;
417+ goto out_err ;
418+ }
416419
417- if (len > size )
418- return - ERANGE ;
420+ if (len > size ) {
421+ err = - ERANGE ;
422+ goto out_err ;
423+ }
419424
420425 lowest_xent_key (c , & key , host -> i_ino );
421426 while (1 ) {
@@ -437,15 +442,20 @@ ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size)
437442 pxent = xent ;
438443 key_read (c , & xent -> key , & key );
439444 }
440-
441445 kfree (pxent );
446+ up_read (& host_ui -> xattr_sem );
447+
442448 if (err != - ENOENT ) {
443449 ubifs_err (c , "cannot find next direntry, error %d" , err );
444450 return err ;
445451 }
446452
447453 ubifs_assert (c , written <= size );
448454 return written ;
455+
456+ out_err :
457+ up_read (& host_ui -> xattr_sem );
458+ return err ;
449459}
450460
451461static int remove_xattr (struct ubifs_info * c , struct inode * host ,
@@ -504,6 +514,7 @@ int ubifs_purge_xattrs(struct inode *host)
504514 ubifs_warn (c , "inode %lu has too many xattrs, doing a non-atomic deletion" ,
505515 host -> i_ino );
506516
517+ down_write (& ubifs_inode (host )-> xattr_sem );
507518 lowest_xent_key (c , & key , host -> i_ino );
508519 while (1 ) {
509520 xent = ubifs_tnc_next_ent (c , & key , & nm );
@@ -523,7 +534,7 @@ int ubifs_purge_xattrs(struct inode *host)
523534 ubifs_ro_mode (c , err );
524535 kfree (pxent );
525536 kfree (xent );
526- return err ;
537+ goto out_err ;
527538 }
528539
529540 ubifs_assert (c , ubifs_inode (xino )-> xattr );
@@ -535,7 +546,7 @@ int ubifs_purge_xattrs(struct inode *host)
535546 kfree (xent );
536547 iput (xino );
537548 ubifs_err (c , "cannot remove xattr, error %d" , err );
538- return err ;
549+ goto out_err ;
539550 }
540551
541552 iput (xino );
@@ -544,14 +555,19 @@ int ubifs_purge_xattrs(struct inode *host)
544555 pxent = xent ;
545556 key_read (c , & xent -> key , & key );
546557 }
547-
548558 kfree (pxent );
559+ up_write (& ubifs_inode (host )-> xattr_sem );
560+
549561 if (err != - ENOENT ) {
550562 ubifs_err (c , "cannot find next direntry, error %d" , err );
551563 return err ;
552564 }
553565
554566 return 0 ;
567+
568+ out_err :
569+ up_write (& ubifs_inode (host )-> xattr_sem );
570+ return err ;
555571}
556572
557573/**
@@ -594,6 +610,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
594610 if (!xent )
595611 return - ENOMEM ;
596612
613+ down_write (& ubifs_inode (host )-> xattr_sem );
597614 xent_key_init (c , & key , host -> i_ino , & nm );
598615 err = ubifs_tnc_lookup_nm (c , & key , xent , & nm );
599616 if (err ) {
@@ -618,6 +635,7 @@ static int ubifs_xattr_remove(struct inode *host, const char *name)
618635 iput (inode );
619636
620637out_free :
638+ up_write (& ubifs_inode (host )-> xattr_sem );
621639 kfree (xent );
622640 return err ;
623641}
0 commit comments