]> Git Repo - J-linux.git/commitdiff
Merge tag '5.13-rc-smb3-part2' of git://git.samba.org/sfrench/cifs-2.6
authorLinus Torvalds <[email protected]>
Wed, 5 May 2021 20:37:07 +0000 (13:37 -0700)
committerLinus Torvalds <[email protected]>
Wed, 5 May 2021 20:37:07 +0000 (13:37 -0700)
Pull cifs updates from Steve French:
 "Ten CIFS/SMB3 changes - including two marked for stable - including
  some important multichannel fixes, as well as support for handle
  leases (deferred close) and shutdown support:

   - some important multichannel fixes

   - support for handle leases (deferred close)

   - shutdown support (which is also helpful since it enables multiple
     xfstests)

   - enable negotiating stronger encryption by default (GCM256)

   - improve wireshark debugging by allowing more options for root to
     dump decryption keys

  SambaXP and the SMB3 Plugfest test event are going on now so I am
  expecting more patches over the next few days due to extra testing
  (including more multichannel fixes)"

* tag '5.13-rc-smb3-part2' of git://git.samba.org/sfrench/cifs-2.6:
  fs/cifs: Fix resource leak
  Cifs: Fix kernel oops caused by deferred close for files.
  cifs: fix regression when mounting shares with prefix paths
  cifs: use echo_interval even when connection not ready.
  cifs: detect dead connections only when echoes are enabled.
  smb3.1.1: allow dumping keys for multiuser mounts
  smb3.1.1: allow dumping GCM256 keys to improve debugging of encrypted shares
  cifs: add shutdown support
  cifs: Deferred close for files
  smb3.1.1: enable negotiating stronger encryption by default

1  2 
fs/cifs/cifsproto.h
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c

diff --combined fs/cifs/cifsproto.h
index a79d50001fbfb417bec46ba78d49d1a72e3ffbd4,3c6b97ef39d3b7ead1b61f51a473f03db553bf99..d30cba44ba2962c8b6718b1ca4d2ef652cf84461
@@@ -205,7 -205,7 +205,7 @@@ extern void cifs_unix_basic_to_fattr(st
                                     struct cifs_sb_info *cifs_sb);
  extern void cifs_dir_info_to_fattr(struct cifs_fattr *, FILE_DIRECTORY_INFO *,
                                        struct cifs_sb_info *);
 -extern void cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
 +extern int cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr);
  extern struct inode *cifs_iget(struct super_block *sb,
                               struct cifs_fattr *fattr);
  
@@@ -267,6 -267,19 +267,19 @@@ extern void cifs_add_pending_open_locke
                                         struct tcon_link *tlink,
                                         struct cifs_pending_open *open);
  extern void cifs_del_pending_open(struct cifs_pending_open *open);
+ extern bool cifs_is_deferred_close(struct cifsFileInfo *cfile,
+                               struct cifs_deferred_close **dclose);
+ extern void cifs_add_deferred_close(struct cifsFileInfo *cfile,
+                               struct cifs_deferred_close *dclose);
+ extern void cifs_del_deferred_close(struct cifsFileInfo *cfile);
+ extern void cifs_close_deferred_file(struct cifsInodeInfo *cifs_inode);
+ extern void cifs_close_all_deferred_files(struct cifs_tcon *cifs_tcon);
  extern struct TCP_Server_Info *cifs_get_tcp_session(struct smb3_fs_context *ctx);
  extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
                                 int from_reconnect);
diff --combined fs/cifs/dir.c
index c85aff838305338d410908036c423e3a9a55aef9,263720131986c7a738a0b07a6a7e50f1201141c3..6bcd3e8f7cdae4710e489e8785a2b752bd760740
@@@ -34,6 -34,7 +34,7 @@@
  #include "cifs_fs_sb.h"
  #include "cifs_unicode.h"
  #include "fs_context.h"
