Re: [PATCH] cifs: add spinlock for the openFileList to cifsInodeInfo

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

 



вт, 4 июн. 2019 г. в 17:42, Ronnie Sahlberg <lsahlber@xxxxxxxxxx>:
>
> We can not depend on the tcon->open_file_lock here since in multiuser mode
> we may have the same file/inode open via multiple different tcons.
>
> The current code is race prone and will crash if one user deletes a file
> at the same time a different user opens/create the file.
>
> To avoid this we need to have a spinlock attached to the inode and not the tcon.
>
> RHBZ:  1580165
>
> CC: Stable <stable@xxxxxxxxxxxxxxx>
> Signed-off-by: Ronnie Sahlberg <lsahlber@xxxxxxxxxx>
> ---
>  fs/cifs/cifsfs.c   | 1 +
>  fs/cifs/cifsglob.h | 1 +
>  fs/cifs/file.c     | 8 ++++++--
>  3 files changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c
> index f5fcd6360056..65d9771e49f9 100644
> --- a/fs/cifs/cifsfs.c
> +++ b/fs/cifs/cifsfs.c
> @@ -303,6 +303,7 @@ cifs_alloc_inode(struct super_block *sb)
>         cifs_inode->uniqueid = 0;
>         cifs_inode->createtime = 0;
>         cifs_inode->epoch = 0;
> +       spin_lock_init(&cifs_inode->open_file_lock);
>         generate_random_uuid(cifs_inode->lease_key);
>
>         /*
> diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h
> index 334ff5f9c3f3..733ddd5fd480 100644
> --- a/fs/cifs/cifsglob.h
> +++ b/fs/cifs/cifsglob.h
> @@ -1377,6 +1377,7 @@ struct cifsInodeInfo {
>         struct rw_semaphore lock_sem;   /* protect the fields above */
>         /* BB add in lists for dirty pages i.e. write caching info for oplock */
>         struct list_head openFileList;
> +       spinlock_t      open_file_lock; /* protects openFileList */
>         __u32 cifsAttrs; /* e.g. DOS archive bit, sparse, compressed, system */
>         unsigned int oplock;            /* oplock/lease level we have */
>         unsigned int epoch;             /* used to track lease state changes */
> diff --git a/fs/cifs/file.c b/fs/cifs/file.c
> index 06e27ac6d82c..97090693d182 100644
> --- a/fs/cifs/file.c
> +++ b/fs/cifs/file.c
> @@ -338,10 +338,12 @@ cifs_new_fileinfo(struct cifs_fid *fid, struct file *file,
>         atomic_inc(&tcon->num_local_opens);
>
>         /* if readable file instance put first in list*/
> +       spin_lock(&cinode->open_file_lock);
>         if (file->f_mode & FMODE_READ)
>                 list_add(&cfile->flist, &cinode->openFileList);
>         else
>                 list_add_tail(&cfile->flist, &cinode->openFileList);
> +       spin_unlock(&cinode->open_file_lock);
>         spin_unlock(&tcon->open_file_lock);
>
>         if (fid->purge_cache)
> @@ -413,7 +415,9 @@ void _cifsFileInfo_put(struct cifsFileInfo *cifs_file, bool wait_oplock_handler)
>         cifs_add_pending_open_locked(&fid, cifs_file->tlink, &open);
>
>         /* remove it from the lists */
> +       spin_lock(&cifsi->open_file_lock);
>         list_del(&cifs_file->flist);
> +       spin_unlock(&cifsi->open_file_lock);
>         list_del(&cifs_file->tlist);
>         atomic_dec(&tcon->num_local_opens);
>
> @@ -1950,9 +1954,9 @@ cifs_get_writable_file(struct cifsInodeInfo *cifs_inode, bool fsuid_only,
>                         return 0;
>                 }
>
> -               spin_lock(&tcon->open_file_lock);
> +               spin_lock(&cifs_inode->open_file_lock);
>                 list_move_tail(&inv_file->flist, &cifs_inode->openFileList);
> -               spin_unlock(&tcon->open_file_lock);
> +               spin_unlock(&cifs_inode->open_file_lock);
>                 cifsFileInfo_put(inv_file);
>                 ++refind;
>                 inv_file = NULL;
> --
> 2.13.6
>

Thanks for the patch. Looks good to me.

Reviewed-by: Pavel Shilovsky <pshilov@xxxxxxxxxxxxx>

I would only add a comment telling what an order of the locks should
be: cifs_tcon.open_file_lock and then cifsInodeInfo.open_file_lock.

--
Best regards,
Pavel Shilovsky




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

  Powered by Linux