From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f53.google.com (mail-pj1-f53.google.com [209.85.216.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 82F9F4878F for ; Mon, 18 Dec 2023 15:39:57 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=fail (p=none dis=none) header.from=kernel.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Received: by mail-pj1-f53.google.com with SMTP id 98e67ed59e1d1-28b012f93eeso1217190a91.0 for ; Mon, 18 Dec 2023 07:39:57 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1702913997; x=1703518797; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=7ITqq+iokKxtTW3U3igcAllgzeqAvaw6fbwoM0JgK1g=; b=Z5D7lrtS7rDUpGN4nKg0BrPngsYLLUUj8Db28BpxpX0pgjWWh+MI7NTjc25izPcNcK eVzya3oHg2qaBbSEzE4ZaqX2feRHdo0Iku5102W5x4UHJWmTMeb3KBvHsz+w0rhWB9gk B/1AvU63jdwCLnm12a3FibEkaa9ZTzhIt8OqnvR2kENoocbhkzoui5rVa80Y/eKUt8vP +VPyo1TEVT2YTsITQv/hZPogdSh3r/UU6mZix6OS4RECncbtwaaB+gdMupLVv4CZoWbI sEgH/Fh6/FDXbngkkgqG2rq/rlAiyN1wJE3uzxj1Qjlywk3nmiK16+jnrnmiWRAYoadm Wwbw== X-Gm-Message-State: AOJu0YxL+hn7MygnFZjtLUdRE95Z6O8eNlxqEJ+Me0OGNqSiSPgxwzvG ehSeiyWETvfNP0MN0RXy31Q= X-Google-Smtp-Source: AGHT+IHgg8n3465b8+ongEpEB6SM+FRo+zmvrvDnfr9F9HQzO+3/R9znXFDGmCUCKrmWwVVwxUWhlA== X-Received: by 2002:a17:90b:2356:b0:28b:729c:b9fb with SMTP id ms22-20020a17090b235600b0028b729cb9fbmr737453pjb.27.1702913996830; Mon, 18 Dec 2023 07:39:56 -0800 (PST) Received: from localhost.localdomain ([110.14.71.32]) by smtp.gmail.com with ESMTPSA id fs7-20020a17090af28700b00286ed94466dsm5613041pjb.32.2023.12.18.07.39.55 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 18 Dec 2023 07:39:56 -0800 (PST) From: Namjae Jeon To: gregkh@linuxfoundation.org, stable@vger.kernel.org Cc: smfrench@gmail.com, Al Viro , Namjae Jeon Subject: [PATCH 5.15.y 086/154] fs: introduce lock_rename_child() helper Date: Tue, 19 Dec 2023 00:33:46 +0900 Message-Id: <20231218153454.8090-87-linkinjeon@kernel.org> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20231218153454.8090-1-linkinjeon@kernel.org> References: <20231218153454.8090-1-linkinjeon@kernel.org> Precedence: bulk X-Mailing-List: stable@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Al Viro [ Upstream commit 9bc37e04823b5280dd0f22b6680fc23fe81ca325 ] Pass the dentry of a source file and the dentry of a destination directory to lock parent inodes for rename. As soon as this function returns, ->d_parent of the source file dentry is stable and inodes are properly locked for calling vfs-rename. This helper is needed for ksmbd server. rename request of SMB protocol has to rename an opened file, no matter which directory it's in. Signed-off-by: Al Viro Signed-off-by: Namjae Jeon Signed-off-by: Al Viro --- fs/namei.c | 68 ++++++++++++++++++++++++++++++++++++------- include/linux/namei.h | 1 + 2 files changed, 58 insertions(+), 11 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index ea2785103376..2a6ce6cfb449 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2956,20 +2956,10 @@ static inline int may_create(struct user_namespace *mnt_userns, return inode_permission(mnt_userns, dir, MAY_WRITE | MAY_EXEC); } -/* - * p1 and p2 should be directories on the same fs. - */ -struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) +static struct dentry *lock_two_directories(struct dentry *p1, struct dentry *p2) { struct dentry *p; - if (p1 == p2) { - inode_lock_nested(p1->d_inode, I_MUTEX_PARENT); - return NULL; - } - - mutex_lock(&p1->d_sb->s_vfs_rename_mutex); - p = d_ancestor(p2, p1); if (p) { inode_lock_nested(p2->d_inode, I_MUTEX_PARENT); @@ -2988,8 +2978,64 @@ struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) I_MUTEX_PARENT, I_MUTEX_PARENT2); return NULL; } + +/* + * p1 and p2 should be directories on the same fs. + */ +struct dentry *lock_rename(struct dentry *p1, struct dentry *p2) +{ + if (p1 == p2) { + inode_lock_nested(p1->d_inode, I_MUTEX_PARENT); + return NULL; + } + + mutex_lock(&p1->d_sb->s_vfs_rename_mutex); + return lock_two_directories(p1, p2); +} EXPORT_SYMBOL(lock_rename); +/* + * c1 and p2 should be on the same fs. + */ +struct dentry *lock_rename_child(struct dentry *c1, struct dentry *p2) +{ + if (READ_ONCE(c1->d_parent) == p2) { + /* + * hopefully won't need to touch ->s_vfs_rename_mutex at all. + */ + inode_lock_nested(p2->d_inode, I_MUTEX_PARENT); + /* + * now that p2 is locked, nobody can move in or out of it, + * so the test below is safe. + */ + if (likely(c1->d_parent == p2)) + return NULL; + + /* + * c1 got moved out of p2 while we'd been taking locks; + * unlock and fall back to slow case. + */ + inode_unlock(p2->d_inode); + } + + mutex_lock(&c1->d_sb->s_vfs_rename_mutex); + /* + * nobody can move out of any directories on this fs. + */ + if (likely(c1->d_parent != p2)) + return lock_two_directories(c1->d_parent, p2); + + /* + * c1 got moved into p2 while we were taking locks; + * we need p2 locked and ->s_vfs_rename_mutex unlocked, + * for consistency with lock_rename(). + */ + inode_lock_nested(p2->d_inode, I_MUTEX_PARENT); + mutex_unlock(&c1->d_sb->s_vfs_rename_mutex); + return NULL; +} +EXPORT_SYMBOL(lock_rename_child); + void unlock_rename(struct dentry *p1, struct dentry *p2) { inode_unlock(p1->d_inode); diff --git a/include/linux/namei.h b/include/linux/namei.h index 40c693525f79..7868732cce24 100644 --- a/include/linux/namei.h +++ b/include/linux/namei.h @@ -83,6 +83,7 @@ extern int follow_down(struct path *); extern int follow_up(struct path *); extern struct dentry *lock_rename(struct dentry *, struct dentry *); +extern struct dentry *lock_rename_child(struct dentry *, struct dentry *); extern void unlock_rename(struct dentry *, struct dentry *); extern int __must_check nd_jump_link(struct path *path); -- 2.25.1