+ #include "cifs_ioctl.h"
  
  static void
  renew_parental_timestamps(struct dentry *direntry)
@@@ -374,16 -375,15 +375,16 @@@ cifs_create_get_file_info
                if (newinode) {
                        if (server->ops->set_lease_key)
                                server->ops->set_lease_key(newinode, fid);
 -                      if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
 -                              newinode->i_mode = mode;
 -                      if ((*oplock & CIFS_CREATE_ACTION) &&
 -                          (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID)) {
 -                              newinode->i_uid = current_fsuid();
 -                              if (inode->i_mode & S_ISGID)
 -                                      newinode->i_gid = inode->i_gid;
 -                              else
 -                                      newinode->i_gid = current_fsgid();
 +                      if ((*oplock & CIFS_CREATE_ACTION) && S_ISREG(newinode->i_mode)) {
 +                              if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_DYNPERM)
 +                                      newinode->i_mode = mode;
 +                              if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
 +                                      newinode->i_uid = current_fsuid();
 +                                      if (inode->i_mode & S_ISGID)
 +                                              newinode->i_gid = inode->i_gid;
 +                                      else
 +                                              newinode->i_gid = current_fsgid();
 +                              }
                        }
                }
        }
@@@ -430,6 -430,9 +431,9 @@@ cifs_atomic_open(struct inode *inode, s
        __u32 oplock;
        struct cifsFileInfo *file_info;
  
+       if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
+               return -EIO;
        /*
         * Posix open is only called (at lookup time) for file create now. For
         * opens (rather than creates), because we do not know if it is a file
@@@ -546,6 -549,9 +550,9 @@@ int cifs_create(struct user_namespace *
        cifs_dbg(FYI, "cifs_create parent inode = 0x%p name is: %pd and dentry = 0x%p\n",
                 inode, direntry, direntry);
  
+       if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
+               return -EIO;
        tlink = cifs_sb_tlink(CIFS_SB(inode->i_sb));
        rc = PTR_ERR(tlink);
        if (IS_ERR(tlink))
@@@ -583,6 -589,9 +590,9 @@@ int cifs_mknod(struct user_namespace *m
                return -EINVAL;
  
        cifs_sb = CIFS_SB(inode->i_sb);
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
diff --combined fs/cifs/file.c
index 639c59596d4f3665dfafd057298c421b7e2b407f,919c82d4713dfa8835385cbfdfae4d493a597f24..6caad100c3f36b78e94c387c5f3c6b6feeab9dd8
@@@ -45,6 -45,7 +45,7 @@@
  #include "fscache.h"
  #include "smbdirect.h"
  #include "fs_context.h"
+ #include "cifs_ioctl.h"
  
  static inline int cifs_convert_flags(unsigned int flags)
  {
@@@ -166,7 -167,7 +167,7 @@@ int cifs_posix_open(const char *full_pa
                }
        } else {
                cifs_revalidate_mapping(*pinode);
 -              cifs_fattr_to_inode(*pinode, &fattr);
 +              rc = cifs_fattr_to_inode(*pinode, &fattr);
        }
  
  posix_open_ret:
@@@ -322,9 -323,12 +323,12 @@@ cifs_new_fileinfo(struct cifs_fid *fid
        cfile->dentry = dget(dentry);
        cfile->f_flags = file->f_flags;
        cfile->invalidHandle = false;
+       cfile->oplock_break_received = false;
+       cfile->deferred_scheduled = false;
        cfile->tlink = cifs_get_tlink(tlink);
        INIT_WORK(&cfile->oplock_break, cifs_oplock_break);
        INIT_WORK(&cfile->put, cifsFileInfo_put_work);
+       INIT_DELAYED_WORK(&cfile->deferred, smb2_deferred_work_close);
        mutex_init(&cfile->fh_mutex);
        spin_lock_init(&cfile->file_info_lock);
  
@@@ -539,6 -543,11 +543,11 @@@ int cifs_open(struct inode *inode, stru
        xid = get_xid();
  
        cifs_sb = CIFS_SB(inode->i_sb);
+       if (unlikely(cifs_forced_shutdown(cifs_sb))) {
+               free_xid(xid);
+               return -EIO;
+       }
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink)) {
                free_xid(xid);
                        file->f_op = &cifs_file_direct_ops;
        }
  
+       spin_lock(&CIFS_I(inode)->deferred_lock);
+       /* Get the cached handle as SMB2 close is deferred */
+       rc = cifs_get_readable_path(tcon, full_path, &cfile);
+       if (rc == 0) {
+               if (file->f_flags == cfile->f_flags) {
+                       file->private_data = cfile;
+                       cifs_del_deferred_close(cfile);
+                       spin_unlock(&CIFS_I(inode)->deferred_lock);
+                       goto out;
+               } else {
+                       spin_unlock(&CIFS_I(inode)->deferred_lock);
+                       _cifsFileInfo_put(cfile, true, false);
+               }
+       } else {
+               spin_unlock(&CIFS_I(inode)->deferred_lock);
+       }
        if (server->oplocks)
                oplock = REQ_OPLOCK;
        else
@@@ -846,11 -872,56 +872,56 @@@ reopen_error_exit
        return rc;
  }
  
