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

new helper: destroy_unused_super()

Used for disposal of super_block instances that had never been reachable
via any shared data structures. No need for RCU delay in there, everything
can be called directly.

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

Al Viro 0200894d 6aa211e8

+19 -12
+19 -12
fs/super.c
··· 171 171 call_rcu(&s->rcu, destroy_super_rcu); 172 172 } 173 173 174 + /* Free a superblock that has never been seen by anyone */ 175 + static void destroy_unused_super(struct super_block *s) 176 + { 177 + if (!s) 178 + return; 179 + up_write(&s->s_umount); 180 + list_lru_destroy(&s->s_dentry_lru); 181 + list_lru_destroy(&s->s_inode_lru); 182 + security_sb_free(s); 183 + put_user_ns(s->s_user_ns); 184 + kfree(s->s_subtype); 185 + /* no delays needed */ 186 + destroy_super_work(&s->destroy_work); 187 + } 188 + 174 189 /** 175 190 * alloc_super - create new superblock 176 191 * @type: filesystem type superblock should belong to ··· 271 256 return s; 272 257 273 258 fail: 274 - destroy_super(s); 259 + destroy_unused_super(s); 275 260 return NULL; 276 261 } 277 262 ··· 499 484 continue; 500 485 if (user_ns != old->s_user_ns) { 501 486 spin_unlock(&sb_lock); 502 - if (s) { 503 - up_write(&s->s_umount); 504 - destroy_super(s); 505 - } 487 + destroy_unused_super(s); 506 488 return ERR_PTR(-EBUSY); 507 489 } 508 490 if (!grab_super(old)) 509 491 goto retry; 510 - if (s) { 511 - up_write(&s->s_umount); 512 - destroy_super(s); 513 - s = NULL; 514 - } 492 + destroy_unused_super(s); 515 493 return old; 516 494 } 517 495 } ··· 519 511 err = set(s, data); 520 512 if (err) { 521 513 spin_unlock(&sb_lock); 522 - up_write(&s->s_umount); 523 - destroy_super(s); 514 + destroy_unused_super(s); 524 515 return ERR_PTR(err); 525 516 } 526 517 s->s_type = type;