lease->new_state = 0;
        lease->flags = lctx->flags;
        lease->duration = lctx->duration;
+       lease->is_dir = lctx->is_dir;
        memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE);
        lease->version = lctx->version;
        lease->epoch = le16_to_cpu(lctx->epoch);
                        /* upgrading lease */
                        if ((atomic_read(&ci->op_count) +
                             atomic_read(&ci->sop_count)) == 1) {
-                               if (lease->state ==
-                                   (lctx->req_state & lease->state)) {
+                               if (lease->state != SMB2_LEASE_NONE_LE &&
+                                   lease->state == (lctx->req_state & lease->state)) {
                                        lease->state |= lctx->req_state;
                                        if (lctx->req_state &
                                                SMB2_LEASE_WRITE_CACHING_LE)
                                                lease_read_to_write(opinfo);
+
                                }
                        } else if ((atomic_read(&ci->op_count) +
                                    atomic_read(&ci->sop_count)) > 1) {
                                        lease->new_state =
                                                SMB2_LEASE_READ_CACHING_LE;
                        } else {
-                               if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE)
+                               if (lease->state & SMB2_LEASE_HANDLE_CACHING_LE &&
+                                               !lease->is_dir)
                                        lease->new_state =
                                                SMB2_LEASE_READ_CACHING_LE;
                                else
        }
 }
 
+void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
+                                     struct lease_ctx_info *lctx)
+{
+       struct oplock_info *opinfo;
+       struct ksmbd_inode *p_ci = NULL;
+
+       if (lctx->version != 2)
+               return;
+
+       p_ci = ksmbd_inode_lookup_lock(fp->filp->f_path.dentry->d_parent);
+       if (!p_ci)
+               return;
+
+       read_lock(&p_ci->m_lock);
+       list_for_each_entry(opinfo, &p_ci->m_op_list, op_entry) {
+               if (!opinfo->is_lease)
+                       continue;
+
+               if (opinfo->o_lease->state != SMB2_OPLOCK_LEVEL_NONE &&
+                   (!(lctx->flags & SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE) ||
+                    !compare_guid_key(opinfo, fp->conn->ClientGUID,
+                                     lctx->parent_lease_key))) {
+                       if (!atomic_inc_not_zero(&opinfo->refcount))
+                               continue;
+
+                       atomic_inc(&opinfo->conn->r_count);
+                       if (ksmbd_conn_releasing(opinfo->conn)) {
+                               atomic_dec(&opinfo->conn->r_count);
+                               continue;
+                       }
+
+                       read_unlock(&p_ci->m_lock);
+                       oplock_break(opinfo, SMB2_OPLOCK_LEVEL_NONE);
+                       opinfo_conn_put(opinfo);
+                       read_lock(&p_ci->m_lock);
+               }
+       }
+       read_unlock(&p_ci->m_lock);
+
+       ksmbd_inode_put(p_ci);
+}
+
 /**
  * smb_grant_oplock() - handle oplock/lease request on file open
  * @work:              smb work
                struct create_lease_v2 *lc = (struct create_lease_v2 *)cc;
 
                memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE);
-               if (is_dir)
+               if (is_dir) {
                        lreq->req_state = lc->lcontext.LeaseState &
                                ~SMB2_LEASE_WRITE_CACHING_LE;
-               else
+                       lreq->is_dir = true;
+               } else
                        lreq->req_state = lc->lcontext.LeaseState;
                lreq->flags = lc->lcontext.LeaseFlags;
                lreq->epoch = lc->lcontext.Epoch;
 
        __u8                    parent_lease_key[SMB2_LEASE_KEY_SIZE];
        __le16                  epoch;
        int                     version;
+       bool                    is_dir;
 };
 
 struct lease_table {
        __u8                    parent_lease_key[SMB2_LEASE_KEY_SIZE];
        int                     version;
        unsigned short          epoch;
+       bool                    is_dir;
        struct lease_table      *l_lb;
 };
 
 int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci,
                        struct lease_ctx_info *lctx);
 void destroy_lease_table(struct ksmbd_conn *conn);
+void smb_send_parent_lease_break_noti(struct ksmbd_file *fp,
+                                     struct lease_ctx_info *lctx);
 #endif /* __KSMBD_OPLOCK_H */
 
        return __ksmbd_inode_lookup(fp->filp->f_path.dentry);
 }
 
+struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d)
+{
+       struct ksmbd_inode *ci;
+
+       read_lock(&inode_hash_lock);
+       ci = __ksmbd_inode_lookup(d);
+       read_unlock(&inode_hash_lock);
+
+       return ci;
+}
+
 int ksmbd_query_inode_status(struct dentry *dentry)
 {
        struct ksmbd_inode *ci;
        kfree(ci);
 }
 
-static void ksmbd_inode_put(struct ksmbd_inode *ci)
+void ksmbd_inode_put(struct ksmbd_inode *ci)
 {
        if (atomic_dec_and_test(&ci->m_count))
                ksmbd_inode_free(ci);