+ void smb2_deferred_work_close(struct work_struct *work)
+ {
+       struct cifsFileInfo *cfile = container_of(work,
+                       struct cifsFileInfo, deferred.work);
+       spin_lock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+       if (!cfile->deferred_scheduled) {
+               spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+               return;
+       }
+       cifs_del_deferred_close(cfile);
+       cfile->deferred_scheduled = false;
+       spin_unlock(&CIFS_I(d_inode(cfile->dentry))->deferred_lock);
+       _cifsFileInfo_put(cfile, true, false);
+ }
  int cifs_close(struct inode *inode, struct file *file)
  {
+       struct cifsFileInfo *cfile;
+       struct cifsInodeInfo *cinode = CIFS_I(inode);
+       struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
+       struct cifs_deferred_close *dclose;
        if (file->private_data != NULL) {
-               _cifsFileInfo_put(file->private_data, true, false);
+               cfile = file->private_data;
                file->private_data = NULL;
+               dclose = kmalloc(sizeof(struct cifs_deferred_close), GFP_KERNEL);
+               if ((cinode->oplock == CIFS_CACHE_RHW_FLG) &&
+                   dclose) {
+                       if (test_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags))
+                               inode->i_ctime = inode->i_mtime = current_time(inode);
+                       spin_lock(&cinode->deferred_lock);
+                       cifs_add_deferred_close(cfile, dclose);
+                       if (cfile->deferred_scheduled) {
+                               mod_delayed_work(deferredclose_wq,
+                                               &cfile->deferred, cifs_sb->ctx->acregmax);
+                       } else {
+                               /* Deferred close for files */
+                               queue_delayed_work(deferredclose_wq,
+                                               &cfile->deferred, cifs_sb->ctx->acregmax);
+                               cfile->deferred_scheduled = true;
+                               spin_unlock(&cinode->deferred_lock);
+                               return 0;
+                       }
+                       spin_unlock(&cinode->deferred_lock);
+                       _cifsFileInfo_put(cfile, true, false);
+               } else {
+                       _cifsFileInfo_put(cfile, true, false);
+                       kfree(dclose);
+               }
        }
  
        /* return code from the ->release op is always ignored */
