Re: [PATCH] CIFS: Fix kernel crash on simultaneous mount/umount calls

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



2011/6/9 Christoph Hellwig <hch@xxxxxxxxxxxxx>:
>>  static void
>>  cifs_put_super(struct super_block *sb)
>>  {
>> +     struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
>> +     if (cifs_sb == NULL) {
>> +             cFYI(1, "Empty cifs superblock info passed to put_super");
>> +             return;
>> +     }
>> +
>> +     bdi_destroy(&cifs_sb->bdi);
>
> This means you have a problem with the lifetime rules in cifs_do_mount.
>
> The VFS only calls ->put_super if sb->s_root is set.  So the rules for
> the mount handler are to only set s_root once the superblock is fully
> set up.
>
> Also you should never call cifs_umount from the error handling in
> cifs_do_mount.  Until s_root is set, please unwind manually, after
> that leave it to ->put_super.
>
>
>> +
>> +static void
>> +cifs_kill_super(struct super_block *sb)
>> +{
>
> This also seems quite broken.  If you fix up the mount path like
> I suggested it won't be nessecary.
>
>>       int rc = 0;
>>       struct cifs_sb_info *cifs_sb;
>>
>>       cFYI(1, "In cifs_put_super");
>>       cifs_sb = CIFS_SB(sb);
>>       if (cifs_sb == NULL) {
>
> And this check should also be removed.
>
>

It seems to me that I didn't understand your points clearly.

That's how I reproduce the problem:
1) one process does mount/umount calls in a loop;
2) another process does mount and umount calls.

As the result, kernel crashes sometimes on mount of the second
process, sometimes - on umount of the second process. The problem is
that:

one of these two processes process umount call. So, it comes to
cifs_put_super, calls cifs_umount and then calls kfree(cifs_sb).  In
the same time, another process comes into cifs_do_mount and calls
sget(). Then it appers into cifs_match_super that thinks that all
structures like server, ses, tcon and cifs_sb are valid, but it is not
true - the first process has already freed them but didn't remove
superblock from fs_supers list.

So, I simply reodered calls: now umount codepath marks a superblock as
non-active and calls kill_sb(new cifs_kill_super), it calls
kill_anon_super (that calls cifs_put_super and removes superblock from
fs_supers list) and after that kill_sb frees all cifs structures
(server, ses, tcon, cifs_sb).

As the result, when we get into cifs_match_super (in mount from
another process) we are sure that all cifs structures are valid.

If I am not right, correct me, please!

-- 
Best regards,
Pavel Shilovsky.
--
To unsubscribe from this list: send the line "unsubscribe linux-cifs" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux