From nobody Wed Apr 29 00:43:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8A06C433F5 for ; Thu, 26 May 2022 01:17:58 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345647AbiEZBR4 (ORCPT ); Wed, 25 May 2022 21:17:56 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59178 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1343986AbiEZBRs (ORCPT ); Wed, 25 May 2022 21:17:48 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id D5D475799E for ; Wed, 25 May 2022 18:17:47 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1653527867; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=BY0uwuvfpByIIEbA88X1ubdt91de5QP6Qq8gloHmh0c=; b=Qf38dp/XqBo9d1R/w7Az8daw1ZtzJjeuzmGKnHhqu7PoP7GzeecIAa+qJsO8CNlYAUIlkz TLMDgQQJSywbCnMUFrgDTrAvSnNe3k05QtmrTNS8ccBDjQfJgKl/tRsIQD7qkVfkHsvcog 1R1ngyJBcXhE0xy60ItfXojam8qUJ7U= Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-348-IXXakG4mN7mno6SV09tZgQ-1; Wed, 25 May 2022 21:17:43 -0400 X-MC-Unique: IXXakG4mN7mno6SV09tZgQ-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.rdu2.redhat.com [10.11.54.6]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 3B6C638041C6; Thu, 26 May 2022 01:17:43 +0000 (UTC) Received: from localhost (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 903A32166B26; Thu, 26 May 2022 01:17:42 +0000 (UTC) From: Xiubo Li To: jlayton@kernel.org, idryomov@gmail.com, viro@zeniv.linux.org.uk Cc: willy@infradead.org, vshankar@redhat.com, ceph-devel@vger.kernel.org, arnd@arndb.de, mcgrof@kernel.org, akpm@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li Subject: [PATCH v6 1/2] fs/dcache: export d_same_name() helper Date: Thu, 26 May 2022 09:17:36 +0800 Message-Id: <20220526011737.371483-2-xiubli@redhat.com> In-Reply-To: <20220526011737.371483-1-xiubli@redhat.com> References: <20220526011737.371483-1-xiubli@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.78 on 10.11.54.6 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" Compare dentry name with case-exact name, return true if names are same, or false. Reviewed-by: Jeff Layton Signed-off-by: Xiubo Li Reviewed-by: Luis Chamberlain --- fs/dcache.c | 15 +++++++++++---- include/linux/dcache.h | 2 ++ 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 93f4f5ee07bf..a409312ee0df 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -2247,10 +2247,16 @@ struct dentry *d_add_ci(struct dentry *dentry, stru= ct inode *inode, } EXPORT_SYMBOL(d_add_ci); =20 - -static inline bool d_same_name(const struct dentry *dentry, - const struct dentry *parent, - const struct qstr *name) +/** + * d_same_name - compare dentry name with case-exact name + * @parent: parent dentry + * @dentry: the negative dentry that was passed to the parent's lookup func + * @name: the case-exact name to be associated with the returned dentry + * + * Return: true if names are same, or false + */ +bool d_same_name(const struct dentry *dentry, const struct dentry *parent, + const struct qstr *name) { if (likely(!(parent->d_flags & DCACHE_OP_COMPARE))) { if (dentry->d_name.len !=3D name->len) @@ -2261,6 +2267,7 @@ static inline bool d_same_name(const struct dentry *d= entry, dentry->d_name.len, dentry->d_name.name, name) =3D=3D 0; } +EXPORT_SYMBOL_GPL(d_same_name); =20 /** * __d_lookup_rcu - search for a dentry (racy, store-free) diff --git a/include/linux/dcache.h b/include/linux/dcache.h index f5bba51480b2..bb72361834de 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -233,6 +233,8 @@ extern struct dentry * d_alloc_parallel(struct dentry *= , const struct qstr *, wait_queue_head_t *); extern struct dentry * d_splice_alias(struct inode *, struct dentry *); extern struct dentry * d_add_ci(struct dentry *, struct inode *, struct qs= tr *); +extern bool d_same_name(const struct dentry *dentry, const struct dentry *= parent, + const struct qstr *name); extern struct dentry * d_exact_alias(struct dentry *, struct inode *); extern struct dentry *d_find_any_alias(struct inode *inode); extern struct dentry * d_obtain_alias(struct inode *); --=20 2.36.0.rc1 From nobody Wed Apr 29 00:43:47 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 13BA6C433EF for ; Thu, 26 May 2022 01:18:05 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1345715AbiEZBSC (ORCPT ); Wed, 25 May 2022 21:18:02 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:59604 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1345018AbiEZBRx (ORCPT ); Wed, 25 May 2022 21:17:53 -0400 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id EB25B58E6E for ; Wed, 25 May 2022 18:17:50 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1653527870; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=L7DKTRWHUfW72IV+NMbmGmzxRHshjNHpsUOa6bq/ra8=; b=P8j2uJhTATmFsScin755oWXgs+GVCVgOTin0rFA7QPzLF5kaBVAH0EO26RXdIwzs0pRcjB gaVZE7bhOvkm00d70yHKP69foUIO217Qv0+1hoJppwO3KF6tytRkhpAfj8lMs7eMyzzJht DdzWFj3cAyvp3mJXs4AFHZeRsO8i2iU= Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-451-E_40z-ueMDCkgE8PxzBaFA-1; Wed, 25 May 2022 21:17:46 -0400 X-MC-Unique: E_40z-ueMDCkgE8PxzBaFA-1 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.rdu2.redhat.com [10.11.54.3]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 2C46B85A5BC; Thu, 26 May 2022 01:17:46 +0000 (UTC) Received: from localhost (unknown [10.72.47.117]) by smtp.corp.redhat.com (Postfix) with ESMTP id 31980112131E; Thu, 26 May 2022 01:17:44 +0000 (UTC) From: Xiubo Li To: jlayton@kernel.org, idryomov@gmail.com, viro@zeniv.linux.org.uk Cc: willy@infradead.org, vshankar@redhat.com, ceph-devel@vger.kernel.org, arnd@arndb.de, mcgrof@kernel.org, akpm@linux-foundation.org, linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org, Xiubo Li , kernel test robot Subject: [PATCH v6 2/2] ceph: wait the first reply of inflight async unlink Date: Thu, 26 May 2022 09:17:37 +0800 Message-Id: <20220526011737.371483-3-xiubli@redhat.com> In-Reply-To: <20220526011737.371483-1-xiubli@redhat.com> References: <20220526011737.371483-1-xiubli@redhat.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 2.78 on 10.11.54.3 Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Type: text/plain; charset="utf-8" In async unlink case the kclient won't wait for the first reply from MDS and just drop all the links and unhash the dentry and then succeeds immediately. For any new create/link/rename,etc requests followed by using the same file names we must wait for the first reply of the inflight unlink request, or the MDS possibly will fail these following requests with -EEXIST if the inflight async unlink request was delayed for some reasons. And the worst case is that for the none async openc request it will successfully open the file if the CDentry hasn't been unlinked yet, but later the previous delayed async unlink request will remove the CDenty. That means the just created file is possiblly deleted later by accident. We need to wait for the inflight async unlink requests to finish when creating new files/directories by using the same file names. URL: https://tracker.ceph.com/issues/55332 Reported-by: kernel test robot Reviewed-by: Jeff Layton Signed-off-by: Xiubo Li --- fs/ceph/dir.c | 79 +++++++++++++++++++++++++++++++++++++++----- fs/ceph/file.c | 6 +++- fs/ceph/mds_client.c | 75 ++++++++++++++++++++++++++++++++++++++++- fs/ceph/mds_client.h | 1 + fs/ceph/super.c | 3 ++ fs/ceph/super.h | 19 ++++++++--- 6 files changed, 167 insertions(+), 16 deletions(-) diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c index eae417d71136..e7e2ebac330d 100644 --- a/fs/ceph/dir.c +++ b/fs/ceph/dir.c @@ -856,6 +856,10 @@ static int ceph_mknod(struct user_namespace *mnt_usern= s, struct inode *dir, if (ceph_snap(dir) !=3D CEPH_NOSNAP) return -EROFS; =20 + err =3D ceph_wait_on_conflict_unlink(dentry); + if (err) + return err; + if (ceph_quota_is_max_files_exceeded(dir)) { err =3D -EDQUOT; goto out; @@ -918,6 +922,10 @@ static int ceph_symlink(struct user_namespace *mnt_use= rns, struct inode *dir, if (ceph_snap(dir) !=3D CEPH_NOSNAP) return -EROFS; =20 + err =3D ceph_wait_on_conflict_unlink(dentry); + if (err) + return err; + if (ceph_quota_is_max_files_exceeded(dir)) { err =3D -EDQUOT; goto out; @@ -968,9 +976,13 @@ static int ceph_mkdir(struct user_namespace *mnt_usern= s, struct inode *dir, struct ceph_mds_client *mdsc =3D ceph_sb_to_mdsc(dir->i_sb); struct ceph_mds_request *req; struct ceph_acl_sec_ctx as_ctx =3D {}; - int err =3D -EROFS; + int err; int op; =20 + err =3D ceph_wait_on_conflict_unlink(dentry); + if (err) + return err; + if (ceph_snap(dir) =3D=3D CEPH_SNAPDIR) { /* mkdir .snap/foo is a MKSNAP */ op =3D CEPH_MDS_OP_MKSNAP; @@ -980,6 +992,7 @@ static int ceph_mkdir(struct user_namespace *mnt_userns= , struct inode *dir, dout("mkdir dir %p dn %p mode 0%ho\n", dir, dentry, mode); op =3D CEPH_MDS_OP_MKDIR; } else { + err =3D -EROFS; goto out; } =20 @@ -1037,6 +1050,10 @@ static int ceph_link(struct dentry *old_dentry, stru= ct inode *dir, struct ceph_mds_request *req; int err; =20 + err =3D ceph_wait_on_conflict_unlink(dentry); + if (err) + return err; + if (ceph_snap(dir) !=3D CEPH_NOSNAP) return -EROFS; =20 @@ -1071,9 +1088,27 @@ static int ceph_link(struct dentry *old_dentry, stru= ct inode *dir, static void ceph_async_unlink_cb(struct ceph_mds_client *mdsc, struct ceph_mds_request *req) { + struct dentry *dentry =3D req->r_dentry; + struct ceph_fs_client *fsc =3D ceph_sb_to_client(dentry->d_sb); + struct ceph_dentry_info *di =3D ceph_dentry(dentry); int result =3D req->r_err ? req->r_err : le32_to_cpu(req->r_reply_info.head->result); =20 + if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags)) + pr_warn("%s dentry %p:%pd async unlink bit is not set\n", + __func__, dentry, dentry); + + spin_lock(&fsc->async_unlink_conflict_lock); + hash_del_rcu(&di->hnode); + spin_unlock(&fsc->async_unlink_conflict_lock); + + spin_lock(&dentry->d_lock); + di->flags &=3D ~CEPH_DENTRY_ASYNC_UNLINK; + wake_up_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT); + spin_unlock(&dentry->d_lock); + + synchronize_rcu(); + if (result =3D=3D -EJUKEBOX) goto out; =20 @@ -1081,7 +1116,7 @@ static void ceph_async_unlink_cb(struct ceph_mds_clie= nt *mdsc, if (result) { int pathlen =3D 0; u64 base =3D 0; - char *path =3D ceph_mdsc_build_path(req->r_dentry, &pathlen, + char *path =3D ceph_mdsc_build_path(dentry, &pathlen, &base, 0); =20 /* mark error on parent + clear complete */ @@ -1089,13 +1124,13 @@ static void ceph_async_unlink_cb(struct ceph_mds_cl= ient *mdsc, ceph_dir_clear_complete(req->r_parent); =20 /* drop the dentry -- we don't know its status */ - if (!d_unhashed(req->r_dentry)) - d_drop(req->r_dentry); + if (!d_unhashed(dentry)) + d_drop(dentry); =20 /* mark inode itself for an error (since metadata is bogus) */ mapping_set_error(req->r_old_inode->i_mapping, result); =20 - pr_warn("ceph: async unlink failure path=3D(%llx)%s result=3D%d!\n", + pr_warn("async unlink failure path=3D(%llx)%s result=3D%d!\n", base, IS_ERR(path) ? "<>" : path, result); ceph_mdsc_free_path(path, pathlen); } @@ -1180,6 +1215,8 @@ static int ceph_unlink(struct inode *dir, struct dent= ry *dentry) =20 if (try_async && op =3D=3D CEPH_MDS_OP_UNLINK && (req->r_dir_caps =3D get_caps_for_async_unlink(dir, dentry))) { + struct ceph_dentry_info *di =3D ceph_dentry(dentry); + dout("async unlink on %llu/%.*s caps=3D%s", ceph_ino(dir), dentry->d_name.len, dentry->d_name.name, ceph_cap_string(req->r_dir_caps)); @@ -1187,6 +1224,16 @@ static int ceph_unlink(struct inode *dir, struct den= try *dentry) req->r_callback =3D ceph_async_unlink_cb; req->r_old_inode =3D d_inode(dentry); ihold(req->r_old_inode); + + spin_lock(&dentry->d_lock); + di->flags |=3D CEPH_DENTRY_ASYNC_UNLINK; + spin_unlock(&dentry->d_lock); + + spin_lock(&fsc->async_unlink_conflict_lock); + hash_add_rcu(fsc->async_unlink_conflict, &di->hnode, + dentry->d_name.hash); + spin_unlock(&fsc->async_unlink_conflict_lock); + err =3D ceph_mdsc_submit_request(mdsc, dir, req); if (!err) { /* @@ -1195,10 +1242,20 @@ static int ceph_unlink(struct inode *dir, struct de= ntry *dentry) */ drop_nlink(inode); d_delete(dentry); - } else if (err =3D=3D -EJUKEBOX) { - try_async =3D false; - ceph_mdsc_put_request(req); - goto retry; + } else { + spin_lock(&fsc->async_unlink_conflict_lock); + hash_del_rcu(&di->hnode); + spin_unlock(&fsc->async_unlink_conflict_lock); + + spin_lock(&dentry->d_lock); + di->flags &=3D ~CEPH_DENTRY_ASYNC_UNLINK; + spin_unlock(&dentry->d_lock); + + if (err =3D=3D -EJUKEBOX) { + try_async =3D false; + ceph_mdsc_put_request(req); + goto retry; + } } } else { set_bit(CEPH_MDS_R_PARENT_LOCKED, &req->r_req_flags); @@ -1237,6 +1294,10 @@ static int ceph_rename(struct user_namespace *mnt_us= erns, struct inode *old_dir, (!ceph_quota_is_same_realm(old_dir, new_dir))) return -EXDEV; =20 + err =3D ceph_wait_on_conflict_unlink(new_dentry); + if (err) + return err; + dout("rename dir %p dentry %p to dir %p dentry %p\n", old_dir, old_dentry, new_dir, new_dentry); req =3D ceph_mdsc_create_request(mdsc, op, USE_AUTH_MDS); diff --git a/fs/ceph/file.c b/fs/ceph/file.c index 8c8226c0feac..0f863e1d6ae9 100644 --- a/fs/ceph/file.c +++ b/fs/ceph/file.c @@ -569,7 +569,7 @@ static void ceph_async_create_cb(struct ceph_mds_client= *mdsc, char *path =3D ceph_mdsc_build_path(req->r_dentry, &pathlen, &base, 0); =20 - pr_warn("ceph: async create failure path=3D(%llx)%s result=3D%d!\n", + pr_warn("async create failure path=3D(%llx)%s result=3D%d!\n", base, IS_ERR(path) ? "<>" : path, result); ceph_mdsc_free_path(path, pathlen); =20 @@ -740,6 +740,10 @@ int ceph_atomic_open(struct inode *dir, struct dentry = *dentry, if (dentry->d_name.len > NAME_MAX) return -ENAMETOOLONG; =20 + err =3D ceph_wait_on_conflict_unlink(dentry); + if (err) + return err; + if (flags & O_CREAT) { if (ceph_quota_is_max_files_exceeded(dir)) return -EDQUOT; diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c index 8efb8927ffb9..4ced8d1e18ba 100644 --- a/fs/ceph/mds_client.c +++ b/fs/ceph/mds_client.c @@ -456,7 +456,7 @@ static int ceph_parse_deleg_inos(void **p, void *end, dout("added delegated inode 0x%llx\n", start - 1); } else if (err =3D=3D -EBUSY) { - pr_warn("ceph: MDS delegated inode 0x%llx more than once.\n", + pr_warn("MDS delegated inode 0x%llx more than once.\n", start - 1); } else { return err; @@ -655,6 +655,79 @@ static void destroy_reply_info(struct ceph_mds_reply_i= nfo_parsed *info) free_pages((unsigned long)info->dir_entries, get_order(info->dir_buf_size= )); } =20 +/* + * In async unlink case the kclient won't wait for the first reply + * from MDS and just drop all the links and unhash the dentry and then + * succeeds immediately. + * + * For any new create/link/rename,etc requests followed by using the + * same file names we must wait for the first reply of the inflight + * unlink request, or the MDS possibly will fail these following + * requests with -EEXIST if the inflight async unlink request was + * delayed for some reasons. + * + * And the worst case is that for the none async openc request it will + * successfully open the file if the CDentry hasn't been unlinked yet, + * but later the previous delayed async unlink request will remove the + * CDenty. That means the just created file is possiblly deleted later + * by accident. + * + * We need to wait for the inflight async unlink requests to finish + * when creating new files/directories by using the same file names. + */ +int ceph_wait_on_conflict_unlink(struct dentry *dentry) +{ + struct ceph_fs_client *fsc =3D ceph_sb_to_client(dentry->d_sb); + struct dentry *pdentry =3D dentry->d_parent; + struct dentry *udentry, *found =3D NULL; + struct ceph_dentry_info *di; + struct qstr dname; + u32 hash =3D dentry->d_name.hash; + int err; + + dname.name =3D dentry->d_name.name; + dname.len =3D dentry->d_name.len; + + rcu_read_lock(); + hash_for_each_possible_rcu(fsc->async_unlink_conflict, di, + hnode, hash) { + udentry =3D di->dentry; + + spin_lock(&udentry->d_lock); + if (udentry->d_name.hash !=3D hash) + goto next; + if (unlikely(udentry->d_parent !=3D pdentry)) + goto next; + if (!hash_hashed(&di->hnode)) + goto next; + + if (!test_bit(CEPH_DENTRY_ASYNC_UNLINK_BIT, &di->flags)) + pr_warn("%s dentry %p:%pd async unlink bit is not set\n", + __func__, dentry, dentry); + + if (!d_same_name(udentry, pdentry, &dname)) + goto next; + + spin_unlock(&udentry->d_lock); + found =3D dget(udentry); + break; +next: + spin_unlock(&udentry->d_lock); + } + rcu_read_unlock(); + + if (likely(!found)) + return 0; + + dout("%s dentry %p:%pd conflict with old %p:%pd\n", __func__, + dentry, dentry, found, found); + + err =3D wait_on_bit(&di->flags, CEPH_DENTRY_ASYNC_UNLINK_BIT, + TASK_KILLABLE); + dput(found); + return err; +} + =20 /* * sessions diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h index 2a49e331987b..636fcf4503e0 100644 --- a/fs/ceph/mds_client.h +++ b/fs/ceph/mds_client.h @@ -576,6 +576,7 @@ static inline int ceph_wait_on_async_create(struct inod= e *inode) TASK_KILLABLE); } =20 +extern int ceph_wait_on_conflict_unlink(struct dentry *dentry); extern u64 ceph_get_deleg_ino(struct ceph_mds_session *session); extern int ceph_restore_deleg_ino(struct ceph_mds_session *session, u64 in= o); #endif diff --git a/fs/ceph/super.c b/fs/ceph/super.c index b73b4f75462c..6542b71f8627 100644 --- a/fs/ceph/super.c +++ b/fs/ceph/super.c @@ -816,6 +816,9 @@ static struct ceph_fs_client *create_fs_client(struct c= eph_mount_options *fsopt, if (!fsc->cap_wq) goto fail_inode_wq; =20 + hash_init(fsc->async_unlink_conflict); + spin_lock_init(&fsc->async_unlink_conflict_lock); + spin_lock(&ceph_fsc_lock); list_add_tail(&fsc->metric_wakeup, &ceph_fsc_list); spin_unlock(&ceph_fsc_lock); diff --git a/fs/ceph/super.h b/fs/ceph/super.h index 506d52633627..251e726ec628 100644 --- a/fs/ceph/super.h +++ b/fs/ceph/super.h @@ -19,6 +19,7 @@ #include #include #include +#include =20 #include =20 @@ -99,6 +100,8 @@ struct ceph_mount_options { char *mon_addr; }; =20 +#define CEPH_ASYNC_CREATE_CONFLICT_BITS 8 + struct ceph_fs_client { struct super_block *sb; =20 @@ -124,6 +127,9 @@ struct ceph_fs_client { struct workqueue_struct *inode_wq; struct workqueue_struct *cap_wq; =20 + DECLARE_HASHTABLE(async_unlink_conflict, CEPH_ASYNC_CREATE_CONFLICT_BITS); + spinlock_t async_unlink_conflict_lock; + #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_dentry_lru, *debugfs_caps; struct dentry *debugfs_congestion_kb; @@ -281,7 +287,8 @@ struct ceph_dentry_info { struct dentry *dentry; struct ceph_mds_session *lease_session; struct list_head lease_list; - unsigned flags; + struct hlist_node hnode; + unsigned long flags; int lease_shared_gen; u32 lease_gen; u32 lease_seq; @@ -290,10 +297,12 @@ struct ceph_dentry_info { u64 offset; }; =20 -#define CEPH_DENTRY_REFERENCED 1 -#define CEPH_DENTRY_LEASE_LIST 2 -#define CEPH_DENTRY_SHRINK_LIST 4 -#define CEPH_DENTRY_PRIMARY_LINK 8 +#define CEPH_DENTRY_REFERENCED (1 << 0) +#define CEPH_DENTRY_LEASE_LIST (1 << 1) +#define CEPH_DENTRY_SHRINK_LIST (1 << 2) +#define CEPH_DENTRY_PRIMARY_LINK (1 << 3) +#define CEPH_DENTRY_ASYNC_UNLINK_BIT (4) +#define CEPH_DENTRY_ASYNC_UNLINK (1 << CEPH_DENTRY_ASYNC_UNLINK_BIT) =20 struct ceph_inode_xattrs_info { /* --=20 2.36.0.rc1