@@@ -1920,8 -1991,10 +1991,10 @@@ cifs_write(struct cifsFileInfo *open_fi
  
        if (total_written > 0) {
                spin_lock(&d_inode(dentry)->i_lock);
-               if (*offset > d_inode(dentry)->i_size)
+               if (*offset > d_inode(dentry)->i_size) {
                        i_size_write(d_inode(dentry), *offset);
+                       d_inode(dentry)->i_blocks = (512 - 1 + *offset) >> 9;
+               }
                spin_unlock(&d_inode(dentry)->i_lock);
        }
        mark_inode_dirty_sync(d_inode(dentry));
@@@ -1947,7 -2020,8 +2020,8 @@@ struct cifsFileInfo *find_readable_file
                if (fsuid_only && !uid_eq(open_file->uid, current_fsuid()))
                        continue;
                if (OPEN_FMODE(open_file->f_flags) & FMODE_READ) {
-                       if (!open_file->invalidHandle) {
+                       if ((!open_file->invalidHandle) &&
+                               (!open_file->oplock_break_received)) {
                                /* found a good file */
                                /* lock it so it will not be closed on us */
                                cifsFileInfo_get(open_file);
@@@ -2476,6 -2550,8 +2550,8 @@@ retry
        if (cfile)
                cifsFileInfo_put(cfile);
        free_xid(xid);
+       /* Indication to update ctime and mtime as close is deferred */
+       set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
        return rc;
  }
  
@@@ -2577,13 -2653,17 +2653,17 @@@ static int cifs_write_end(struct file *
  
        if (rc > 0) {
                spin_lock(&inode->i_lock);
-               if (pos > inode->i_size)
+               if (pos > inode->i_size) {
                        i_size_write(inode, pos);
+                       inode->i_blocks = (512 - 1 + pos) >> 9;
+               }
                spin_unlock(&inode->i_lock);
        }
  
        unlock_page(page);
        put_page(page);
+       /* Indication to update ctime and mtime as close is deferred */
+       set_bit(CIFS_INO_MODIFIED_ATTR, &CIFS_I(inode)->flags);
  
        return rc;
  }
@@@ -4744,6 -4824,8 +4824,8 @@@ void cifs_oplock_break(struct work_stru
        struct TCP_Server_Info *server = tcon->ses->server;
        int rc = 0;
        bool purge_cache = false;
+       bool is_deferred = false;
+       struct cifs_deferred_close *dclose;
  
        wait_on_bit(&cinode->flags, CIFS_INODE_PENDING_WRITERS,
                        TASK_UNINTERRUPTIBLE);
@@@ -4790,6 -4872,18 +4872,18 @@@ oplock_break_ack
                                                             cinode);
                cifs_dbg(FYI, "Oplock release rc = %d\n", rc);
        }
+       /*
+        * When oplock break is received and there are no active
+        * file handles but cached, then set the flag oplock_break_received.
+        * So, new open will not use cached handle.
+        */
+       spin_lock(&CIFS_I(inode)->deferred_lock);
+       is_deferred = cifs_is_deferred_close(cfile, &dclose);
+       if (is_deferred && cfile->deferred_scheduled) {
+               cfile->oplock_break_received = true;
+               mod_delayed_work(deferredclose_wq, &cfile->deferred, 0);
+       }
+       spin_unlock(&CIFS_I(inode)->deferred_lock);
        _cifsFileInfo_put(cfile, false /* do not wait for ourself */, false);
        cifs_done_oplock_break(cinode);
  }
diff --combined fs/cifs/inode.c
index 002d864b8f7b5bd6e562c7acbaa792394cbc86ff,591f18e3e933bc3026edc6e27d0b3a2281b54a03..1dfa57982522bdf8f9c59a22c026d6fc73159629
@@@ -26,7 -26,6 +26,6 @@@
  #include <linux/sched/signal.h>
  #include <linux/wait_bit.h>
  #include <linux/fiemap.h>
  #include <asm/div64.h>
  #include "cifsfs.h"
  #include "cifspdu.h"
@@@ -38,7 -37,7 +37,7 @@@
  #include "cifs_unicode.h"
  #include "fscache.h"
  #include "fs_context.h"
+ #include "cifs_ioctl.h"
  
  static void cifs_set_ops(struct inode *inode)
  {
@@@ -157,18 -156,12 +156,18 @@@ cifs_nlink_fattr_to_inode(struct inode 
  }
  
  /* populate an inode with info from a cifs_fattr struct */
 -void
 +int
  cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
  {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
  
 +      if (!(inode->i_state & I_NEW) &&
 +          unlikely(inode_wrong_type(inode, fattr->cf_mode))) {
 +              CIFS_I(inode)->time = 0; /* force reval */
 +              return -ESTALE;
 +      }
 +
        cifs_revalidate_cache(inode, fattr);
  
        spin_lock(&inode->i_lock);
                inode->i_flags |= S_AUTOMOUNT;
        if (inode->i_state & I_NEW)
                cifs_set_ops(inode);
 +      return 0;
  }
  
  void
@@@ -370,7 -362,7 +369,7 @@@ cifs_get_file_info_unix(struct file *fi
                rc = 0;
        }
  
 -      cifs_fattr_to_inode(inode, &fattr);
 +      rc = cifs_fattr_to_inode(inode, &fattr);
        free_xid(xid);
        return rc;
  }
@@@ -433,7 -425,14 +432,7 @@@ int cifs_get_inode_info_unix(struct ino
                }
  
                /* if filetype is different, return error */
 -              if (unlikely(((*pinode)->i_mode & S_IFMT) !=
 -                  (fattr.cf_mode & S_IFMT))) {
 -                      CIFS_I(*pinode)->time = 0; /* force reval */
 -                      rc = -ESTALE;
 -                      goto cgiiu_exit;
 -              }
 -
 -              cifs_fattr_to_inode(*pinode, &fattr);
 +              rc = cifs_fattr_to_inode(*pinode, &fattr);
        }
  
  cgiiu_exit:
