Commit cac45b062c67f86dc1d91d675128838773523243

Authored by Al Viro
1 parent 2e32cf5ef2

fat: rcu-delay unloading nls and freeing sbi

makes ->d_hash() and ->d_compare() safety in RCU mode independent
from vfsmount_lock.

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>

Showing 2 changed files with 12 additions and 8 deletions Side-by-side Diff

... ... @@ -102,6 +102,7 @@
102 102 struct hlist_head dir_hashtable[FAT_HASH_SIZE];
103 103  
104 104 unsigned int dirty; /* fs state before mount */
  105 + struct rcu_head rcu;
105 106 };
106 107  
107 108 #define FAT_CACHE_VALID 0 /* special case for valid cache */
... ... @@ -548,6 +548,16 @@
548 548 brelse(bh);
549 549 }
550 550  
  551 +static void delayed_free(struct rcu_head *p)
  552 +{
  553 + struct msdos_sb_info *sbi = container_of(p, struct msdos_sb_info, rcu);
  554 + unload_nls(sbi->nls_disk);
  555 + unload_nls(sbi->nls_io);
  556 + if (sbi->options.iocharset != fat_default_iocharset)
  557 + kfree(sbi->options.iocharset);
  558 + kfree(sbi);
  559 +}
  560 +
551 561 static void fat_put_super(struct super_block *sb)
552 562 {
553 563 struct msdos_sb_info *sbi = MSDOS_SB(sb);
... ... @@ -557,14 +567,7 @@
557 567 iput(sbi->fsinfo_inode);
558 568 iput(sbi->fat_inode);
559 569  
560   - unload_nls(sbi->nls_disk);
561   - unload_nls(sbi->nls_io);
562   -
563   - if (sbi->options.iocharset != fat_default_iocharset)
564   - kfree(sbi->options.iocharset);
565   -
566   - sb->s_fs_info = NULL;
567   - kfree(sbi);
  570 + call_rcu(&sbi->rcu, delayed_free);
568 571 }
569 572  
570 573 static struct kmem_cache *fat_inode_cachep;