@@@ -783,8 -782,7 +782,8 @@@ cifs_get_file_info(struct file *filp
         */
        fattr.cf_uniqueid = CIFS_I(inode)->uniqueid;
        fattr.cf_flags |= CIFS_FATTR_NEED_REVAL;
 -      cifs_fattr_to_inode(inode, &fattr);
 +      /* if filetype is different, return error */
 +      rc = cifs_fattr_to_inode(inode, &fattr);
  cgfi_exit:
        free_xid(xid);
        return rc;
@@@ -1101,8 -1099,16 +1100,8 @@@ handle_mnt_opt
                        rc = -ESTALE;
                        goto out;
                }
 -
                /* if filetype is different, return error */
 -              if (unlikely(((*inode)->i_mode & S_IFMT) !=
 -                  (fattr.cf_mode & S_IFMT))) {
 -                      CIFS_I(*inode)->time = 0; /* force reval */
 -                      rc = -ESTALE;
 -                      goto out;
 -              }
 -
 -              cifs_fattr_to_inode(*inode, &fattr);
 +              rc = cifs_fattr_to_inode(*inode, &fattr);
        }
  out:
        cifs_buf_release(smb1_backup_rsp_buf);
@@@ -1208,7 -1214,14 +1207,7 @@@ smb311_posix_get_inode_info(struct inod
                }
  
                /* if filetype is different, return error */
 -              if (unlikely(((*inode)->i_mode & S_IFMT) !=
 -                  (fattr.cf_mode & S_IFMT))) {
 -                      CIFS_I(*inode)->time = 0; /* force reval */
 -                      rc = -ESTALE;
 -                      goto out;
 -              }
 -
 -              cifs_fattr_to_inode(*inode, &fattr);
 +              rc = cifs_fattr_to_inode(*inode, &fattr);
        }
  out:
        cifs_put_tlink(tlink);
@@@ -1235,7 -1248,7 +1234,7 @@@ cifs_find_inode(struct inode *inode, vo
                return 0;
  
        /* don't match inode of different type */
 -      if ((inode->i_mode & S_IFMT) != (fattr->cf_mode & S_IFMT))
 +      if (inode_wrong_type(inode, fattr->cf_mode))
                return 0;
  
        /* if it's not a directory or has no dentries, then flag it */
@@@ -1303,7 -1316,6 +1302,7 @@@ retry_iget5_locked
                        }
                }
  
 +              /* can't fail - see cifs_find_inode() */
                cifs_fattr_to_inode(inode, fattr);
                if (sb->s_flags & SB_NOATIME)
                        inode->i_flags |= S_NOATIME | S_NOCMTIME;
@@@ -1610,6 -1622,9 +1609,9 @@@ int cifs_unlink(struct inode *dir, stru
  
        cifs_dbg(FYI, "cifs_unlink, dir=0x%p, dentry=0x%p\n", dir, dentry);
  
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
                goto unlink_out;
        }
  
+       cifs_close_all_deferred_files(tcon);
        if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
                                le64_to_cpu(tcon->fsUnixInfo.Capability))) {
                rc = CIFSPOSIXDelFile(xid, tcon, full_path,
@@@ -1729,16 -1745,6 +1732,16 @@@ cifs_mkdir_qinfo(struct inode *parent, 
        if (rc)
                return rc;
  
 +      if (!S_ISDIR(inode->i_mode)) {
 +              /*
 +               * mkdir succeeded, but another client has managed to remove the
 +               * sucker and replace it with non-directory.  Return success,
 +               * but don't leave the child in dcache.
 +               */
 +               iput(inode);
 +               d_drop(dentry);
 +               return 0;
 +      }
        /*
         * setting nlink not necessary except in cases where we failed to get it
         * from the server or was set bogus. Also, since this is a brand new
                }
        }
        d_instantiate(dentry, inode);
 -      return rc;
 +      return 0;
  }
  
  static int
@@@ -1872,6 -1878,8 +1875,8 @@@ int cifs_mkdir(struct user_namespace *m
                 mode, inode);
  
        cifs_sb = CIFS_SB(inode->i_sb);
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
@@@ -1954,6 -1962,11 +1959,11 @@@ int cifs_rmdir(struct inode *inode, str
        }
  
        cifs_sb = CIFS_SB(inode->i_sb);
+       if (unlikely(cifs_forced_shutdown(cifs_sb))) {
+               rc = -EIO;
+               goto rmdir_exit;
+       }
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink)) {
                rc = PTR_ERR(tlink);
@@@ -2088,6 -2101,9 +2098,9 @@@ cifs_rename2(struct user_namespace *mnt
                return -EINVAL;
  
        cifs_sb = CIFS_SB(source_dir->i_sb);
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        tlink = cifs_sb_tlink(cifs_sb);
        if (IS_ERR(tlink))
                return PTR_ERR(tlink);
                goto cifs_rename_exit;
        }
  
+       cifs_close_all_deferred_files(tcon);
        rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
                            to_name);
  
@@@ -2404,6 -2421,9 +2418,9 @@@ int cifs_getattr(struct user_namespace 
        struct inode *inode = d_inode(dentry);
        int rc;
  
+       if (unlikely(cifs_forced_shutdown(CIFS_SB(inode->i_sb))))
+               return -EIO;
        /*
         * We need to be sure that all dirty pages are written and the server
         * has actual ctime, mtime and file length.
@@@ -2476,6 -2496,9 +2493,9 @@@ int cifs_fiemap(struct inode *inode, st
        struct cifsFileInfo *cfile;
        int rc;
  
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        /*
         * We need to be sure that all dirty pages are written as they
         * might fill holes on the server.
@@@ -2962,6 -2985,9 +2982,9 @@@ cifs_setattr(struct user_namespace *mnt
        struct cifs_tcon *pTcon = cifs_sb_master_tcon(cifs_sb);
        int rc, retries = 0;
  
+       if (unlikely(cifs_forced_shutdown(cifs_sb)))
+               return -EIO;
        do {
                if (pTcon->unix_ext)
                        rc = cifs_setattr_unix(direntry, attrs);
This page took 0.08125 seconds and 4 git commands to generate.