From: Sasha Levin Date: Mon, 1 Jan 2024 18:11:03 +0000 (-0500) Subject: Fixes for 6.6 X-Git-Tag: v5.10.206~33 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=8b4ebae34a422c4576e8be4b884ccb360cdf60d4;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.6 Signed-off-by: Sasha Levin --- diff --git a/queue-6.6/block-renumber-queue_flag_hw_wc.patch b/queue-6.6/block-renumber-queue_flag_hw_wc.patch new file mode 100644 index 00000000000..edadc479c92 --- /dev/null +++ b/queue-6.6/block-renumber-queue_flag_hw_wc.patch @@ -0,0 +1,37 @@ +From fbd24f0e0ca8e3930e380a9ced8deb198c10a149 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 26 Dec 2023 08:15:24 +0000 +Subject: block: renumber QUEUE_FLAG_HW_WC + +From: Christoph Hellwig + +[ Upstream commit 02d374f3418df577c850f0cd45c3da9245ead547 ] + +For the QUEUE_FLAG_HW_WC to actually work, it needs to have a separate +number from QUEUE_FLAG_FUA, doh. + +Fixes: 43c9835b144c ("block: don't allow enabling a cache on devices that don't support it") +Signed-off-by: Christoph Hellwig +Link: https://lore.kernel.org/r/20231226081524.180289-1-hch@lst.de +Signed-off-by: Jens Axboe +Signed-off-by: Sasha Levin +--- + include/linux/blkdev.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h +index eef450f259828..f59fcd5b499a5 100644 +--- a/include/linux/blkdev.h ++++ b/include/linux/blkdev.h +@@ -538,7 +538,7 @@ struct request_queue { + #define QUEUE_FLAG_ADD_RANDOM 10 /* Contributes to random pool */ + #define QUEUE_FLAG_SYNCHRONOUS 11 /* always completes in submit context */ + #define QUEUE_FLAG_SAME_FORCE 12 /* force complete on same CPU */ +-#define QUEUE_FLAG_HW_WC 18 /* Write back caching supported */ ++#define QUEUE_FLAG_HW_WC 13 /* Write back caching supported */ + #define QUEUE_FLAG_INIT_DONE 14 /* queue is initialized */ + #define QUEUE_FLAG_STABLE_WRITES 15 /* don't modify blks until WB is done */ + #define QUEUE_FLAG_POLL 16 /* IO polling enabled if set */ +-- +2.43.0 + diff --git a/queue-6.6/client-convert-to-new-timestamp-accessors.patch b/queue-6.6/client-convert-to-new-timestamp-accessors.patch new file mode 100644 index 00000000000..9076dedef8e --- /dev/null +++ b/queue-6.6/client-convert-to-new-timestamp-accessors.patch @@ -0,0 +1,185 @@ +From 671945edb68c3d381b1e66740822bf980235d30d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 14:52:53 -0400 +Subject: client: convert to new timestamp accessors + +From: Jeff Layton + +[ Upstream commit 8f22ce7088835444418f0775efb455d10b825596 ] + +Convert to using the new inode timestamp accessor functions. + +Signed-off-by: Jeff Layton +Link: https://lore.kernel.org/r/20231004185347.80880-66-jlayton@kernel.org +Signed-off-by: Christian Brauner +Stable-dep-of: 01fe654f78fd ("fs: cifs: Fix atime update check") +Signed-off-by: Sasha Levin +--- + fs/smb/client/file.c | 18 ++++++++++-------- + fs/smb/client/fscache.h | 6 +++--- + fs/smb/client/inode.c | 17 ++++++++--------- + fs/smb/client/smb2ops.c | 6 ++++-- + 4 files changed, 25 insertions(+), 22 deletions(-) + +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index 2108b3b40ce92..cf17e3dd703e6 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -1085,7 +1085,8 @@ int cifs_close(struct inode *inode, struct file *file) + !test_bit(CIFS_INO_CLOSE_ON_LOCK, &cinode->flags) && + dclose) { + if (test_and_clear_bit(CIFS_INO_MODIFIED_ATTR, &cinode->flags)) { +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, ++ inode_set_ctime_current(inode)); + } + spin_lock(&cinode->deferred_lock); + cifs_add_deferred_close(cfile, dclose); +@@ -2596,7 +2597,7 @@ static int cifs_partialpagewrite(struct page *page, unsigned from, unsigned to) + write_data, to - from, &offset); + cifsFileInfo_put(open_file); + /* Does mm or vfs already set times? */ +- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); ++ simple_inode_init_ts(inode); + if ((bytes_written > 0) && (offset)) + rc = 0; + else if (bytes_written < 0) +@@ -4647,11 +4648,13 @@ static void cifs_readahead(struct readahead_control *ractl) + static int cifs_readpage_worker(struct file *file, struct page *page, + loff_t *poffset) + { ++ struct inode *inode = file_inode(file); ++ struct timespec64 atime, mtime; + char *read_data; + int rc; + + /* Is the page cached? */ +- rc = cifs_readpage_from_fscache(file_inode(file), page); ++ rc = cifs_readpage_from_fscache(inode, page); + if (rc == 0) + goto read_complete; + +@@ -4666,11 +4669,10 @@ static int cifs_readpage_worker(struct file *file, struct page *page, + cifs_dbg(FYI, "Bytes read %d\n", rc); + + /* we do not want atime to be less than mtime, it broke some apps */ +- file_inode(file)->i_atime = current_time(file_inode(file)); +- if (timespec64_compare(&(file_inode(file)->i_atime), &(file_inode(file)->i_mtime))) +- file_inode(file)->i_atime = file_inode(file)->i_mtime; +- else +- file_inode(file)->i_atime = current_time(file_inode(file)); ++ atime = inode_set_atime_to_ts(inode, current_time(inode)); ++ mtime = inode_get_mtime(inode); ++ if (timespec64_compare(&atime, &mtime)) ++ inode_set_atime_to_ts(inode, inode_get_mtime(inode)); + + if (PAGE_SIZE > rc) + memset(read_data + rc, 0, PAGE_SIZE - rc); +diff --git a/fs/smb/client/fscache.h b/fs/smb/client/fscache.h +index 84f3b09367d2c..a3d73720914f8 100644 +--- a/fs/smb/client/fscache.h ++++ b/fs/smb/client/fscache.h +@@ -49,12 +49,12 @@ static inline + void cifs_fscache_fill_coherency(struct inode *inode, + struct cifs_fscache_inode_coherency_data *cd) + { +- struct cifsInodeInfo *cifsi = CIFS_I(inode); + struct timespec64 ctime = inode_get_ctime(inode); ++ struct timespec64 mtime = inode_get_mtime(inode); + + memset(cd, 0, sizeof(*cd)); +- cd->last_write_time_sec = cpu_to_le64(cifsi->netfs.inode.i_mtime.tv_sec); +- cd->last_write_time_nsec = cpu_to_le32(cifsi->netfs.inode.i_mtime.tv_nsec); ++ cd->last_write_time_sec = cpu_to_le64(mtime.tv_sec); ++ cd->last_write_time_nsec = cpu_to_le32(mtime.tv_nsec); + cd->last_change_time_sec = cpu_to_le64(ctime.tv_sec); + cd->last_change_time_nsec = cpu_to_le32(ctime.tv_nsec); + } +diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c +index 6a856945f2b42..09c5c0f5c96e2 100644 +--- a/fs/smb/client/inode.c ++++ b/fs/smb/client/inode.c +@@ -82,6 +82,7 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) + { + struct cifs_fscache_inode_coherency_data cd; + struct cifsInodeInfo *cifs_i = CIFS_I(inode); ++ struct timespec64 mtime; + + cifs_dbg(FYI, "%s: revalidating inode %llu\n", + __func__, cifs_i->uniqueid); +@@ -101,7 +102,8 @@ cifs_revalidate_cache(struct inode *inode, struct cifs_fattr *fattr) + + /* revalidate if mtime or size have changed */ + fattr->cf_mtime = timestamp_truncate(fattr->cf_mtime, inode); +- if (timespec64_equal(&inode->i_mtime, &fattr->cf_mtime) && ++ mtime = inode_get_mtime(inode); ++ if (timespec64_equal(&mtime, &fattr->cf_mtime) && + cifs_i->server_eof == fattr->cf_eof) { + cifs_dbg(FYI, "%s: inode %llu is unchanged\n", + __func__, cifs_i->uniqueid); +@@ -164,10 +166,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr) + fattr->cf_ctime = timestamp_truncate(fattr->cf_ctime, inode); + /* we do not want atime to be less than mtime, it broke some apps */ + if (timespec64_compare(&fattr->cf_atime, &fattr->cf_mtime) < 0) +- inode->i_atime = fattr->cf_mtime; ++ inode_set_atime_to_ts(inode, fattr->cf_mtime); + else +- inode->i_atime = fattr->cf_atime; +- inode->i_mtime = fattr->cf_mtime; ++ inode_set_atime_to_ts(inode, fattr->cf_atime); ++ inode_set_mtime_to_ts(inode, fattr->cf_mtime); + inode_set_ctime_to_ts(inode, fattr->cf_ctime); + inode->i_rdev = fattr->cf_rdev; + cifs_nlink_fattr_to_inode(inode, fattr); +@@ -1868,7 +1870,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry) + when needed */ + inode_set_ctime_current(inode); + } +- dir->i_mtime = inode_set_ctime_current(dir); ++ inode_set_mtime_to_ts(dir, inode_set_ctime_current(dir)); + cifs_inode = CIFS_I(dir); + CIFS_I(dir)->time = 0; /* force revalidate of dir as well */ + unlink_out: +@@ -2183,7 +2185,7 @@ int cifs_rmdir(struct inode *inode, struct dentry *direntry) + cifsInode->time = 0; + + inode_set_ctime_current(d_inode(direntry)); +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, inode_set_ctime_current(inode)); + + rmdir_exit: + free_dentry_path(page); +@@ -2389,9 +2391,6 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir, + /* force revalidate to go get info when needed */ + CIFS_I(source_dir)->time = CIFS_I(target_dir)->time = 0; + +- source_dir->i_mtime = target_dir->i_mtime = inode_set_ctime_to_ts(source_dir, +- inode_set_ctime_current(target_dir)); +- + cifs_rename_exit: + kfree(info_buf_source); + free_dentry_path(page2); +diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c +index 2187921580ac6..e917eeba9c772 100644 +--- a/fs/smb/client/smb2ops.c ++++ b/fs/smb/client/smb2ops.c +@@ -1409,12 +1409,14 @@ smb2_close_getattr(const unsigned int xid, struct cifs_tcon *tcon, + + /* Creation time should not need to be updated on close */ + if (file_inf.LastWriteTime) +- inode->i_mtime = cifs_NTtimeToUnix(file_inf.LastWriteTime); ++ inode_set_mtime_to_ts(inode, ++ cifs_NTtimeToUnix(file_inf.LastWriteTime)); + if (file_inf.ChangeTime) + inode_set_ctime_to_ts(inode, + cifs_NTtimeToUnix(file_inf.ChangeTime)); + if (file_inf.LastAccessTime) +- inode->i_atime = cifs_NTtimeToUnix(file_inf.LastAccessTime); ++ inode_set_atime_to_ts(inode, ++ cifs_NTtimeToUnix(file_inf.LastAccessTime)); + + /* + * i_blocks is not related to (i_size / i_blksize), +-- +2.43.0 + diff --git a/queue-6.6/fs-cifs-fix-atime-update-check.patch b/queue-6.6/fs-cifs-fix-atime-update-check.patch new file mode 100644 index 00000000000..224afcd28b0 --- /dev/null +++ b/queue-6.6/fs-cifs-fix-atime-update-check.patch @@ -0,0 +1,44 @@ +From e07f8d4e04e5a8ceaa94203d1204f4c9df6eddda Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Dec 2023 10:23:53 +0800 +Subject: fs: cifs: Fix atime update check + +From: Zizhi Wo + +[ Upstream commit 01fe654f78fd1ea4df046ef76b07ba92a35f8dbe ] + +Commit 9b9c5bea0b96 ("cifs: do not return atime less than mtime") indicates +that in cifs, if atime is less than mtime, some apps will break. +Therefore, it introduce a function to compare this two variables in two +places where atime is updated. If atime is less than mtime, update it to +mtime. + +However, the patch was handled incorrectly, resulting in atime and mtime +being exactly equal. A previous commit 69738cfdfa70 ("fs: cifs: Fix atime +update check vs mtime") fixed one place and forgot to fix another. Fix it. + +Fixes: 9b9c5bea0b96 ("cifs: do not return atime less than mtime") +Cc: stable@vger.kernel.org +Signed-off-by: Zizhi Wo +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/client/file.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c +index cf17e3dd703e6..32a8525415d96 100644 +--- a/fs/smb/client/file.c ++++ b/fs/smb/client/file.c +@@ -4671,7 +4671,7 @@ static int cifs_readpage_worker(struct file *file, struct page *page, + /* we do not want atime to be less than mtime, it broke some apps */ + atime = inode_set_atime_to_ts(inode, current_time(inode)); + mtime = inode_get_mtime(inode); +- if (timespec64_compare(&atime, &mtime)) ++ if (timespec64_compare(&atime, &mtime) < 0) + inode_set_atime_to_ts(inode, inode_get_mtime(inode)); + + if (PAGE_SIZE > rc) +-- +2.43.0 + diff --git a/queue-6.6/fs-new-accessor-methods-for-atime-and-mtime.patch b/queue-6.6/fs-new-accessor-methods-for-atime-and-mtime.patch new file mode 100644 index 00000000000..e51cb1317d5 --- /dev/null +++ b/queue-6.6/fs-new-accessor-methods-for-atime-and-mtime.patch @@ -0,0 +1,244 @@ +From d8f630c0aff115330cf581a0dad0733aec9bde2e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 4 Oct 2023 14:52:37 -0400 +Subject: fs: new accessor methods for atime and mtime + +From: Jeff Layton + +[ Upstream commit 077c212f0344ae4198b2b51af128a94b614ccdf4 ] + +Recently, we converted the ctime accesses in the kernel to use new +accessor functions. Linus recently pointed out though that if we add +accessors for the atime and mtime, then that would allow us to +seamlessly change how these timestamps are stored in the inode. + +Add new accessor functions for the atime and mtime that mirror the +accessors for the ctime. + +Signed-off-by: Jeff Layton +Link: https://lore.kernel.org/r/20231004185239.80830-1-jlayton@kernel.org +Signed-off-by: Christian Brauner +Stable-dep-of: 01fe654f78fd ("fs: cifs: Fix atime update check") +Signed-off-by: Sasha Levin +--- + fs/libfs.c | 41 ++++++++++++++++------ + include/linux/fs.h | 85 +++++++++++++++++++++++++++++++++++++++------- + 2 files changed, 102 insertions(+), 24 deletions(-) + +diff --git a/fs/libfs.c b/fs/libfs.c +index 189447cf4acf5..dc0f7519045f1 100644 +--- a/fs/libfs.c ++++ b/fs/libfs.c +@@ -549,7 +549,8 @@ void simple_recursive_removal(struct dentry *dentry, + dput(victim); // unpin it + } + if (victim == dentry) { +- inode->i_mtime = inode_set_ctime_current(inode); ++ inode_set_mtime_to_ts(inode, ++ inode_set_ctime_current(inode)); + if (d_is_dir(dentry)) + drop_nlink(inode); + inode_unlock(inode); +@@ -590,7 +591,7 @@ static int pseudo_fs_fill_super(struct super_block *s, struct fs_context *fc) + */ + root->i_ino = 1; + root->i_mode = S_IFDIR | S_IRUSR | S_IWUSR; +- root->i_atime = root->i_mtime = inode_set_ctime_current(root); ++ simple_inode_init_ts(root); + s->s_root = d_make_root(root); + if (!s->s_root) + return -ENOMEM; +@@ -646,8 +647,8 @@ int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *den + { + struct inode *inode = d_inode(old_dentry); + +- dir->i_mtime = inode_set_ctime_to_ts(dir, +- inode_set_ctime_current(inode)); ++ inode_set_mtime_to_ts(dir, ++ inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode))); + inc_nlink(inode); + ihold(inode); + dget(dentry); +@@ -681,8 +682,8 @@ int simple_unlink(struct inode *dir, struct dentry *dentry) + { + struct inode *inode = d_inode(dentry); + +- dir->i_mtime = inode_set_ctime_to_ts(dir, +- inode_set_ctime_current(inode)); ++ inode_set_mtime_to_ts(dir, ++ inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode))); + drop_nlink(inode); + dput(dentry); + return 0; +@@ -717,9 +718,10 @@ void simple_rename_timestamp(struct inode *old_dir, struct dentry *old_dentry, + { + struct inode *newino = d_inode(new_dentry); + +- old_dir->i_mtime = inode_set_ctime_current(old_dir); ++ inode_set_mtime_to_ts(old_dir, inode_set_ctime_current(old_dir)); + if (new_dir != old_dir) +- new_dir->i_mtime = inode_set_ctime_current(new_dir); ++ inode_set_mtime_to_ts(new_dir, ++ inode_set_ctime_current(new_dir)); + inode_set_ctime_current(d_inode(old_dentry)); + if (newino) + inode_set_ctime_current(newino); +@@ -934,7 +936,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic, + */ + inode->i_ino = 1; + inode->i_mode = S_IFDIR | 0755; +- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); ++ simple_inode_init_ts(inode); + inode->i_op = &simple_dir_inode_operations; + inode->i_fop = &simple_dir_operations; + set_nlink(inode, 2); +@@ -960,7 +962,7 @@ int simple_fill_super(struct super_block *s, unsigned long magic, + goto out; + } + inode->i_mode = S_IFREG | files->mode; +- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); ++ simple_inode_init_ts(inode); + inode->i_fop = files->ops; + inode->i_ino = i; + d_add(dentry, inode); +@@ -1528,7 +1530,7 @@ struct inode *alloc_anon_inode(struct super_block *s) + inode->i_uid = current_fsuid(); + inode->i_gid = current_fsgid(); + inode->i_flags |= S_PRIVATE; +- inode->i_atime = inode->i_mtime = inode_set_ctime_current(inode); ++ simple_inode_init_ts(inode); + return inode; + } + EXPORT_SYMBOL(alloc_anon_inode); +@@ -1920,3 +1922,20 @@ ssize_t direct_write_fallback(struct kiocb *iocb, struct iov_iter *iter, + return direct_written + buffered_written; + } + EXPORT_SYMBOL_GPL(direct_write_fallback); ++ ++/** ++ * simple_inode_init_ts - initialize the timestamps for a new inode ++ * @inode: inode to be initialized ++ * ++ * When a new inode is created, most filesystems set the timestamps to the ++ * current time. Add a helper to do this. ++ */ ++struct timespec64 simple_inode_init_ts(struct inode *inode) ++{ ++ struct timespec64 ts = inode_set_ctime_current(inode); ++ ++ inode_set_atime_to_ts(inode, ts); ++ inode_set_mtime_to_ts(inode, ts); ++ return ts; ++} ++EXPORT_SYMBOL(simple_inode_init_ts); +diff --git a/include/linux/fs.h b/include/linux/fs.h +index 4a40823c3c678..d08b97dacd2d9 100644 +--- a/include/linux/fs.h ++++ b/include/linux/fs.h +@@ -1511,24 +1511,81 @@ static inline bool fsuidgid_has_mapping(struct super_block *sb, + struct timespec64 current_time(struct inode *inode); + struct timespec64 inode_set_ctime_current(struct inode *inode); + +-/** +- * inode_get_ctime - fetch the current ctime from the inode +- * @inode: inode from which to fetch ctime +- * +- * Grab the current ctime from the inode and return it. +- */ ++static inline time64_t inode_get_atime_sec(const struct inode *inode) ++{ ++ return inode->i_atime.tv_sec; ++} ++ ++static inline long inode_get_atime_nsec(const struct inode *inode) ++{ ++ return inode->i_atime.tv_nsec; ++} ++ ++static inline struct timespec64 inode_get_atime(const struct inode *inode) ++{ ++ return inode->i_atime; ++} ++ ++static inline struct timespec64 inode_set_atime_to_ts(struct inode *inode, ++ struct timespec64 ts) ++{ ++ inode->i_atime = ts; ++ return ts; ++} ++ ++static inline struct timespec64 inode_set_atime(struct inode *inode, ++ time64_t sec, long nsec) ++{ ++ struct timespec64 ts = { .tv_sec = sec, ++ .tv_nsec = nsec }; ++ return inode_set_atime_to_ts(inode, ts); ++} ++ ++static inline time64_t inode_get_mtime_sec(const struct inode *inode) ++{ ++ return inode->i_mtime.tv_sec; ++} ++ ++static inline long inode_get_mtime_nsec(const struct inode *inode) ++{ ++ return inode->i_mtime.tv_nsec; ++} ++ ++static inline struct timespec64 inode_get_mtime(const struct inode *inode) ++{ ++ return inode->i_mtime; ++} ++ ++static inline struct timespec64 inode_set_mtime_to_ts(struct inode *inode, ++ struct timespec64 ts) ++{ ++ inode->i_mtime = ts; ++ return ts; ++} ++ ++static inline struct timespec64 inode_set_mtime(struct inode *inode, ++ time64_t sec, long nsec) ++{ ++ struct timespec64 ts = { .tv_sec = sec, ++ .tv_nsec = nsec }; ++ return inode_set_mtime_to_ts(inode, ts); ++} ++ ++static inline time64_t inode_get_ctime_sec(const struct inode *inode) ++{ ++ return inode->__i_ctime.tv_sec; ++} ++ ++static inline long inode_get_ctime_nsec(const struct inode *inode) ++{ ++ return inode->__i_ctime.tv_nsec; ++} ++ + static inline struct timespec64 inode_get_ctime(const struct inode *inode) + { + return inode->__i_ctime; + } + +-/** +- * inode_set_ctime_to_ts - set the ctime in the inode +- * @inode: inode in which to set the ctime +- * @ts: value to set in the ctime field +- * +- * Set the ctime in @inode to @ts +- */ + static inline struct timespec64 inode_set_ctime_to_ts(struct inode *inode, + struct timespec64 ts) + { +@@ -1553,6 +1610,8 @@ static inline struct timespec64 inode_set_ctime(struct inode *inode, + return inode_set_ctime_to_ts(inode, ts); + } + ++struct timespec64 simple_inode_init_ts(struct inode *inode); ++ + /* + * Snapshotting support. + */ +-- +2.43.0 + diff --git a/queue-6.6/kexec-fix-kexec_file-dependencies.patch b/queue-6.6/kexec-fix-kexec_file-dependencies.patch new file mode 100644 index 00000000000..6d07b1c6f86 --- /dev/null +++ b/queue-6.6/kexec-fix-kexec_file-dependencies.patch @@ -0,0 +1,163 @@ +From b55c74642aa82b90e6300d44c4fcf6fe3c5471e2 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Oct 2023 13:01:54 +0200 +Subject: kexec: fix KEXEC_FILE dependencies + +From: Arnd Bergmann + +[ Upstream commit c1ad12ee0efc07244be37f69311e6f7c4ac98e62 ] + +The cleanup for the CONFIG_KEXEC Kconfig logic accidentally changed the +'depends on CRYPTO=y' dependency to a plain 'depends on CRYPTO', which +causes a link failure when all the crypto support is in a loadable module +and kexec_file support is built-in: + +x86_64-linux-ld: vmlinux.o: in function `__x64_sys_kexec_file_load': +(.text+0x32e30a): undefined reference to `crypto_alloc_shash' +x86_64-linux-ld: (.text+0x32e58e): undefined reference to `crypto_shash_update' +x86_64-linux-ld: (.text+0x32e6ee): undefined reference to `crypto_shash_final' + +Both s390 and x86 have this problem, while ppc64 and riscv have the +correct dependency already. On riscv, the dependency is only used for the +purgatory, not for the kexec_file code itself, which may be a bit +surprising as it means that with CONFIG_CRYPTO=m, it is possible to enable +KEXEC_FILE but then the purgatory code is silently left out. + +Move this into the common Kconfig.kexec file in a way that is correct +everywhere, using the dependency on CRYPTO_SHA256=y only when the +purgatory code is available. This requires reversing the dependency +between ARCH_SUPPORTS_KEXEC_PURGATORY and KEXEC_FILE, but the effect +remains the same, other than making riscv behave like the other ones. + +On s390, there is an additional dependency on CRYPTO_SHA256_S390, which +should technically not be required but gives better performance. Remove +this dependency here, noting that it was not present in the initial +Kconfig code but was brought in without an explanation in commit +71406883fd357 ("s390/kexec_file: Add kexec_file_load system call"). + +[arnd@arndb.de: fix riscv build] + Link: https://lkml.kernel.org/r/67ddd260-d424-4229-a815-e3fcfb864a77@app.fastmail.com +Link: https://lkml.kernel.org/r/20231023110308.1202042-1-arnd@kernel.org +Fixes: 6af5138083005 ("x86/kexec: refactor for kernel/Kconfig.kexec") +Signed-off-by: Arnd Bergmann +Reviewed-by: Eric DeVolder +Tested-by: Eric DeVolder +Cc: Albert Ou +Cc: Alexander Gordeev +Cc: Ard Biesheuvel +Cc: Borislav Petkov +Cc: Christian Borntraeger +Cc: Christophe Leroy +Cc: Conor Dooley +Cc: Dave Hansen +Cc: David S. Miller +Cc: Heiko Carstens +Cc: Herbert Xu +Cc: "H. Peter Anvin" +Cc: Ingo Molnar +Cc: Nicholas Piggin +Cc: Palmer Dabbelt +Cc: Paul Walmsley +Cc: Peter Zijlstra +Cc: Sven Schnelle +Cc: Thomas Gleixner +Cc: Vasily Gorbik +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + arch/powerpc/Kconfig | 4 ++-- + arch/riscv/Kconfig | 4 +--- + arch/s390/Kconfig | 4 ++-- + arch/x86/Kconfig | 4 ++-- + kernel/Kconfig.kexec | 1 + + 5 files changed, 8 insertions(+), 9 deletions(-) + +diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig +index d5d5388973ac7..4640cee33f123 100644 +--- a/arch/powerpc/Kconfig ++++ b/arch/powerpc/Kconfig +@@ -607,10 +607,10 @@ config ARCH_SUPPORTS_KEXEC + def_bool PPC_BOOK3S || PPC_E500 || (44x && !SMP) + + config ARCH_SUPPORTS_KEXEC_FILE +- def_bool PPC64 && CRYPTO=y && CRYPTO_SHA256=y ++ def_bool PPC64 + + config ARCH_SUPPORTS_KEXEC_PURGATORY +- def_bool KEXEC_FILE ++ def_bool y + + config ARCH_SELECTS_KEXEC_FILE + def_bool y +diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig +index 6688cbbed0b42..9e6d442773eea 100644 +--- a/arch/riscv/Kconfig ++++ b/arch/riscv/Kconfig +@@ -686,9 +686,7 @@ config ARCH_SELECTS_KEXEC_FILE + select KEXEC_ELF + + config ARCH_SUPPORTS_KEXEC_PURGATORY +- def_bool KEXEC_FILE +- depends on CRYPTO=y +- depends on CRYPTO_SHA256=y ++ def_bool ARCH_SUPPORTS_KEXEC_FILE + + config ARCH_SUPPORTS_CRASH_DUMP + def_bool y +diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig +index ae29e4392664a..bd4782f23f66d 100644 +--- a/arch/s390/Kconfig ++++ b/arch/s390/Kconfig +@@ -252,13 +252,13 @@ config ARCH_SUPPORTS_KEXEC + def_bool y + + config ARCH_SUPPORTS_KEXEC_FILE +- def_bool CRYPTO && CRYPTO_SHA256 && CRYPTO_SHA256_S390 ++ def_bool y + + config ARCH_SUPPORTS_KEXEC_SIG + def_bool MODULE_SIG_FORMAT + + config ARCH_SUPPORTS_KEXEC_PURGATORY +- def_bool KEXEC_FILE ++ def_bool y + + config ARCH_SUPPORTS_CRASH_DUMP + def_bool y +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 66bfabae88149..fe3292e310d48 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -2034,7 +2034,7 @@ config ARCH_SUPPORTS_KEXEC + def_bool y + + config ARCH_SUPPORTS_KEXEC_FILE +- def_bool X86_64 && CRYPTO && CRYPTO_SHA256 ++ def_bool X86_64 + + config ARCH_SELECTS_KEXEC_FILE + def_bool y +@@ -2042,7 +2042,7 @@ config ARCH_SELECTS_KEXEC_FILE + select HAVE_IMA_KEXEC if IMA + + config ARCH_SUPPORTS_KEXEC_PURGATORY +- def_bool KEXEC_FILE ++ def_bool y + + config ARCH_SUPPORTS_KEXEC_SIG + def_bool y +diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec +index f9619ac6b71d9..d3b8a2b1b5732 100644 +--- a/kernel/Kconfig.kexec ++++ b/kernel/Kconfig.kexec +@@ -36,6 +36,7 @@ config KEXEC + config KEXEC_FILE + bool "Enable kexec file based system call" + depends on ARCH_SUPPORTS_KEXEC_FILE ++ depends on CRYPTO_SHA256=y || !ARCH_SUPPORTS_KEXEC_PURGATORY + select KEXEC_CORE + help + This is new version of kexec system call. This system call is +-- +2.43.0 + diff --git a/queue-6.6/kexec-select-crypto-from-kexec_file-instead-of-depen.patch b/queue-6.6/kexec-select-crypto-from-kexec_file-instead-of-depen.patch new file mode 100644 index 00000000000..057d9bc198d --- /dev/null +++ b/queue-6.6/kexec-select-crypto-from-kexec_file-instead-of-depen.patch @@ -0,0 +1,73 @@ +From 7b2bff1809afebd3d9c349a92791095fc4b11a5c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Oct 2023 13:01:55 +0200 +Subject: kexec: select CRYPTO from KEXEC_FILE instead of depending on it + +From: Arnd Bergmann + +[ Upstream commit e63bde3d9417f8318d6dd0d0fafa35ebf307aabd ] + +All other users of crypto code use 'select' instead of 'depends on', so do +the same thing with KEXEC_FILE for consistency. + +In practice this makes very little difference as kernels with kexec +support are very likely to also include some other feature that already +selects both crypto and crypto_sha256, but being consistent here helps for +usability as well as to avoid potential circular dependencies. + +This reverts the dependency back to what it was originally before commit +74ca317c26a3f ("kexec: create a new config option CONFIG_KEXEC_FILE for +new syscall"), which changed changed it with the comment "This should be +safer as "select" is not recursive", but that appears to have been done in +error, as "select" is indeed recursive, and there are no other +dependencies that prevent CRYPTO_SHA256 from being selected here. + +Link: https://lkml.kernel.org/r/20231023110308.1202042-2-arnd@kernel.org +Fixes: 74ca317c26a3f ("kexec: create a new config option CONFIG_KEXEC_FILE for new syscall") +Signed-off-by: Arnd Bergmann +Reviewed-by: Eric DeVolder +Tested-by: Eric DeVolder +Acked-by: Baoquan He +Cc: Herbert Xu +Cc: "David S. Miller" +Cc: Albert Ou +Cc: Alexander Gordeev +Cc: Ard Biesheuvel +Cc: Borislav Petkov +Cc: Christian Borntraeger +Cc: Christophe Leroy +Cc: Conor Dooley +Cc: Dave Hansen +Cc: Heiko Carstens +Cc: "H. Peter Anvin" +Cc: Ingo Molnar +Cc: Nicholas Piggin +Cc: Palmer Dabbelt +Cc: Paul Walmsley +Cc: Peter Zijlstra +Cc: Sven Schnelle +Cc: Thomas Gleixner +Cc: Vasily Gorbik +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + kernel/Kconfig.kexec | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec +index d3b8a2b1b5732..37e488d5b4fc0 100644 +--- a/kernel/Kconfig.kexec ++++ b/kernel/Kconfig.kexec +@@ -36,7 +36,8 @@ config KEXEC + config KEXEC_FILE + bool "Enable kexec file based system call" + depends on ARCH_SUPPORTS_KEXEC_FILE +- depends on CRYPTO_SHA256=y || !ARCH_SUPPORTS_KEXEC_PURGATORY ++ select CRYPTO ++ select CRYPTO_SHA256 + select KEXEC_CORE + help + This is new version of kexec system call. This system call is +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-add-support-for-surrogate-pair-conversion.patch b/queue-6.6/ksmbd-add-support-for-surrogate-pair-conversion.patch new file mode 100644 index 00000000000..92195d4cece --- /dev/null +++ b/queue-6.6/ksmbd-add-support-for-surrogate-pair-conversion.patch @@ -0,0 +1,297 @@ +From fc247894cb76ca52c8598ef3c5a6161cb27e9778 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:05 +0900 +Subject: ksmbd: add support for surrogate pair conversion + +From: Namjae Jeon + +[ Upstream commit 0c180317c654a494fe429adbf7bc9b0793caf9e2 ] + +ksmbd is missing supporting to convert filename included surrogate pair +characters. It triggers a "file or folder does not exist" error in +Windows client. + +[Steps to Reproduce for bug] +1. Create surrogate pair file + touch $(echo -e '\xf0\x9d\x9f\xa3') + touch $(echo -e '\xf0\x9d\x9f\xa4') + +2. Try to open these files in ksmbd share through Windows client. + +This patch update unicode functions not to consider about surrogate pair +(and IVS). + +Reviewed-by: Marios Makassikis +Tested-by: Marios Makassikis +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/unicode.c | 187 +++++++++++++++++++++++++++++----------- + 1 file changed, 138 insertions(+), 49 deletions(-) + +diff --git a/fs/smb/server/unicode.c b/fs/smb/server/unicode.c +index 393dd4a7432b6..43ed29ee44ead 100644 +--- a/fs/smb/server/unicode.c ++++ b/fs/smb/server/unicode.c +@@ -13,46 +13,10 @@ + #include "unicode.h" + #include "smb_common.h" + +-/* +- * smb_utf16_bytes() - how long will a string be after conversion? +- * @from: pointer to input string +- * @maxbytes: don't go past this many bytes of input string +- * @codepage: destination codepage +- * +- * Walk a utf16le string and return the number of bytes that the string will +- * be after being converted to the given charset, not including any null +- * termination required. Don't walk past maxbytes in the source buffer. +- * +- * Return: string length after conversion +- */ +-static int smb_utf16_bytes(const __le16 *from, int maxbytes, +- const struct nls_table *codepage) +-{ +- int i; +- int charlen, outlen = 0; +- int maxwords = maxbytes / 2; +- char tmp[NLS_MAX_CHARSET_SIZE]; +- __u16 ftmp; +- +- for (i = 0; i < maxwords; i++) { +- ftmp = get_unaligned_le16(&from[i]); +- if (ftmp == 0) +- break; +- +- charlen = codepage->uni2char(ftmp, tmp, NLS_MAX_CHARSET_SIZE); +- if (charlen > 0) +- outlen += charlen; +- else +- outlen++; +- } +- +- return outlen; +-} +- + /* + * cifs_mapchar() - convert a host-endian char to proper char in codepage + * @target: where converted character should be copied +- * @src_char: 2 byte host-endian source character ++ * @from: host-endian source string + * @cp: codepage to which character should be converted + * @mapchar: should character be mapped according to mapchars mount option? + * +@@ -63,10 +27,13 @@ static int smb_utf16_bytes(const __le16 *from, int maxbytes, + * Return: string length after conversion + */ + static int +-cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, ++cifs_mapchar(char *target, const __u16 *from, const struct nls_table *cp, + bool mapchar) + { + int len = 1; ++ __u16 src_char; ++ ++ src_char = *from; + + if (!mapchar) + goto cp_convert; +@@ -104,12 +71,66 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, + + cp_convert: + len = cp->uni2char(src_char, target, NLS_MAX_CHARSET_SIZE); +- if (len <= 0) { +- *target = '?'; +- len = 1; +- } ++ if (len <= 0) ++ goto surrogate_pair; + + goto out; ++ ++surrogate_pair: ++ /* convert SURROGATE_PAIR and IVS */ ++ if (strcmp(cp->charset, "utf8")) ++ goto unknown; ++ len = utf16s_to_utf8s(from, 3, UTF16_LITTLE_ENDIAN, target, 6); ++ if (len <= 0) ++ goto unknown; ++ return len; ++ ++unknown: ++ *target = '?'; ++ len = 1; ++ goto out; ++} ++ ++/* ++ * smb_utf16_bytes() - compute converted string length ++ * @from: pointer to input string ++ * @maxbytes: input string length ++ * @codepage: destination codepage ++ * ++ * Walk a utf16le string and return the number of bytes that the string will ++ * be after being converted to the given charset, not including any null ++ * termination required. Don't walk past maxbytes in the source buffer. ++ * ++ * Return: string length after conversion ++ */ ++static int smb_utf16_bytes(const __le16 *from, int maxbytes, ++ const struct nls_table *codepage) ++{ ++ int i, j; ++ int charlen, outlen = 0; ++ int maxwords = maxbytes / 2; ++ char tmp[NLS_MAX_CHARSET_SIZE]; ++ __u16 ftmp[3]; ++ ++ for (i = 0; i < maxwords; i++) { ++ ftmp[0] = get_unaligned_le16(&from[i]); ++ if (ftmp[0] == 0) ++ break; ++ for (j = 1; j <= 2; j++) { ++ if (i + j < maxwords) ++ ftmp[j] = get_unaligned_le16(&from[i + j]); ++ else ++ ftmp[j] = 0; ++ } ++ ++ charlen = cifs_mapchar(tmp, ftmp, codepage, 0); ++ if (charlen > 0) ++ outlen += charlen; ++ else ++ outlen++; ++ } ++ ++ return outlen; + } + + /* +@@ -139,12 +160,12 @@ cifs_mapchar(char *target, const __u16 src_char, const struct nls_table *cp, + static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, + const struct nls_table *codepage, bool mapchar) + { +- int i, charlen, safelen; ++ int i, j, charlen, safelen; + int outlen = 0; + int nullsize = nls_nullsize(codepage); + int fromwords = fromlen / 2; + char tmp[NLS_MAX_CHARSET_SIZE]; +- __u16 ftmp; ++ __u16 ftmp[3]; /* ftmp[3] = 3array x 2bytes = 6bytes UTF-16 */ + + /* + * because the chars can be of varying widths, we need to take care +@@ -155,9 +176,15 @@ static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, + safelen = tolen - (NLS_MAX_CHARSET_SIZE + nullsize); + + for (i = 0; i < fromwords; i++) { +- ftmp = get_unaligned_le16(&from[i]); +- if (ftmp == 0) ++ ftmp[0] = get_unaligned_le16(&from[i]); ++ if (ftmp[0] == 0) + break; ++ for (j = 1; j <= 2; j++) { ++ if (i + j < fromwords) ++ ftmp[j] = get_unaligned_le16(&from[i + j]); ++ else ++ ftmp[j] = 0; ++ } + + /* + * check to see if converting this character might make the +@@ -172,6 +199,19 @@ static int smb_from_utf16(char *to, const __le16 *from, int tolen, int fromlen, + /* put converted char into 'to' buffer */ + charlen = cifs_mapchar(&to[outlen], ftmp, codepage, mapchar); + outlen += charlen; ++ ++ /* ++ * charlen (=bytes of UTF-8 for 1 character) ++ * 4bytes UTF-8(surrogate pair) is charlen=4 ++ * (4bytes UTF-16 code) ++ * 7-8bytes UTF-8(IVS) is charlen=3+4 or 4+4 ++ * (2 UTF-8 pairs divided to 2 UTF-16 pairs) ++ */ ++ if (charlen == 4) ++ i++; ++ else if (charlen >= 5) ++ /* 5-6bytes UTF-8 */ ++ i += 2; + } + + /* properly null-terminate string */ +@@ -306,6 +346,9 @@ int smbConvertToUTF16(__le16 *target, const char *source, int srclen, + char src_char; + __le16 dst_char; + wchar_t tmp; ++ wchar_t wchar_to[6]; /* UTF-16 */ ++ int ret; ++ unicode_t u; + + if (!mapchars) + return smb_strtoUTF16(target, source, srclen, cp); +@@ -348,11 +391,57 @@ int smbConvertToUTF16(__le16 *target, const char *source, int srclen, + * if no match, use question mark, which at least in + * some cases serves as wild card + */ +- if (charlen < 1) { +- dst_char = cpu_to_le16(0x003f); +- charlen = 1; ++ if (charlen > 0) ++ goto ctoUTF16; ++ ++ /* convert SURROGATE_PAIR */ ++ if (strcmp(cp->charset, "utf8")) ++ goto unknown; ++ if (*(source + i) & 0x80) { ++ charlen = utf8_to_utf32(source + i, 6, &u); ++ if (charlen < 0) ++ goto unknown; ++ } else ++ goto unknown; ++ ret = utf8s_to_utf16s(source + i, charlen, ++ UTF16_LITTLE_ENDIAN, ++ wchar_to, 6); ++ if (ret < 0) ++ goto unknown; ++ ++ i += charlen; ++ dst_char = cpu_to_le16(*wchar_to); ++ if (charlen <= 3) ++ /* 1-3bytes UTF-8 to 2bytes UTF-16 */ ++ put_unaligned(dst_char, &target[j]); ++ else if (charlen == 4) { ++ /* ++ * 4bytes UTF-8(surrogate pair) to 4bytes UTF-16 ++ * 7-8bytes UTF-8(IVS) divided to 2 UTF-16 ++ * (charlen=3+4 or 4+4) ++ */ ++ put_unaligned(dst_char, &target[j]); ++ dst_char = cpu_to_le16(*(wchar_to + 1)); ++ j++; ++ put_unaligned(dst_char, &target[j]); ++ } else if (charlen >= 5) { ++ /* 5-6bytes UTF-8 to 6bytes UTF-16 */ ++ put_unaligned(dst_char, &target[j]); ++ dst_char = cpu_to_le16(*(wchar_to + 1)); ++ j++; ++ put_unaligned(dst_char, &target[j]); ++ dst_char = cpu_to_le16(*(wchar_to + 2)); ++ j++; ++ put_unaligned(dst_char, &target[j]); + } ++ continue; ++ ++unknown: ++ dst_char = cpu_to_le16(0x003f); ++ charlen = 1; + } ++ ++ctoUTF16: + /* + * character may take more than one byte in the source string, + * but will take exactly two bytes in the target string +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-avoid-duplicate-opinfo_put-call-on-error-of-sm.patch b/queue-6.6/ksmbd-avoid-duplicate-opinfo_put-call-on-error-of-sm.patch new file mode 100644 index 00000000000..9da44835671 --- /dev/null +++ b/queue-6.6/ksmbd-avoid-duplicate-opinfo_put-call-on-error-of-sm.patch @@ -0,0 +1,51 @@ +From 863e4d5f3789c5e036e008076264130b5263862a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:19 +0900 +Subject: ksmbd: avoid duplicate opinfo_put() call on error of + smb21_lease_break_ack() + +From: Namjae Jeon + +[ Upstream commit 658609d9a618d8881bf549b5893c0ba8fcff4526 ] + +opinfo_put() could be called twice on error of smb21_lease_break_ack(). +It will cause UAF issue if opinfo is referenced on other places. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index cbd5c5572217d..fbd708bb4a5b2 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -8219,6 +8219,11 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) + le32_to_cpu(req->LeaseState)); + } + ++ if (ret < 0) { ++ rsp->hdr.Status = err; ++ goto err_out; ++ } ++ + lease_state = lease->state; + opinfo->op_state = OPLOCK_STATE_NONE; + wake_up_interruptible_all(&opinfo->oplock_q); +@@ -8226,11 +8231,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) + wake_up_interruptible_all(&opinfo->oplock_brk); + opinfo_put(opinfo); + +- if (ret < 0) { +- rsp->hdr.Status = err; +- goto err_out; +- } +- + rsp->StructureSize = cpu_to_le16(36); + rsp->Reserved = 0; + rsp->Flags = 0; +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-don-t-update-op_state-as-oplock_state_none-on-.patch b/queue-6.6/ksmbd-don-t-update-op_state-as-oplock_state_none-on-.patch new file mode 100644 index 00000000000..5ebbfcda39f --- /dev/null +++ b/queue-6.6/ksmbd-don-t-update-op_state-as-oplock_state_none-on-.patch @@ -0,0 +1,35 @@ +From 7dc03a40f58d6b1244d68651051496d43a8a09c0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:13 +0900 +Subject: ksmbd: don't update ->op_state as OPLOCK_STATE_NONE on error + +From: Namjae Jeon + +[ Upstream commit cd80ce7e68f1624ac29cd0a6b057789d1236641e ] + +ksmbd set ->op_state as OPLOCK_STATE_NONE on lease break ack error. +op_state of lease should not be updated because client can send lease +break ack again. This patch fix smb2.lease.breaking2 test failure. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index de71532651d97..5bff6746234d4 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -8235,7 +8235,6 @@ static void smb21_lease_break_ack(struct ksmbd_work *work) + return; + + err_out: +- opinfo->op_state = OPLOCK_STATE_NONE; + wake_up_interruptible_all(&opinfo->oplock_q); + atomic_dec(&opinfo->breaking_cnt); + wake_up_interruptible_all(&opinfo->oplock_brk); +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-downgrade-rwh-lease-caching-state-to-rh-for-di.patch b/queue-6.6/ksmbd-downgrade-rwh-lease-caching-state-to-rh-for-di.patch new file mode 100644 index 00000000000..be544023772 --- /dev/null +++ b/queue-6.6/ksmbd-downgrade-rwh-lease-caching-state-to-rh-for-di.patch @@ -0,0 +1,94 @@ +From 60c4a1ff2ef4b280c894a0be0e525a4cd29a9e06 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:16 +0900 +Subject: ksmbd: downgrade RWH lease caching state to RH for directory + +From: Namjae Jeon + +[ Upstream commit eb547407f3572d2110cb1194ecd8865b3371a7a4 ] + +RWH(Read + Write + Handle) caching state is not supported for directory. +ksmbd downgrade it to RH for directory if client send RWH caching lease +state. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 9 +++++++-- + fs/smb/server/oplock.h | 2 +- + fs/smb/server/smb2pdu.c | 8 ++++---- + 3 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 5ef6af68d0de6..57950ba7e9257 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -1398,10 +1398,11 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) + /** + * parse_lease_state() - parse lease context containted in file open request + * @open_req: buffer containing smb2 file open(create) request ++ * @is_dir: whether leasing file is directory + * + * Return: oplock state, -ENOENT if create lease context not found + */ +-struct lease_ctx_info *parse_lease_state(void *open_req) ++struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) + { + struct create_context *cc; + struct smb2_create_req *req = (struct smb2_create_req *)open_req; +@@ -1419,7 +1420,11 @@ struct lease_ctx_info *parse_lease_state(void *open_req) + struct create_lease_v2 *lc = (struct create_lease_v2 *)cc; + + memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); +- lreq->req_state = lc->lcontext.LeaseState; ++ if (is_dir) ++ lreq->req_state = lc->lcontext.LeaseState & ++ ~SMB2_LEASE_WRITE_CACHING_LE; ++ else ++ lreq->req_state = lc->lcontext.LeaseState; + lreq->flags = lc->lcontext.LeaseFlags; + lreq->epoch = lc->lcontext.Epoch; + lreq->duration = lc->lcontext.LeaseDuration; +diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h +index ad31439c61fef..672127318c750 100644 +--- a/fs/smb/server/oplock.h ++++ b/fs/smb/server/oplock.h +@@ -109,7 +109,7 @@ void opinfo_put(struct oplock_info *opinfo); + + /* Lease related functions */ + void create_lease_buf(u8 *rbuf, struct lease *lease); +-struct lease_ctx_info *parse_lease_state(void *open_req); ++struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir); + __u8 smb2_map_lease_to_oplock(__le32 lease_state); + int lease_read_to_write(struct oplock_info *opinfo); + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 5bff6746234d4..c4b6adce178a2 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2732,10 +2732,6 @@ int smb2_open(struct ksmbd_work *work) + } + } + +- req_op_level = req->RequestedOplockLevel; +- if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) +- lc = parse_lease_state(req); +- + if (le32_to_cpu(req->ImpersonationLevel) > le32_to_cpu(IL_DELEGATE)) { + pr_err("Invalid impersonationlevel : 0x%x\n", + le32_to_cpu(req->ImpersonationLevel)); +@@ -3215,6 +3211,10 @@ int smb2_open(struct ksmbd_work *work) + need_truncate = 1; + } + ++ req_op_level = req->RequestedOplockLevel; ++ if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) ++ lc = parse_lease_state(req, S_ISDIR(file_inode(filp)->i_mode)); ++ + share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); + if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || + (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_kern_path_.patch b/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_kern_path_.patch new file mode 100644 index 00000000000..be281c3127b --- /dev/null +++ b/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_kern_path_.patch @@ -0,0 +1,44 @@ +From fcc9ac784adc57a05a7310ed135cc8c0c9cdc484 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:07 +0900 +Subject: ksmbd: fix kernel-doc comment of ksmbd_vfs_kern_path_locked() + +From: Namjae Jeon + +[ Upstream commit f6049712e520287ad695e9d4f1572ab76807fa0c ] + +Fix argument list that the kdoc format and script verified in +ksmbd_vfs_kern_path_locked(). + +fs/smb/server/vfs.c:1207: warning: Function parameter or member 'parent_path' +not described in 'ksmbd_vfs_kern_path_locked' + +Reported-by: kernel test robot +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/vfs.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 183e36cda59ec..533257b46fc17 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -1186,9 +1186,10 @@ static int ksmbd_vfs_lookup_in_dir(const struct path *dir, char *name, + + /** + * ksmbd_vfs_kern_path_locked() - lookup a file and get path info +- * @name: file path that is relative to share +- * @flags: lookup flags +- * @path: if lookup succeed, return path info ++ * @name: file path that is relative to share ++ * @flags: lookup flags ++ * @parent_path: if lookup succeed, return parent_path info ++ * @path: if lookup succeed, return path info + * @caseless: caseless filename lookup + * + * Return: 0 on success, otherwise error +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_setxattr.patch b/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_setxattr.patch new file mode 100644 index 00000000000..ea7b1475607 --- /dev/null +++ b/queue-6.6/ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_setxattr.patch @@ -0,0 +1,39 @@ +From 8b7cd2ea6b0823abce85a64bb76a8d63cf2f65a5 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:03 +0900 +Subject: ksmbd: fix kernel-doc comment of ksmbd_vfs_setxattr() + +From: Namjae Jeon + +[ Upstream commit 3354db668808d5b6d7c5e0cb19ff4c9da4bb5e58 ] + +Fix argument list that the kdoc format and script verified in +ksmbd_vfs_setxattr(). + +fs/smb/server/vfs.c:929: warning: Function parameter or member 'path' +not described in 'ksmbd_vfs_setxattr' + +Reported-by: kernel test robot +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/vfs.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 5a41c0b4e9335..183e36cda59ec 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -906,7 +906,7 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap, + /** + * ksmbd_vfs_setxattr() - vfs helper for smb set extended attributes value + * @idmap: idmap of the relevant mount +- * @dentry: dentry to set XATTR at ++ * @path: path of dentry to set XATTR at + * @attr_name: xattr name for setxattr + * @attr_value: xattr value to set + * @attr_size: size of xattr value +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-fix-missing-rdma-capable-flag-for-ipoib-device.patch b/queue-6.6/ksmbd-fix-missing-rdma-capable-flag-for-ipoib-device.patch new file mode 100644 index 00000000000..f612c736978 --- /dev/null +++ b/queue-6.6/ksmbd-fix-missing-rdma-capable-flag-for-ipoib-device.patch @@ -0,0 +1,89 @@ +From 7a6e40545d1690575a5500ab0dcadb4793ee3a17 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:04 +0900 +Subject: ksmbd: fix missing RDMA-capable flag for IPoIB device in + ksmbd_rdma_capable_netdev() + +From: Kangjing Huang + +[ Upstream commit ecce70cf17d91c3dd87a0c4ea00b2d1387729701 ] + +Physical ib_device does not have an underlying net_device, thus its +association with IPoIB net_device cannot be retrieved via +ops.get_netdev() or ib_device_get_by_netdev(). ksmbd reads physical +ib_device port GUID from the lower 16 bytes of the hardware addresses on +IPoIB net_device and match its underlying ib_device using ib_find_gid() + +Signed-off-by: Kangjing Huang +Acked-by: Namjae Jeon +Reviewed-by: Tom Talpey +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/transport_rdma.c | 40 +++++++++++++++++++++++++--------- + 1 file changed, 30 insertions(+), 10 deletions(-) + +diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c +index 3b269e1f523a1..c5629a68c8b73 100644 +--- a/fs/smb/server/transport_rdma.c ++++ b/fs/smb/server/transport_rdma.c +@@ -2140,8 +2140,7 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev) + if (ib_dev->node_type != RDMA_NODE_IB_CA) + smb_direct_port = SMB_DIRECT_PORT_IWARP; + +- if (!ib_dev->ops.get_netdev || +- !rdma_frwr_is_supported(&ib_dev->attrs)) ++ if (!rdma_frwr_is_supported(&ib_dev->attrs)) + return 0; + + smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL); +@@ -2241,17 +2240,38 @@ bool ksmbd_rdma_capable_netdev(struct net_device *netdev) + for (i = 0; i < smb_dev->ib_dev->phys_port_cnt; i++) { + struct net_device *ndev; + +- ndev = smb_dev->ib_dev->ops.get_netdev(smb_dev->ib_dev, +- i + 1); +- if (!ndev) +- continue; ++ if (smb_dev->ib_dev->ops.get_netdev) { ++ ndev = smb_dev->ib_dev->ops.get_netdev( ++ smb_dev->ib_dev, i + 1); ++ if (!ndev) ++ continue; + +- if (ndev == netdev) { ++ if (ndev == netdev) { ++ dev_put(ndev); ++ rdma_capable = true; ++ goto out; ++ } + dev_put(ndev); +- rdma_capable = true; +- goto out; ++ /* if ib_dev does not implement ops.get_netdev ++ * check for matching infiniband GUID in hw_addr ++ */ ++ } else if (netdev->type == ARPHRD_INFINIBAND) { ++ struct netdev_hw_addr *ha; ++ union ib_gid gid; ++ u32 port_num; ++ int ret; ++ ++ netdev_hw_addr_list_for_each( ++ ha, &netdev->dev_addrs) { ++ memcpy(&gid, ha->addr + 4, sizeof(gid)); ++ ret = ib_find_gid(smb_dev->ib_dev, &gid, ++ &port_num, NULL); ++ if (!ret) { ++ rdma_capable = true; ++ goto out; ++ } ++ } + } +- dev_put(ndev); + } + } + out: +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-lazy-v2-lease-break-on-smb2_write.patch b/queue-6.6/ksmbd-lazy-v2-lease-break-on-smb2_write.patch new file mode 100644 index 00000000000..0acd5cc8dca --- /dev/null +++ b/queue-6.6/ksmbd-lazy-v2-lease-break-on-smb2_write.patch @@ -0,0 +1,124 @@ +From 0291d341c42d2be8e72ec6ac68730aa09e05ccbf Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:18 +0900 +Subject: ksmbd: lazy v2 lease break on smb2_write() + +From: Namjae Jeon + +[ Upstream commit c2a721eead71202a0d8ddd9b56ec8dce652c71d1 ] + +Don't immediately send directory lease break notification on smb2_write(). +Instead, It postpones it until smb2_close(). + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 45 +++++++++++++++++++++++++++++++++++++-- + fs/smb/server/oplock.h | 1 + + fs/smb/server/vfs.c | 3 +++ + fs/smb/server/vfs_cache.h | 1 + + 4 files changed, 48 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 147d98427ce89..562b180459a1a 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -396,8 +396,8 @@ void close_id_del_oplock(struct ksmbd_file *fp) + { + struct oplock_info *opinfo; + +- if (S_ISDIR(file_inode(fp->filp)->i_mode)) +- return; ++ if (fp->reserve_lease_break) ++ smb_lazy_parent_lease_break_close(fp); + + opinfo = opinfo_get(fp); + if (!opinfo) +@@ -1127,6 +1127,47 @@ void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, + ksmbd_inode_put(p_ci); + } + ++void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp) ++{ ++ struct oplock_info *opinfo; ++ struct ksmbd_inode *p_ci = NULL; ++ ++ rcu_read_lock(); ++ opinfo = rcu_dereference(fp->f_opinfo); ++ rcu_read_unlock(); ++ ++ if (!opinfo->is_lease || opinfo->o_lease->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) { ++ 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 +diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h +index b64d1536882a1..5b93ea9196c01 100644 +--- a/fs/smb/server/oplock.h ++++ b/fs/smb/server/oplock.h +@@ -129,4 +129,5 @@ int find_same_lease_key(struct ksmbd_session *sess, struct ksmbd_inode *ci, + void destroy_lease_table(struct ksmbd_conn *conn); + void smb_send_parent_lease_break_noti(struct ksmbd_file *fp, + struct lease_ctx_info *lctx); ++void smb_lazy_parent_lease_break_close(struct ksmbd_file *fp); + #endif /* __KSMBD_OPLOCK_H */ +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 9091dcd7a3102..4277750a6da1b 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -517,6 +517,9 @@ int ksmbd_vfs_write(struct ksmbd_work *work, struct ksmbd_file *fp, + } + } + ++ /* Reserve lease break for parent dir at closing time */ ++ fp->reserve_lease_break = true; ++ + /* Do we need to break any of a levelII oplock? */ + smb_break_all_levII_oplock(work, fp, 1); + +diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h +index 4d4938d6029b6..a528f0cc775ae 100644 +--- a/fs/smb/server/vfs_cache.h ++++ b/fs/smb/server/vfs_cache.h +@@ -105,6 +105,7 @@ struct ksmbd_file { + struct ksmbd_readdir_data readdir_data; + int dot_dotdot[2]; + unsigned int f_state; ++ bool reserve_lease_break; + }; + + static inline void set_ctx_actor(struct dir_context *ctx, +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-move-oplock-handling-after-unlock-parent-dir.patch b/queue-6.6/ksmbd-move-oplock-handling-after-unlock-parent-dir.patch new file mode 100644 index 00000000000..9455825dbad --- /dev/null +++ b/queue-6.6/ksmbd-move-oplock-handling-after-unlock-parent-dir.patch @@ -0,0 +1,363 @@ +From 8cbb70617659725ea092ed031b7ad2ea57f10bbd Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:10 +0900 +Subject: ksmbd: move oplock handling after unlock parent dir + +From: Namjae Jeon + +[ Upstream commit 2e450920d58b4991a436c8cecf3484bcacd8e535 ] + +ksmbd should process secound parallel smb2 create request during waiting +oplock break ack. parent lock range that is too large in smb2_open() causes +smb2_open() to be serialized. Move the oplock handling to the bottom of +smb2_open() and make it called after parent unlock. This fixes the failure +of smb2.lease.breaking1 testcase. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 121 +++++++++++++++++++++------------------- + 1 file changed, 65 insertions(+), 56 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 28b61dad27498..e58504d0e9c1e 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -2691,7 +2691,7 @@ int smb2_open(struct ksmbd_work *work) + *(char *)req->Buffer == '\\') { + pr_err("not allow directory name included leading slash\n"); + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } + + name = smb2_get_name(req->Buffer, +@@ -2702,7 +2702,7 @@ int smb2_open(struct ksmbd_work *work) + if (rc != -ENOMEM) + rc = -ENOENT; + name = NULL; +- goto err_out1; ++ goto err_out2; + } + + ksmbd_debug(SMB, "converted name = %s\n", name); +@@ -2710,28 +2710,28 @@ int smb2_open(struct ksmbd_work *work) + if (!test_share_config_flag(work->tcon->share_conf, + KSMBD_SHARE_FLAG_STREAMS)) { + rc = -EBADF; +- goto err_out1; ++ goto err_out2; + } + rc = parse_stream_name(name, &stream_name, &s_type); + if (rc < 0) +- goto err_out1; ++ goto err_out2; + } + + rc = ksmbd_validate_filename(name); + if (rc < 0) +- goto err_out1; ++ goto err_out2; + + if (ksmbd_share_veto_filename(share, name)) { + rc = -ENOENT; + ksmbd_debug(SMB, "Reject open(), vetoed file: %s\n", + name); +- goto err_out1; ++ goto err_out2; + } + } else { + name = kstrdup("", GFP_KERNEL); + if (!name) { + rc = -ENOMEM; +- goto err_out1; ++ goto err_out2; + } + } + +@@ -2744,14 +2744,14 @@ int smb2_open(struct ksmbd_work *work) + le32_to_cpu(req->ImpersonationLevel)); + rc = -EIO; + rsp->hdr.Status = STATUS_BAD_IMPERSONATION_LEVEL; +- goto err_out1; ++ goto err_out2; + } + + if (req->CreateOptions && !(req->CreateOptions & CREATE_OPTIONS_MASK_LE)) { + pr_err("Invalid create options : 0x%x\n", + le32_to_cpu(req->CreateOptions)); + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } else { + if (req->CreateOptions & FILE_SEQUENTIAL_ONLY_LE && + req->CreateOptions & FILE_RANDOM_ACCESS_LE) +@@ -2761,13 +2761,13 @@ int smb2_open(struct ksmbd_work *work) + (FILE_OPEN_BY_FILE_ID_LE | CREATE_TREE_CONNECTION | + FILE_RESERVE_OPFILTER_LE)) { + rc = -EOPNOTSUPP; +- goto err_out1; ++ goto err_out2; + } + + if (req->CreateOptions & FILE_DIRECTORY_FILE_LE) { + if (req->CreateOptions & FILE_NON_DIRECTORY_FILE_LE) { + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } else if (req->CreateOptions & FILE_NO_COMPRESSION_LE) { + req->CreateOptions = ~(FILE_NO_COMPRESSION_LE); + } +@@ -2779,21 +2779,21 @@ int smb2_open(struct ksmbd_work *work) + pr_err("Invalid create disposition : 0x%x\n", + le32_to_cpu(req->CreateDisposition)); + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } + + if (!(req->DesiredAccess & DESIRED_ACCESS_MASK)) { + pr_err("Invalid desired access : 0x%x\n", + le32_to_cpu(req->DesiredAccess)); + rc = -EACCES; +- goto err_out1; ++ goto err_out2; + } + + if (req->FileAttributes && !(req->FileAttributes & FILE_ATTRIBUTE_MASK_LE)) { + pr_err("Invalid file attribute : 0x%x\n", + le32_to_cpu(req->FileAttributes)); + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } + + if (req->CreateContextsOffset) { +@@ -2801,19 +2801,19 @@ int smb2_open(struct ksmbd_work *work) + context = smb2_find_context_vals(req, SMB2_CREATE_EA_BUFFER, 4); + if (IS_ERR(context)) { + rc = PTR_ERR(context); +- goto err_out1; ++ goto err_out2; + } else if (context) { + ea_buf = (struct create_ea_buf_req *)context; + if (le16_to_cpu(context->DataOffset) + + le32_to_cpu(context->DataLength) < + sizeof(struct create_ea_buf_req)) { + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } + if (req->CreateOptions & FILE_NO_EA_KNOWLEDGE_LE) { + rsp->hdr.Status = STATUS_ACCESS_DENIED; + rc = -EACCES; +- goto err_out1; ++ goto err_out2; + } + } + +@@ -2821,7 +2821,7 @@ int smb2_open(struct ksmbd_work *work) + SMB2_CREATE_QUERY_MAXIMAL_ACCESS_REQUEST, 4); + if (IS_ERR(context)) { + rc = PTR_ERR(context); +- goto err_out1; ++ goto err_out2; + } else if (context) { + ksmbd_debug(SMB, + "get query maximal access context\n"); +@@ -2832,11 +2832,11 @@ int smb2_open(struct ksmbd_work *work) + SMB2_CREATE_TIMEWARP_REQUEST, 4); + if (IS_ERR(context)) { + rc = PTR_ERR(context); +- goto err_out1; ++ goto err_out2; + } else if (context) { + ksmbd_debug(SMB, "get timewarp context\n"); + rc = -EBADF; +- goto err_out1; ++ goto err_out2; + } + + if (tcon->posix_extensions) { +@@ -2844,7 +2844,7 @@ int smb2_open(struct ksmbd_work *work) + SMB2_CREATE_TAG_POSIX, 16); + if (IS_ERR(context)) { + rc = PTR_ERR(context); +- goto err_out1; ++ goto err_out2; + } else if (context) { + struct create_posix *posix = + (struct create_posix *)context; +@@ -2852,7 +2852,7 @@ int smb2_open(struct ksmbd_work *work) + le32_to_cpu(context->DataLength) < + sizeof(struct create_posix) - 4) { + rc = -EINVAL; +- goto err_out1; ++ goto err_out2; + } + ksmbd_debug(SMB, "get posix context\n"); + +@@ -2864,7 +2864,7 @@ int smb2_open(struct ksmbd_work *work) + + if (ksmbd_override_fsids(work)) { + rc = -ENOMEM; +- goto err_out1; ++ goto err_out2; + } + + rc = ksmbd_vfs_kern_path_locked(work, name, LOOKUP_NO_SYMLINKS, +@@ -3177,11 +3177,6 @@ int smb2_open(struct ksmbd_work *work) + + fp->attrib_only = !(req->DesiredAccess & ~(FILE_READ_ATTRIBUTES_LE | + FILE_WRITE_ATTRIBUTES_LE | FILE_SYNCHRONIZE_LE)); +- if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && +- !fp->attrib_only && !stream_name) { +- smb_break_all_oplock(work, fp); +- need_truncate = 1; +- } + + /* fp should be searchable through ksmbd_inode.m_fp_list + * after daccess, saccess, attrib_only, and stream are +@@ -3197,13 +3192,39 @@ int smb2_open(struct ksmbd_work *work) + goto err_out; + } + ++ rc = ksmbd_vfs_getattr(&path, &stat); ++ if (rc) ++ goto err_out; ++ ++ if (stat.result_mask & STATX_BTIME) ++ fp->create_time = ksmbd_UnixTimeToNT(stat.btime); ++ else ++ fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); ++ if (req->FileAttributes || fp->f_ci->m_fattr == 0) ++ fp->f_ci->m_fattr = ++ cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); ++ ++ if (!created) ++ smb2_update_xattrs(tcon, &path, fp); ++ else ++ smb2_new_xattrs(tcon, &path, fp); ++ ++ if (file_present || created) ++ ksmbd_vfs_kern_path_unlock(&parent_path, &path); ++ ++ if (!S_ISDIR(file_inode(filp)->i_mode) && open_flags & O_TRUNC && ++ !fp->attrib_only && !stream_name) { ++ smb_break_all_oplock(work, fp); ++ need_truncate = 1; ++ } ++ + share_ret = ksmbd_smb_check_shared_mode(fp->filp, fp); + if (!test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_OPLOCKS) || + (req_op_level == SMB2_OPLOCK_LEVEL_LEASE && + !(conn->vals->capabilities & SMB2_GLOBAL_CAP_LEASING))) { + if (share_ret < 0 && !S_ISDIR(file_inode(fp->filp)->i_mode)) { + rc = share_ret; +- goto err_out; ++ goto err_out1; + } + } else { + if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { +@@ -3213,7 +3234,7 @@ int smb2_open(struct ksmbd_work *work) + name, req_op_level, lc->req_state); + rc = find_same_lease_key(sess, fp->f_ci, lc); + if (rc) +- goto err_out; ++ goto err_out1; + } else if (open_flags == O_RDONLY && + (req_op_level == SMB2_OPLOCK_LEVEL_BATCH || + req_op_level == SMB2_OPLOCK_LEVEL_EXCLUSIVE)) +@@ -3224,12 +3245,18 @@ int smb2_open(struct ksmbd_work *work) + le32_to_cpu(req->hdr.Id.SyncId.TreeId), + lc, share_ret); + if (rc < 0) +- goto err_out; ++ goto err_out1; + } + + if (req->CreateOptions & FILE_DELETE_ON_CLOSE_LE) + ksmbd_fd_set_delete_on_close(fp, file_info); + ++ if (need_truncate) { ++ rc = smb2_create_truncate(&fp->filp->f_path); ++ if (rc) ++ goto err_out1; ++ } ++ + if (req->CreateContextsOffset) { + struct create_alloc_size_req *az_req; + +@@ -3237,7 +3264,7 @@ int smb2_open(struct ksmbd_work *work) + SMB2_CREATE_ALLOCATION_SIZE, 4); + if (IS_ERR(az_req)) { + rc = PTR_ERR(az_req); +- goto err_out; ++ goto err_out1; + } else if (az_req) { + loff_t alloc_size; + int err; +@@ -3246,7 +3273,7 @@ int smb2_open(struct ksmbd_work *work) + le32_to_cpu(az_req->ccontext.DataLength) < + sizeof(struct create_alloc_size_req)) { + rc = -EINVAL; +- goto err_out; ++ goto err_out1; + } + alloc_size = le64_to_cpu(az_req->AllocationSize); + ksmbd_debug(SMB, +@@ -3264,30 +3291,13 @@ int smb2_open(struct ksmbd_work *work) + context = smb2_find_context_vals(req, SMB2_CREATE_QUERY_ON_DISK_ID, 4); + if (IS_ERR(context)) { + rc = PTR_ERR(context); +- goto err_out; ++ goto err_out1; + } else if (context) { + ksmbd_debug(SMB, "get query on disk id context\n"); + query_disk_id = 1; + } + } + +- rc = ksmbd_vfs_getattr(&path, &stat); +- if (rc) +- goto err_out; +- +- if (stat.result_mask & STATX_BTIME) +- fp->create_time = ksmbd_UnixTimeToNT(stat.btime); +- else +- fp->create_time = ksmbd_UnixTimeToNT(stat.ctime); +- if (req->FileAttributes || fp->f_ci->m_fattr == 0) +- fp->f_ci->m_fattr = +- cpu_to_le32(smb2_get_dos_mode(&stat, le32_to_cpu(req->FileAttributes))); +- +- if (!created) +- smb2_update_xattrs(tcon, &path, fp); +- else +- smb2_new_xattrs(tcon, &path, fp); +- + memcpy(fp->client_guid, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE); + + rsp->StructureSize = cpu_to_le16(89); +@@ -3394,14 +3404,13 @@ int smb2_open(struct ksmbd_work *work) + } + + err_out: +- if (file_present || created) ++ if (rc && (file_present || created)) + ksmbd_vfs_kern_path_unlock(&parent_path, &path); + +- if (fp && need_truncate) +- rc = smb2_create_truncate(&fp->filp->f_path); +- +- ksmbd_revert_fsids(work); + err_out1: ++ ksmbd_revert_fsids(work); ++ ++err_out2: + if (!rc) { + ksmbd_update_fstate(&work->sess->file_table, fp, FP_INITED); + rc = ksmbd_iov_pin_rsp(work, (void *)rsp, iov_len); +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-move-setting-smb2_flags_async_command-and-asyn.patch b/queue-6.6/ksmbd-move-setting-smb2_flags_async_command-and-asyn.patch new file mode 100644 index 00000000000..fe357f3912b --- /dev/null +++ b/queue-6.6/ksmbd-move-setting-smb2_flags_async_command-and-asyn.patch @@ -0,0 +1,57 @@ +From 7c32b1c166d3279f9cf01c8409f4aa9cf08bd291 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:12 +0900 +Subject: ksmbd: move setting SMB2_FLAGS_ASYNC_COMMAND and AsyncId + +From: Namjae Jeon + +[ Upstream commit 9ac45ac7cf65b0623ceeab9b28b307a08efa22dc ] + +Directly set SMB2_FLAGS_ASYNC_COMMAND flags and AsyncId in smb2 header of +interim response instead of current response header. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 7 ++----- + 1 file changed, 2 insertions(+), 5 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index e58504d0e9c1e..de71532651d97 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -657,13 +657,9 @@ smb2_get_name(const char *src, const int maxlen, struct nls_table *local_nls) + + int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) + { +- struct smb2_hdr *rsp_hdr; + struct ksmbd_conn *conn = work->conn; + int id; + +- rsp_hdr = ksmbd_resp_buf_next(work); +- rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; +- + id = ksmbd_acquire_async_msg_id(&conn->async_ida); + if (id < 0) { + pr_err("Failed to alloc async message id\n"); +@@ -671,7 +667,6 @@ int setup_async_work(struct ksmbd_work *work, void (*fn)(void **), void **arg) + } + work->asynchronous = true; + work->async_id = id; +- rsp_hdr->Id.AsyncId = cpu_to_le64(id); + + ksmbd_debug(SMB, + "Send interim Response to inform async request id : %d\n", +@@ -723,6 +718,8 @@ void smb2_send_interim_resp(struct ksmbd_work *work, __le32 status) + __SMB2_HEADER_STRUCTURE_SIZE); + + rsp_hdr = smb2_get_msg(in_work->response_buf); ++ rsp_hdr->Flags |= SMB2_FLAGS_ASYNC_COMMAND; ++ rsp_hdr->Id.AsyncId = cpu_to_le64(work->async_id); + smb2_set_err_rsp(in_work); + rsp_hdr->Status = status; + +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-no-need-to-wait-for-binded-connection-terminat.patch b/queue-6.6/ksmbd-no-need-to-wait-for-binded-connection-terminat.patch new file mode 100644 index 00000000000..be996d99083 --- /dev/null +++ b/queue-6.6/ksmbd-no-need-to-wait-for-binded-connection-terminat.patch @@ -0,0 +1,51 @@ +From ea08891fcdc4be6df14a3d6d80df248307d5c443 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:06 +0900 +Subject: ksmbd: no need to wait for binded connection termination at logoff + +From: Namjae Jeon + +[ Upstream commit 67797da8a4b82446d42c52b6ee1419a3100d78ff ] + +The connection could be binded to the existing session for Multichannel. +session will be destroyed when binded connections are released. +So no need to wait for that's connection at logoff. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/connection.c | 16 ---------------- + 1 file changed, 16 deletions(-) + +diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c +index 4b38c3a285f60..b6fa1e285c401 100644 +--- a/fs/smb/server/connection.c ++++ b/fs/smb/server/connection.c +@@ -167,23 +167,7 @@ void ksmbd_all_conn_set_status(u64 sess_id, u32 status) + + void ksmbd_conn_wait_idle(struct ksmbd_conn *conn, u64 sess_id) + { +- struct ksmbd_conn *bind_conn; +- + wait_event(conn->req_running_q, atomic_read(&conn->req_running) < 2); +- +- down_read(&conn_list_lock); +- list_for_each_entry(bind_conn, &conn_list, conns_list) { +- if (bind_conn == conn) +- continue; +- +- if ((bind_conn->binding || xa_load(&bind_conn->sessions, sess_id)) && +- !ksmbd_conn_releasing(bind_conn) && +- atomic_read(&bind_conn->req_running)) { +- wait_event(bind_conn->req_running_q, +- atomic_read(&bind_conn->req_running) == 0); +- } +- } +- up_read(&conn_list_lock); + } + + int ksmbd_conn_write(struct ksmbd_work *work) +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-prevent-memory-leak-on-error-return.patch b/queue-6.6/ksmbd-prevent-memory-leak-on-error-return.patch new file mode 100644 index 00000000000..5bc1d4843cd --- /dev/null +++ b/queue-6.6/ksmbd-prevent-memory-leak-on-error-return.patch @@ -0,0 +1,53 @@ +From e75aebb6c928acc8f25124afd53b26f394eaa659 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:08 +0900 +Subject: ksmbd: prevent memory leak on error return + +From: Zongmin Zhou + +[ Upstream commit 90044481e7cca6cb3125b3906544954a25f1309f ] + +When allocated memory for 'new' failed,just return +will cause memory leak of 'ar'. + +Fixes: 1819a9042999 ("ksmbd: reorganize ksmbd_iov_pin_rsp()") +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202311031837.H3yo7JVl-lkp@intel.com/ +Signed-off-by: Zongmin Zhou +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/ksmbd_work.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c +index a2ed441e837ae..2510b9f3c8c14 100644 +--- a/fs/smb/server/ksmbd_work.c ++++ b/fs/smb/server/ksmbd_work.c +@@ -106,7 +106,7 @@ static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib, + static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, + void *aux_buf, unsigned int aux_size) + { +- struct aux_read *ar; ++ struct aux_read *ar = NULL; + int need_iov_cnt = 1; + + if (aux_size) { +@@ -123,8 +123,11 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, + new = krealloc(work->iov, + sizeof(struct kvec) * work->iov_alloc_cnt, + GFP_KERNEL | __GFP_ZERO); +- if (!new) ++ if (!new) { ++ kfree(ar); ++ work->iov_alloc_cnt -= 4; + return -ENOMEM; ++ } + work->iov = new; + } + +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-release-interim-response-after-sending-status-.patch b/queue-6.6/ksmbd-release-interim-response-after-sending-status-.patch new file mode 100644 index 00000000000..5dece04d65f --- /dev/null +++ b/queue-6.6/ksmbd-release-interim-response-after-sending-status-.patch @@ -0,0 +1,51 @@ +From 7b205000c9ef02b1c2020d70e1366eb8d4254ebe Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:11 +0900 +Subject: ksmbd: release interim response after sending status pending response + +From: Namjae Jeon + +[ Upstream commit 2a3f7857ec742e212d6cee7fbbf7b0e2ae7f5161 ] + +Add missing release async id and delete interim response entry after +sending status pending response. This only cause when smb2 lease is enable. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/ksmbd_work.c | 3 +++ + fs/smb/server/oplock.c | 3 ++- + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c +index 2510b9f3c8c14..d7c676c151e20 100644 +--- a/fs/smb/server/ksmbd_work.c ++++ b/fs/smb/server/ksmbd_work.c +@@ -56,6 +56,9 @@ void ksmbd_free_work_struct(struct ksmbd_work *work) + kfree(work->tr_buf); + kvfree(work->request_buf); + kfree(work->iov); ++ if (!list_empty(&work->interim_entry)) ++ list_del(&work->interim_entry); ++ + if (work->async_id) + ksmbd_release_id(&work->conn->async_ida, work->async_id); + kmem_cache_free(work_cache, work); +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 9bc0103720f57..50c68beb71d6c 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -833,7 +833,8 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo) + interim_entry); + setup_async_work(in_work, NULL, NULL); + smb2_send_interim_resp(in_work, STATUS_PENDING); +- list_del(&in_work->interim_entry); ++ list_del_init(&in_work->interim_entry); ++ release_async_work(in_work); + } + INIT_WORK(&work->work, __smb2_lease_break_noti); + ksmbd_queue_work(work); +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-remove-unused-field-in-ksmbd_user-struct.patch b/queue-6.6/ksmbd-remove-unused-field-in-ksmbd_user-struct.patch new file mode 100644 index 00000000000..5665375c47b --- /dev/null +++ b/queue-6.6/ksmbd-remove-unused-field-in-ksmbd_user-struct.patch @@ -0,0 +1,34 @@ +From ca9d4237b8763667328cb86ff0a5364c972c76fb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:01 +0900 +Subject: ksmbd: Remove unused field in ksmbd_user struct + +From: Cheng-Han Wu + +[ Upstream commit eacc655e18d1dec9b50660d16a1ddeeb4d6c48f2 ] + +fs/smb/server/mgmt/user_config.h:21: Remove the unused field 'failed_login_count' from the ksmbd_user struct. + +Signed-off-by: Cheng-Han Wu +Acked-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/mgmt/user_config.h | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/fs/smb/server/mgmt/user_config.h b/fs/smb/server/mgmt/user_config.h +index 6a44109617f14..e068a19fd9049 100644 +--- a/fs/smb/server/mgmt/user_config.h ++++ b/fs/smb/server/mgmt/user_config.h +@@ -18,7 +18,6 @@ struct ksmbd_user { + + size_t passkey_sz; + char *passkey; +- unsigned int failed_login_count; + }; + + static inline bool user_guest(struct ksmbd_user *user) +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-reorganize-ksmbd_iov_pin_rsp.patch b/queue-6.6/ksmbd-reorganize-ksmbd_iov_pin_rsp.patch new file mode 100644 index 00000000000..442e4e81552 --- /dev/null +++ b/queue-6.6/ksmbd-reorganize-ksmbd_iov_pin_rsp.patch @@ -0,0 +1,99 @@ +From 2cdb97e320d71b96acdcbca1d0ece7761429637c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:02 +0900 +Subject: ksmbd: reorganize ksmbd_iov_pin_rsp() + +From: Namjae Jeon + +[ Upstream commit 1819a904299942b309f687cc0f08b123500aa178 ] + +If ksmbd_iov_pin_rsp fail, io vertor should be rollback. +This patch moves memory allocations to before setting the io vector +to avoid rollbacks. + +Fixes: e2b76ab8b5c9 ("ksmbd: add support for read compound") +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/ksmbd_work.c | 43 +++++++++++++++++++------------------- + 1 file changed, 22 insertions(+), 21 deletions(-) + +diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c +index 51def3ca74c01..a2ed441e837ae 100644 +--- a/fs/smb/server/ksmbd_work.c ++++ b/fs/smb/server/ksmbd_work.c +@@ -95,11 +95,28 @@ bool ksmbd_queue_work(struct ksmbd_work *work) + return queue_work(ksmbd_wq, &work->work); + } + +-static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib, +- unsigned int ib_len) ++static inline void __ksmbd_iov_pin(struct ksmbd_work *work, void *ib, ++ unsigned int ib_len) + { ++ work->iov[++work->iov_idx].iov_base = ib; ++ work->iov[work->iov_idx].iov_len = ib_len; ++ work->iov_cnt++; ++} ++ ++static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, ++ void *aux_buf, unsigned int aux_size) ++{ ++ struct aux_read *ar; ++ int need_iov_cnt = 1; + +- if (work->iov_alloc_cnt <= work->iov_cnt) { ++ if (aux_size) { ++ need_iov_cnt++; ++ ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL); ++ if (!ar) ++ return -ENOMEM; ++ } ++ ++ if (work->iov_alloc_cnt < work->iov_cnt + need_iov_cnt) { + struct kvec *new; + + work->iov_alloc_cnt += 4; +@@ -111,16 +128,6 @@ static int ksmbd_realloc_iov_pin(struct ksmbd_work *work, void *ib, + work->iov = new; + } + +- work->iov[++work->iov_idx].iov_base = ib; +- work->iov[work->iov_idx].iov_len = ib_len; +- work->iov_cnt++; +- +- return 0; +-} +- +-static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, +- void *aux_buf, unsigned int aux_size) +-{ + /* Plus rfc_length size on first iov */ + if (!work->iov_idx) { + work->iov[work->iov_idx].iov_base = work->response_buf; +@@ -129,19 +136,13 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len, + work->iov_cnt++; + } + +- ksmbd_realloc_iov_pin(work, ib, len); ++ __ksmbd_iov_pin(work, ib, len); + inc_rfc1001_len(work->iov[0].iov_base, len); + + if (aux_size) { +- struct aux_read *ar; +- +- ksmbd_realloc_iov_pin(work, aux_buf, aux_size); ++ __ksmbd_iov_pin(work, aux_buf, aux_size); + inc_rfc1001_len(work->iov[0].iov_base, aux_size); + +- ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL); +- if (!ar) +- return -ENOMEM; +- + ar->buf = aux_buf; + list_add(&ar->entry, &work->aux_read_list); + } +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-send-v2-lease-break-notification-for-directory.patch b/queue-6.6/ksmbd-send-v2-lease-break-notification-for-directory.patch new file mode 100644 index 00000000000..0f4cf4ce11b --- /dev/null +++ b/queue-6.6/ksmbd-send-v2-lease-break-notification-for-directory.patch @@ -0,0 +1,230 @@ +From 6f97c5d91588a4e085325e121593d11e2f582608 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:17 +0900 +Subject: ksmbd: send v2 lease break notification for directory + +From: Namjae Jeon + +[ Upstream commit d47d9886aeef79feba7adac701a510d65f3682b5 ] + +If client send different parent key, different client guid, or there is +no parent lease key flags in create context v2 lease, ksmbd send lease +break to client. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/common/smb2pdu.h | 1 + + fs/smb/server/oplock.c | 56 +++++++++++++++++++++++++++++++++++---- + fs/smb/server/oplock.h | 4 +++ + fs/smb/server/smb2pdu.c | 7 +++++ + fs/smb/server/vfs_cache.c | 13 ++++++++- + fs/smb/server/vfs_cache.h | 2 ++ + 6 files changed, 77 insertions(+), 6 deletions(-) + +diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h +index ec20c83cc8366..d58550c1c9378 100644 +--- a/fs/smb/common/smb2pdu.h ++++ b/fs/smb/common/smb2pdu.h +@@ -1228,6 +1228,7 @@ struct create_mxac_rsp { + #define SMB2_LEASE_WRITE_CACHING_LE cpu_to_le32(0x04) + + #define SMB2_LEASE_FLAG_BREAK_IN_PROGRESS_LE cpu_to_le32(0x02) ++#define SMB2_LEASE_FLAG_PARENT_LEASE_KEY_SET_LE cpu_to_le32(0x04) + + #define SMB2_LEASE_KEY_SIZE 16 + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 57950ba7e9257..147d98427ce89 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -102,6 +102,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx) + 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); +@@ -543,12 +544,13 @@ static struct oplock_info *same_client_has_lease(struct ksmbd_inode *ci, + /* 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) { +@@ -900,7 +902,8 @@ static int oplock_break(struct oplock_info *brk_opinfo, int req_op_level) + 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 +@@ -1082,6 +1085,48 @@ static void set_oplock_level(struct oplock_info *opinfo, int level, + } + } + ++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 +@@ -1420,10 +1465,11 @@ struct lease_ctx_info *parse_lease_state(void *open_req, bool is_dir) + 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; +diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h +index 672127318c750..b64d1536882a1 100644 +--- a/fs/smb/server/oplock.h ++++ b/fs/smb/server/oplock.h +@@ -36,6 +36,7 @@ struct lease_ctx_info { + __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; + __le16 epoch; + int version; ++ bool is_dir; + }; + + struct lease_table { +@@ -54,6 +55,7 @@ struct lease { + __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; + int version; + unsigned short epoch; ++ bool is_dir; + struct lease_table *l_lb; + }; + +@@ -125,4 +127,6 @@ struct oplock_info *lookup_lease_in_table(struct ksmbd_conn *conn, + 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 */ +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index c4b6adce178a2..cbd5c5572217d 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -3225,6 +3225,13 @@ int smb2_open(struct ksmbd_work *work) + } + } else { + if (req_op_level == SMB2_OPLOCK_LEVEL_LEASE) { ++ /* ++ * Compare parent lease using parent key. If there is no ++ * a lease that has same parent key, Send lease break ++ * notification. ++ */ ++ smb_send_parent_lease_break_noti(fp, lc); ++ + req_op_level = smb2_map_lease_to_oplock(lc->req_state); + ksmbd_debug(SMB, + "lease req for(%s) req oplock state 0x%x, lease state 0x%x\n", +diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c +index ddf233994ddbb..4e82ff627d122 100644 +--- a/fs/smb/server/vfs_cache.c ++++ b/fs/smb/server/vfs_cache.c +@@ -87,6 +87,17 @@ static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp) + 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; +@@ -199,7 +210,7 @@ static void ksmbd_inode_free(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); +diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h +index 8325cf4527c46..4d4938d6029b6 100644 +--- a/fs/smb/server/vfs_cache.h ++++ b/fs/smb/server/vfs_cache.h +@@ -138,6 +138,8 @@ struct ksmbd_file *ksmbd_lookup_foreign_fd(struct ksmbd_work *work, u64 id); + struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, + u64 pid); + void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); ++struct ksmbd_inode *ksmbd_inode_lookup_lock(struct dentry *d); ++void ksmbd_inode_put(struct ksmbd_inode *ci); + struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); + struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); + struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-separately-allocate-ci-per-dentry.patch b/queue-6.6/ksmbd-separately-allocate-ci-per-dentry.patch new file mode 100644 index 00000000000..99ad5e5acc0 --- /dev/null +++ b/queue-6.6/ksmbd-separately-allocate-ci-per-dentry.patch @@ -0,0 +1,181 @@ +From 640162d3794d3503e8aa018f14dd655a7f4e9549 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:09 +0900 +Subject: ksmbd: separately allocate ci per dentry + +From: Namjae Jeon + +[ Upstream commit 4274a9dc6aeb9fea66bffba15697a35ae8983b6a ] + +xfstests generic/002 test fail when enabling smb2 leases feature. +This test create hard link file, but removeal failed. +ci has a file open count to count file open through the smb client, +but in the case of hard link files, The allocation of ci per inode +cause incorrectly open count for file deletion. This patch allocate +ci per dentry to counts open counts for hard link. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/smb2pdu.c | 2 +- + fs/smb/server/vfs.c | 2 +- + fs/smb/server/vfs_cache.c | 33 +++++++++++++-------------------- + fs/smb/server/vfs_cache.h | 6 +++--- + 4 files changed, 18 insertions(+), 25 deletions(-) + +diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c +index 2b248d45d40ae..28b61dad27498 100644 +--- a/fs/smb/server/smb2pdu.c ++++ b/fs/smb/server/smb2pdu.c +@@ -3039,7 +3039,7 @@ int smb2_open(struct ksmbd_work *work) + } + } + +- rc = ksmbd_query_inode_status(d_inode(path.dentry->d_parent)); ++ rc = ksmbd_query_inode_status(path.dentry->d_parent); + if (rc == KSMBD_INODE_STATUS_PENDING_DELETE) { + rc = -EBUSY; + goto err_out; +diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c +index 533257b46fc17..9091dcd7a3102 100644 +--- a/fs/smb/server/vfs.c ++++ b/fs/smb/server/vfs.c +@@ -719,7 +719,7 @@ int ksmbd_vfs_rename(struct ksmbd_work *work, const struct path *old_path, + goto out3; + } + +- parent_fp = ksmbd_lookup_fd_inode(d_inode(old_child->d_parent)); ++ parent_fp = ksmbd_lookup_fd_inode(old_child->d_parent); + if (parent_fp) { + if (parent_fp->daccess & FILE_DELETE_LE) { + pr_err("parent dir is opened with delete access\n"); +diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c +index c91eac6514dd9..ddf233994ddbb 100644 +--- a/fs/smb/server/vfs_cache.c ++++ b/fs/smb/server/vfs_cache.c +@@ -66,14 +66,14 @@ static unsigned long inode_hash(struct super_block *sb, unsigned long hashval) + return tmp & inode_hash_mask; + } + +-static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode) ++static struct ksmbd_inode *__ksmbd_inode_lookup(struct dentry *de) + { + struct hlist_head *head = inode_hashtable + +- inode_hash(inode->i_sb, inode->i_ino); ++ inode_hash(d_inode(de)->i_sb, (unsigned long)de); + struct ksmbd_inode *ci = NULL, *ret_ci = NULL; + + hlist_for_each_entry(ci, head, m_hash) { +- if (ci->m_inode == inode) { ++ if (ci->m_de == de) { + if (atomic_inc_not_zero(&ci->m_count)) + ret_ci = ci; + break; +@@ -84,26 +84,16 @@ static struct ksmbd_inode *__ksmbd_inode_lookup(struct inode *inode) + + static struct ksmbd_inode *ksmbd_inode_lookup(struct ksmbd_file *fp) + { +- return __ksmbd_inode_lookup(file_inode(fp->filp)); ++ return __ksmbd_inode_lookup(fp->filp->f_path.dentry); + } + +-static struct ksmbd_inode *ksmbd_inode_lookup_by_vfsinode(struct inode *inode) +-{ +- struct ksmbd_inode *ci; +- +- read_lock(&inode_hash_lock); +- ci = __ksmbd_inode_lookup(inode); +- read_unlock(&inode_hash_lock); +- return ci; +-} +- +-int ksmbd_query_inode_status(struct inode *inode) ++int ksmbd_query_inode_status(struct dentry *dentry) + { + struct ksmbd_inode *ci; + int ret = KSMBD_INODE_STATUS_UNKNOWN; + + read_lock(&inode_hash_lock); +- ci = __ksmbd_inode_lookup(inode); ++ ci = __ksmbd_inode_lookup(dentry); + if (ci) { + ret = KSMBD_INODE_STATUS_OK; + if (ci->m_flags & (S_DEL_PENDING | S_DEL_ON_CLS)) +@@ -143,7 +133,7 @@ void ksmbd_fd_set_delete_on_close(struct ksmbd_file *fp, + static void ksmbd_inode_hash(struct ksmbd_inode *ci) + { + struct hlist_head *b = inode_hashtable + +- inode_hash(ci->m_inode->i_sb, ci->m_inode->i_ino); ++ inode_hash(d_inode(ci->m_de)->i_sb, (unsigned long)ci->m_de); + + hlist_add_head(&ci->m_hash, b); + } +@@ -157,7 +147,6 @@ static void ksmbd_inode_unhash(struct ksmbd_inode *ci) + + static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) + { +- ci->m_inode = file_inode(fp->filp); + atomic_set(&ci->m_count, 1); + atomic_set(&ci->op_count, 0); + atomic_set(&ci->sop_count, 0); +@@ -166,6 +155,7 @@ static int ksmbd_inode_init(struct ksmbd_inode *ci, struct ksmbd_file *fp) + INIT_LIST_HEAD(&ci->m_fp_list); + INIT_LIST_HEAD(&ci->m_op_list); + rwlock_init(&ci->m_lock); ++ ci->m_de = fp->filp->f_path.dentry; + return 0; + } + +@@ -488,12 +478,15 @@ struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid) + return fp; + } + +-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode) ++struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry) + { + struct ksmbd_file *lfp; + struct ksmbd_inode *ci; ++ struct inode *inode = d_inode(dentry); + +- ci = ksmbd_inode_lookup_by_vfsinode(inode); ++ read_lock(&inode_hash_lock); ++ ci = __ksmbd_inode_lookup(dentry); ++ read_unlock(&inode_hash_lock); + if (!ci) + return NULL; + +diff --git a/fs/smb/server/vfs_cache.h b/fs/smb/server/vfs_cache.h +index 03d0bf941216f..8325cf4527c46 100644 +--- a/fs/smb/server/vfs_cache.h ++++ b/fs/smb/server/vfs_cache.h +@@ -51,7 +51,7 @@ struct ksmbd_inode { + atomic_t op_count; + /* opinfo count for streams */ + atomic_t sop_count; +- struct inode *m_inode; ++ struct dentry *m_de; + unsigned int m_flags; + struct hlist_node m_hash; + struct list_head m_fp_list; +@@ -140,7 +140,7 @@ struct ksmbd_file *ksmbd_lookup_fd_slow(struct ksmbd_work *work, u64 id, + void ksmbd_fd_put(struct ksmbd_work *work, struct ksmbd_file *fp); + struct ksmbd_file *ksmbd_lookup_durable_fd(unsigned long long id); + struct ksmbd_file *ksmbd_lookup_fd_cguid(char *cguid); +-struct ksmbd_file *ksmbd_lookup_fd_inode(struct inode *inode); ++struct ksmbd_file *ksmbd_lookup_fd_inode(struct dentry *dentry); + unsigned int ksmbd_open_durable_fd(struct ksmbd_file *fp); + struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp); + void ksmbd_close_tree_conn_fds(struct ksmbd_work *work); +@@ -164,7 +164,7 @@ enum KSMBD_INODE_STATUS { + KSMBD_INODE_STATUS_PENDING_DELETE, + }; + +-int ksmbd_query_inode_status(struct inode *inode); ++int ksmbd_query_inode_status(struct dentry *dentry); + bool ksmbd_inode_pending_delete(struct ksmbd_file *fp); + void ksmbd_set_inode_pending_delete(struct ksmbd_file *fp); + void ksmbd_clear_inode_pending_delete(struct ksmbd_file *fp); +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-set-epoch-in-create-context-v2-lease.patch b/queue-6.6/ksmbd-set-epoch-in-create-context-v2-lease.patch new file mode 100644 index 00000000000..1bffca974ca --- /dev/null +++ b/queue-6.6/ksmbd-set-epoch-in-create-context-v2-lease.patch @@ -0,0 +1,72 @@ +From f95b24e87a8aafa1b5956fa94ac851d495eae69f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:14 +0900 +Subject: ksmbd: set epoch in create context v2 lease + +From: Namjae Jeon + +[ Upstream commit d045850b628aaf931fc776c90feaf824dca5a1cf ] + +To support v2 lease(directory lease), ksmbd set epoch in create context +v2 lease response. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 5 ++++- + fs/smb/server/oplock.h | 1 + + 2 files changed, 5 insertions(+), 1 deletion(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index 50c68beb71d6c..ff5c83b1fb85c 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -104,7 +104,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx) + lease->duration = lctx->duration; + memcpy(lease->parent_lease_key, lctx->parent_lease_key, SMB2_LEASE_KEY_SIZE); + lease->version = lctx->version; +- lease->epoch = 0; ++ lease->epoch = le16_to_cpu(lctx->epoch); + INIT_LIST_HEAD(&opinfo->lease_entry); + opinfo->o_lease = lease; + +@@ -1032,6 +1032,7 @@ static void copy_lease(struct oplock_info *op1, struct oplock_info *op2) + SMB2_LEASE_KEY_SIZE); + lease2->duration = lease1->duration; + lease2->flags = lease1->flags; ++ lease2->epoch = lease1->epoch++; + } + + static int add_lease_global_list(struct oplock_info *opinfo) +@@ -1364,6 +1365,7 @@ void create_lease_buf(u8 *rbuf, struct lease *lease) + memcpy(buf->lcontext.LeaseKey, lease->lease_key, + SMB2_LEASE_KEY_SIZE); + buf->lcontext.LeaseFlags = lease->flags; ++ buf->lcontext.Epoch = cpu_to_le16(++lease->epoch); + buf->lcontext.LeaseState = lease->state; + memcpy(buf->lcontext.ParentLeaseKey, lease->parent_lease_key, + SMB2_LEASE_KEY_SIZE); +@@ -1423,6 +1425,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req) + memcpy(lreq->lease_key, lc->lcontext.LeaseKey, SMB2_LEASE_KEY_SIZE); + lreq->req_state = lc->lcontext.LeaseState; + lreq->flags = lc->lcontext.LeaseFlags; ++ lreq->epoch = lc->lcontext.Epoch; + lreq->duration = lc->lcontext.LeaseDuration; + memcpy(lreq->parent_lease_key, lc->lcontext.ParentLeaseKey, + SMB2_LEASE_KEY_SIZE); +diff --git a/fs/smb/server/oplock.h b/fs/smb/server/oplock.h +index 4b0fe6da76940..ad31439c61fef 100644 +--- a/fs/smb/server/oplock.h ++++ b/fs/smb/server/oplock.h +@@ -34,6 +34,7 @@ struct lease_ctx_info { + __le32 flags; + __le64 duration; + __u8 parent_lease_key[SMB2_LEASE_KEY_SIZE]; ++ __le16 epoch; + int version; + }; + +-- +2.43.0 + diff --git a/queue-6.6/ksmbd-set-v2-lease-capability.patch b/queue-6.6/ksmbd-set-v2-lease-capability.patch new file mode 100644 index 00000000000..f91fc3173c5 --- /dev/null +++ b/queue-6.6/ksmbd-set-v2-lease-capability.patch @@ -0,0 +1,72 @@ +From 411d996a9f134b8df9dc5d925cd19343bb044c81 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 31 Dec 2023 16:19:15 +0900 +Subject: ksmbd: set v2 lease capability + +From: Namjae Jeon + +[ Upstream commit 18dd1c367c31d0a060f737d48345747662369b64 ] + +Set SMB2_GLOBAL_CAP_DIRECTORY_LEASING to ->capabilities to inform server +support directory lease to client. + +Signed-off-by: Namjae Jeon +Signed-off-by: Steve French +Signed-off-by: Sasha Levin +--- + fs/smb/server/oplock.c | 4 ---- + fs/smb/server/smb2ops.c | 9 ++++++--- + 2 files changed, 6 insertions(+), 7 deletions(-) + +diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c +index ff5c83b1fb85c..5ef6af68d0de6 100644 +--- a/fs/smb/server/oplock.c ++++ b/fs/smb/server/oplock.c +@@ -1105,10 +1105,6 @@ int smb_grant_oplock(struct ksmbd_work *work, int req_op_level, u64 pid, + bool prev_op_has_lease; + __le32 prev_op_state = 0; + +- /* not support directory lease */ +- if (S_ISDIR(file_inode(fp->filp)->i_mode)) +- return 0; +- + opinfo = alloc_opinfo(work, pid, tid); + if (!opinfo) + return -ENOMEM; +diff --git a/fs/smb/server/smb2ops.c b/fs/smb/server/smb2ops.c +index aed7704a06728..27a9dce3e03ab 100644 +--- a/fs/smb/server/smb2ops.c ++++ b/fs/smb/server/smb2ops.c +@@ -221,7 +221,8 @@ void init_smb3_0_server(struct ksmbd_conn *conn) + conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; ++ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | ++ SMB2_GLOBAL_CAP_DIRECTORY_LEASING; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION && + conn->cli_cap & SMB2_GLOBAL_CAP_ENCRYPTION) +@@ -245,7 +246,8 @@ void init_smb3_02_server(struct ksmbd_conn *conn) + conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; ++ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | ++ SMB2_GLOBAL_CAP_DIRECTORY_LEASING; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || + (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && +@@ -270,7 +272,8 @@ int init_smb3_11_server(struct ksmbd_conn *conn) + conn->signing_algorithm = SIGNING_ALG_AES_CMAC_LE; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_LEASES) +- conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING; ++ conn->vals->capabilities |= SMB2_GLOBAL_CAP_LEASING | ++ SMB2_GLOBAL_CAP_DIRECTORY_LEASING; + + if (server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION || + (!(server_conf.flags & KSMBD_GLOBAL_FLAG_SMB2_ENCRYPTION_OFF) && +-- +2.43.0 + diff --git a/queue-6.6/linux-export-ensure-natural-alignment-of-kcrctab-arr.patch b/queue-6.6/linux-export-ensure-natural-alignment-of-kcrctab-arr.patch new file mode 100644 index 00000000000..47945b13741 --- /dev/null +++ b/queue-6.6/linux-export-ensure-natural-alignment-of-kcrctab-arr.patch @@ -0,0 +1,35 @@ +From 42baf792ef97846cb809cdba0d5bd374d850815f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 28 Dec 2023 11:36:03 +0100 +Subject: linux/export: Ensure natural alignment of kcrctab array + +From: Helge Deller + +[ Upstream commit 753547de0daecbdbd1af3618987ddade325d9aaa ] + +The ___kcrctab section holds an array of 32-bit CRC values. +Add a .balign 4 to tell the linker the correct memory alignment. + +Fixes: f3304ecd7f06 ("linux/export: use inline assembler to populate symbol CRCs") +Signed-off-by: Helge Deller +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + include/linux/export-internal.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/include/linux/export-internal.h b/include/linux/export-internal.h +index b842aeecef791..5280194777340 100644 +--- a/include/linux/export-internal.h ++++ b/include/linux/export-internal.h +@@ -66,6 +66,7 @@ + + #define SYMBOL_CRC(sym, crc, sec) \ + asm(".section \"___kcrctab" sec "+" #sym "\",\"a\"" "\n" \ ++ ".balign 4" "\n" \ + "__crc_" #sym ":" "\n" \ + ".long " #crc "\n" \ + ".previous" "\n") +-- +2.43.0 + diff --git a/queue-6.6/linux-export-fix-alignment-for-64-bit-ksymtab-entrie.patch b/queue-6.6/linux-export-fix-alignment-for-64-bit-ksymtab-entrie.patch new file mode 100644 index 00000000000..64bc4f503b9 --- /dev/null +++ b/queue-6.6/linux-export-fix-alignment-for-64-bit-ksymtab-entrie.patch @@ -0,0 +1,51 @@ +From 616d3a9f442244f63e12fd5a992261153b46a38f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 22 Nov 2023 23:18:11 +0100 +Subject: linux/export: Fix alignment for 64-bit ksymtab entries + +From: Helge Deller + +[ Upstream commit f6847807c22f6944c71c981b630b9fff30801e73 ] + +An alignment of 4 bytes is wrong for 64-bit platforms which don't define +CONFIG_HAVE_ARCH_PREL32_RELOCATIONS (which then store 64-bit pointers). +Fix their alignment to 8 bytes. + +Fixes: ddb5cdbafaaa ("kbuild: generate KSYMTAB entries by modpost") +Signed-off-by: Helge Deller +Signed-off-by: Masahiro Yamada +Signed-off-by: Sasha Levin +--- + include/linux/export-internal.h | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/include/linux/export-internal.h b/include/linux/export-internal.h +index 45fca09b23194..b842aeecef791 100644 +--- a/include/linux/export-internal.h ++++ b/include/linux/export-internal.h +@@ -16,10 +16,13 @@ + * and eliminates the need for absolute relocations that require runtime + * processing on relocatable kernels. + */ ++#define __KSYM_ALIGN ".balign 4" + #define __KSYM_REF(sym) ".long " #sym "- ." + #elif defined(CONFIG_64BIT) ++#define __KSYM_ALIGN ".balign 8" + #define __KSYM_REF(sym) ".quad " #sym + #else ++#define __KSYM_ALIGN ".balign 4" + #define __KSYM_REF(sym) ".long " #sym + #endif + +@@ -42,7 +45,7 @@ + " .asciz \"" ns "\"" "\n" \ + " .previous" "\n" \ + " .section \"___ksymtab" sec "+" #name "\", \"a\"" "\n" \ +- " .balign 4" "\n" \ ++ __KSYM_ALIGN "\n" \ + "__ksymtab_" #name ":" "\n" \ + __KSYM_REF(sym) "\n" \ + __KSYM_REF(__kstrtab_ ##name) "\n" \ +-- +2.43.0 + diff --git a/queue-6.6/mptcp-fix-inconsistent-state-on-fastopen-race.patch b/queue-6.6/mptcp-fix-inconsistent-state-on-fastopen-race.patch new file mode 100644 index 00000000000..2f6d6ca0daf --- /dev/null +++ b/queue-6.6/mptcp-fix-inconsistent-state-on-fastopen-race.patch @@ -0,0 +1,237 @@ +From 2b1d92ea197fb279ca67e48645295e9aa1c51a7c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 15 Dec 2023 17:04:25 +0100 +Subject: mptcp: fix inconsistent state on fastopen race + +From: Paolo Abeni + +[ Upstream commit 4fd19a30701659af5839b7bd19d1f05f05933ebe ] + +The netlink PM can race with fastopen self-connect attempts, shutting +down the first subflow via: + +MPTCP_PM_CMD_DEL_ADDR -> mptcp_nl_remove_id_zero_address -> + mptcp_pm_nl_rm_subflow_received -> mptcp_close_ssk + +and transitioning such subflow to FIN_WAIT1 status before the syn-ack +packet is processed. The MPTCP code does not react to such state change, +leaving the connection in not-fallback status and the subflow handshake +uncompleted, triggering the following splat: + + WARNING: CPU: 0 PID: 10630 at net/mptcp/subflow.c:1405 subflow_data_ready+0x39f/0x690 net/mptcp/subflow.c:1405 + Modules linked in: + CPU: 0 PID: 10630 Comm: kworker/u4:11 Not tainted 6.6.0-syzkaller-14500-g1c41041124bd #0 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/09/2023 + Workqueue: bat_events batadv_nc_worker + RIP: 0010:subflow_data_ready+0x39f/0x690 net/mptcp/subflow.c:1405 + Code: 18 89 ee e8 e3 d2 21 f7 40 84 ed 75 1f e8 a9 d7 21 f7 44 89 fe bf 07 00 00 00 e8 0c d3 21 f7 41 83 ff 07 74 07 e8 91 d7 21 f7 <0f> 0b e8 8a d7 21 f7 48 89 df e8 d2 b2 ff ff 31 ff 89 c5 89 c6 e8 + RSP: 0018:ffffc90000007448 EFLAGS: 00010246 + RAX: 0000000000000000 RBX: ffff888031efc700 RCX: ffffffff8a65baf4 + RDX: ffff888043222140 RSI: ffffffff8a65baff RDI: 0000000000000005 + RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000007 + R10: 000000000000000b R11: 0000000000000000 R12: 1ffff92000000e89 + R13: ffff88807a534d80 R14: ffff888021c11a00 R15: 000000000000000b + FS: 0000000000000000(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fa19a0ffc81 CR3: 000000007a2db000 CR4: 00000000003506f0 + DR0: 000000000000d8dd DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400 + Call Trace: + + tcp_data_ready+0x14c/0x5b0 net/ipv4/tcp_input.c:5128 + tcp_data_queue+0x19c3/0x5190 net/ipv4/tcp_input.c:5208 + tcp_rcv_state_process+0x11ef/0x4e10 net/ipv4/tcp_input.c:6844 + tcp_v4_do_rcv+0x369/0xa10 net/ipv4/tcp_ipv4.c:1929 + tcp_v4_rcv+0x3888/0x3b30 net/ipv4/tcp_ipv4.c:2329 + ip_protocol_deliver_rcu+0x9f/0x480 net/ipv4/ip_input.c:205 + ip_local_deliver_finish+0x2e4/0x510 net/ipv4/ip_input.c:233 + NF_HOOK include/linux/netfilter.h:314 [inline] + NF_HOOK include/linux/netfilter.h:308 [inline] + ip_local_deliver+0x1b6/0x550 net/ipv4/ip_input.c:254 + dst_input include/net/dst.h:461 [inline] + ip_rcv_finish+0x1c4/0x2e0 net/ipv4/ip_input.c:449 + NF_HOOK include/linux/netfilter.h:314 [inline] + NF_HOOK include/linux/netfilter.h:308 [inline] + ip_rcv+0xce/0x440 net/ipv4/ip_input.c:569 + __netif_receive_skb_one_core+0x115/0x180 net/core/dev.c:5527 + __netif_receive_skb+0x1f/0x1b0 net/core/dev.c:5641 + process_backlog+0x101/0x6b0 net/core/dev.c:5969 + __napi_poll.constprop.0+0xb4/0x540 net/core/dev.c:6531 + napi_poll net/core/dev.c:6600 [inline] + net_rx_action+0x956/0xe90 net/core/dev.c:6733 + __do_softirq+0x21a/0x968 kernel/softirq.c:553 + do_softirq kernel/softirq.c:454 [inline] + do_softirq+0xaa/0xe0 kernel/softirq.c:441 + + + __local_bh_enable_ip+0xf8/0x120 kernel/softirq.c:381 + spin_unlock_bh include/linux/spinlock.h:396 [inline] + batadv_nc_purge_paths+0x1ce/0x3c0 net/batman-adv/network-coding.c:471 + batadv_nc_worker+0x9b1/0x10e0 net/batman-adv/network-coding.c:722 + process_one_work+0x884/0x15c0 kernel/workqueue.c:2630 + process_scheduled_works kernel/workqueue.c:2703 [inline] + worker_thread+0x8b9/0x1290 kernel/workqueue.c:2784 + kthread+0x33c/0x440 kernel/kthread.c:388 + ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:147 + ret_from_fork_asm+0x11/0x20 arch/x86/entry/entry_64.S:242 + + +To address the issue, catch the racing subflow state change and +use it to cause the MPTCP fallback. Such fallback is also used to +cause the first subflow state propagation to the msk socket via +mptcp_set_connected(). After this change, the first subflow can +additionally propagate the TCP_FIN_WAIT1 state, so rename the +helper accordingly. + +Finally, if the state propagation is delayed to the msk release +callback, the first subflow can change to a different state in between. +Cache the relevant target state in a new msk-level field and use +such value to update the msk state at release time. + +Fixes: 1e777f39b4d7 ("mptcp: add MSG_FASTOPEN sendmsg flag support") +Cc: stable@vger.kernel.org +Reported-by: +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/458 +Signed-off-by: Paolo Abeni +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 6 +++--- + net/mptcp/protocol.h | 9 ++++++--- + net/mptcp/subflow.c | 28 +++++++++++++++++----------- + 3 files changed, 26 insertions(+), 17 deletions(-) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index dc030551cac13..5c003a0f0fe5b 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3397,12 +3397,12 @@ static void mptcp_release_cb(struct sock *sk) + if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) + __mptcp_clean_una_wakeup(sk); + if (unlikely(msk->cb_flags)) { +- /* be sure to set the current sk state before taking actions ++ /* be sure to sync the msk state before taking actions + * depending on sk_state (MPTCP_ERROR_REPORT) + * On sk release avoid actions depending on the first subflow + */ +- if (__test_and_clear_bit(MPTCP_CONNECTED, &msk->cb_flags) && msk->first) +- __mptcp_set_connected(sk); ++ if (__test_and_clear_bit(MPTCP_SYNC_STATE, &msk->cb_flags) && msk->first) ++ __mptcp_sync_state(sk, msk->pending_state); + if (__test_and_clear_bit(MPTCP_ERROR_REPORT, &msk->cb_flags)) + __mptcp_error_report(sk); + if (__test_and_clear_bit(MPTCP_SYNC_SNDBUF, &msk->cb_flags)) +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 40866acd91ad5..07c5ac37d092b 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -122,7 +122,7 @@ + #define MPTCP_ERROR_REPORT 3 + #define MPTCP_RETRANSMIT 4 + #define MPTCP_FLUSH_JOIN_LIST 5 +-#define MPTCP_CONNECTED 6 ++#define MPTCP_SYNC_STATE 6 + #define MPTCP_SYNC_SNDBUF 7 + + struct mptcp_skb_cb { +@@ -293,6 +293,9 @@ struct mptcp_sock { + bool use_64bit_ack; /* Set when we received a 64-bit DSN */ + bool csum_enabled; + bool allow_infinite_fallback; ++ u8 pending_state; /* A subflow asked to set this sk_state, ++ * protected by the msk data lock ++ */ + u8 mpc_endpoint_id; + u8 recvmsg_inq:1, + cork:1, +@@ -711,7 +714,7 @@ void mptcp_get_options(const struct sk_buff *skb, + struct mptcp_options_received *mp_opt); + + void mptcp_finish_connect(struct sock *sk); +-void __mptcp_set_connected(struct sock *sk); ++void __mptcp_sync_state(struct sock *sk, int state); + void mptcp_reset_tout_timer(struct mptcp_sock *msk, unsigned long fail_tout); + + static inline void mptcp_stop_tout_timer(struct sock *sk) +@@ -1101,7 +1104,7 @@ static inline bool subflow_simultaneous_connect(struct sock *sk) + { + struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(sk); + +- return sk->sk_state == TCP_ESTABLISHED && ++ return (1 << sk->sk_state) & (TCPF_ESTABLISHED | TCPF_FIN_WAIT1) && + is_active_ssk(subflow) && + !subflow->conn_finished; + } +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index d8827427ffc84..f3a1e4aa0e5eb 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -419,22 +419,28 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc + return inet_sk(sk)->inet_dport != inet_sk((struct sock *)msk)->inet_dport; + } + +-void __mptcp_set_connected(struct sock *sk) ++void __mptcp_sync_state(struct sock *sk, int state) + { +- __mptcp_propagate_sndbuf(sk, mptcp_sk(sk)->first); ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ ++ __mptcp_propagate_sndbuf(sk, msk->first); + if (sk->sk_state == TCP_SYN_SENT) { +- inet_sk_state_store(sk, TCP_ESTABLISHED); ++ inet_sk_state_store(sk, state); + sk->sk_state_change(sk); + } + } + +-static void mptcp_set_connected(struct sock *sk) ++static void mptcp_propagate_state(struct sock *sk, struct sock *ssk) + { ++ struct mptcp_sock *msk = mptcp_sk(sk); ++ + mptcp_data_lock(sk); +- if (!sock_owned_by_user(sk)) +- __mptcp_set_connected(sk); +- else +- __set_bit(MPTCP_CONNECTED, &mptcp_sk(sk)->cb_flags); ++ if (!sock_owned_by_user(sk)) { ++ __mptcp_sync_state(sk, ssk->sk_state); ++ } else { ++ msk->pending_state = ssk->sk_state; ++ __set_bit(MPTCP_SYNC_STATE, &msk->cb_flags); ++ } + mptcp_data_unlock(sk); + } + +@@ -496,7 +502,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + subflow_set_remote_key(msk, subflow, &mp_opt); + MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_MPCAPABLEACTIVEACK); + mptcp_finish_connect(sk); +- mptcp_set_connected(parent); ++ mptcp_propagate_state(parent, sk); + } else if (subflow->request_join) { + u8 hmac[SHA256_DIGEST_SIZE]; + +@@ -540,7 +546,7 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + } else if (mptcp_check_fallback(sk)) { + fallback: + mptcp_rcv_space_init(msk, sk); +- mptcp_set_connected(parent); ++ mptcp_propagate_state(parent, sk); + } + return; + +@@ -1732,7 +1738,7 @@ static void subflow_state_change(struct sock *sk) + mptcp_rcv_space_init(msk, sk); + pr_fallback(msk); + subflow->conn_finished = 1; +- mptcp_set_connected(parent); ++ mptcp_propagate_state(parent, sk); + } + + /* as recvmsg() does not acquire the subflow socket for ssk selection +-- +2.43.0 + diff --git a/queue-6.6/mptcp-fix-possible-null-pointer-dereference-on-close.patch b/queue-6.6/mptcp-fix-possible-null-pointer-dereference-on-close.patch new file mode 100644 index 00000000000..27a2dc7a598 --- /dev/null +++ b/queue-6.6/mptcp-fix-possible-null-pointer-dereference-on-close.patch @@ -0,0 +1,110 @@ +From 4af5540db7fecce388dcf27be65e4d510fc7aafb Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Nov 2023 00:16:14 +0100 +Subject: mptcp: fix possible NULL pointer dereference on close + +From: Paolo Abeni + +[ Upstream commit d109a7767273d1706b541c22b83a0323823dfde4 ] + +After the blamed commit below, the MPTCP release callback can +dereference the first subflow pointer via __mptcp_set_connected() +and send buffer auto-tuning. Such pointer is always expected to be +valid, except at socket destruction time, when the first subflow is +deleted and the pointer zeroed. + +If the connect event is handled by the release callback while the +msk socket is finally released, MPTCP hits the following splat: + + general protection fault, probably for non-canonical address 0xdffffc00000000f2: 0000 [#1] PREEMPT SMP KASAN + KASAN: null-ptr-deref in range [0x0000000000000790-0x0000000000000797] + CPU: 1 PID: 26719 Comm: syz-executor.2 Not tainted 6.6.0-syzkaller-10102-gff269e2cd5ad #0 + Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/09/2023 + RIP: 0010:mptcp_subflow_ctx net/mptcp/protocol.h:542 [inline] + RIP: 0010:__mptcp_propagate_sndbuf net/mptcp/protocol.h:813 [inline] + RIP: 0010:__mptcp_set_connected+0x57/0x3e0 net/mptcp/subflow.c:424 + RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff8a62323c + RDX: 00000000000000f2 RSI: ffffffff8a630116 RDI: 0000000000000790 + RBP: ffff88803334b100 R08: 0000000000000001 R09: 0000000000000000 + R10: 0000000000000001 R11: 0000000000000034 R12: ffff88803334b198 + R13: ffff888054f0b018 R14: 0000000000000000 R15: ffff88803334b100 + FS: 0000000000000000(0000) GS:ffff8880b9900000(0000) knlGS:0000000000000000 + CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 + CR2: 00007fbcb4f75198 CR3: 000000006afb5000 CR4: 00000000003506f0 + DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 + DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 + Call Trace: + + mptcp_release_cb+0xa2c/0xc40 net/mptcp/protocol.c:3405 + release_sock+0xba/0x1f0 net/core/sock.c:3537 + mptcp_close+0x32/0xf0 net/mptcp/protocol.c:3084 + inet_release+0x132/0x270 net/ipv4/af_inet.c:433 + inet6_release+0x4f/0x70 net/ipv6/af_inet6.c:485 + __sock_release+0xae/0x260 net/socket.c:659 + sock_close+0x1c/0x20 net/socket.c:1419 + __fput+0x270/0xbb0 fs/file_table.c:394 + task_work_run+0x14d/0x240 kernel/task_work.c:180 + exit_task_work include/linux/task_work.h:38 [inline] + do_exit+0xa92/0x2a20 kernel/exit.c:876 + do_group_exit+0xd4/0x2a0 kernel/exit.c:1026 + get_signal+0x23ba/0x2790 kernel/signal.c:2900 + arch_do_signal_or_restart+0x90/0x7f0 arch/x86/kernel/signal.c:309 + exit_to_user_mode_loop kernel/entry/common.c:168 [inline] + exit_to_user_mode_prepare+0x11f/0x240 kernel/entry/common.c:204 + __syscall_exit_to_user_mode_work kernel/entry/common.c:285 [inline] + syscall_exit_to_user_mode+0x1d/0x60 kernel/entry/common.c:296 + do_syscall_64+0x4b/0x110 arch/x86/entry/common.c:88 + entry_SYSCALL_64_after_hwframe+0x63/0x6b + RIP: 0033:0x7fb515e7cae9 + Code: Unable to access opcode bytes at 0x7fb515e7cabf. + RSP: 002b:00007fb516c560c8 EFLAGS: 00000246 ORIG_RAX: 000000000000002e + RAX: 000000000000003c RBX: 00007fb515f9c120 RCX: 00007fb515e7cae9 + RDX: 0000000000000000 RSI: 0000000020000140 RDI: 0000000000000006 + RBP: 00007fb515ec847a R08: 0000000000000000 R09: 0000000000000000 + R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 + R13: 000000000000006e R14: 00007fb515f9c120 R15: 00007ffc631eb968 + + +To avoid sparkling unneeded conditionals, address the issue explicitly +checking msk->first only in the critical place. + +Fixes: 8005184fd1ca ("mptcp: refactor sndbuf auto-tuning") +Cc: stable@vger.kernel.org +Reported-by: +Closes: https://github.com/multipath-tcp/mptcp_net-next/issues/454 +Reported-by: Eric Dumazet +Closes: https://lore.kernel.org/netdev/CANn89iLZUA6S2a=K8GObnS62KK6Jt4B7PsAs7meMFooM8xaTgw@mail.gmail.com/ +Signed-off-by: Paolo Abeni +Reviewed-by: Eric Dumazet +Reviewed-by: Mat Martineau +Signed-off-by: Matthieu Baerts +Link: https://lore.kernel.org/r/20231114-upstream-net-20231113-mptcp-misc-fixes-6-7-rc2-v1-2-7b9cd6a7b7f4@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4fd19a307016 ("mptcp: fix inconsistent state on fastopen race") +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index 44499e49d76e6..dc030551cac13 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -3397,10 +3397,11 @@ static void mptcp_release_cb(struct sock *sk) + if (__test_and_clear_bit(MPTCP_CLEAN_UNA, &msk->cb_flags)) + __mptcp_clean_una_wakeup(sk); + if (unlikely(msk->cb_flags)) { +- /* be sure to set the current sk state before tacking actions +- * depending on sk_state, that is processing MPTCP_ERROR_REPORT ++ /* be sure to set the current sk state before taking actions ++ * depending on sk_state (MPTCP_ERROR_REPORT) ++ * On sk release avoid actions depending on the first subflow + */ +- if (__test_and_clear_bit(MPTCP_CONNECTED, &msk->cb_flags)) ++ if (__test_and_clear_bit(MPTCP_CONNECTED, &msk->cb_flags) && msk->first) + __mptcp_set_connected(sk); + if (__test_and_clear_bit(MPTCP_ERROR_REPORT, &msk->cb_flags)) + __mptcp_error_report(sk); +-- +2.43.0 + diff --git a/queue-6.6/mptcp-refactor-sndbuf-auto-tuning.patch b/queue-6.6/mptcp-refactor-sndbuf-auto-tuning.patch new file mode 100644 index 00000000000..18cd632315d --- /dev/null +++ b/queue-6.6/mptcp-refactor-sndbuf-auto-tuning.patch @@ -0,0 +1,257 @@ +From ce42391e5377ff68cfc85036666147da9f2521ae Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 23 Oct 2023 13:44:42 -0700 +Subject: mptcp: refactor sndbuf auto-tuning + +From: Paolo Abeni + +[ Upstream commit 8005184fd1ca6aeb3fea36f4eb9463fc1b90c114 ] + +The MPTCP protocol account for the data enqueued on all the subflows +to the main socket send buffer, while the send buffer auto-tuning +algorithm set the main socket send buffer size as the max size among +the subflows. + +That causes bad performances when at least one subflow is sndbuf +limited, e.g. due to very high latency, as the MPTCP scheduler can't +even fill such buffer. + +Change the send-buffer auto-tuning algorithm to compute the main socket +send buffer size as the sum of all the subflows buffer size. + +Reviewed-by: Mat Martineau +Signed-off-by: Paolo Abeni +Signed-off-by: Mat Martineau +Link: https://lore.kernel.org/r/20231023-send-net-next-20231023-2-v1-9-9dc60939d371@kernel.org +Signed-off-by: Jakub Kicinski +Stable-dep-of: 4fd19a307016 ("mptcp: fix inconsistent state on fastopen race") +Signed-off-by: Sasha Levin +--- + net/mptcp/protocol.c | 18 +++++++++++++-- + net/mptcp/protocol.h | 54 ++++++++++++++++++++++++++++++++++++++++---- + net/mptcp/sockopt.c | 5 +++- + net/mptcp/subflow.c | 3 +-- + 4 files changed, 70 insertions(+), 10 deletions(-) + +diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c +index c1527f520dce3..44499e49d76e6 100644 +--- a/net/mptcp/protocol.c ++++ b/net/mptcp/protocol.c +@@ -893,6 +893,7 @@ static bool __mptcp_finish_join(struct mptcp_sock *msk, struct sock *ssk) + mptcp_sockopt_sync_locked(msk, ssk); + mptcp_subflow_joined(msk, ssk); + mptcp_stop_tout_timer(sk); ++ __mptcp_propagate_sndbuf(sk, ssk); + return true; + } + +@@ -1079,15 +1080,16 @@ static void mptcp_enter_memory_pressure(struct sock *sk) + struct mptcp_sock *msk = mptcp_sk(sk); + bool first = true; + +- sk_stream_moderate_sndbuf(sk); + mptcp_for_each_subflow(msk, subflow) { + struct sock *ssk = mptcp_subflow_tcp_sock(subflow); + + if (first) + tcp_enter_memory_pressure(ssk); + sk_stream_moderate_sndbuf(ssk); ++ + first = false; + } ++ __mptcp_sync_sndbuf(sk); + } + + /* ensure we get enough memory for the frag hdr, beyond some minimal amount of +@@ -2452,6 +2454,7 @@ static void __mptcp_close_ssk(struct sock *sk, struct sock *ssk, + WRITE_ONCE(msk->first, NULL); + + out: ++ __mptcp_sync_sndbuf(sk); + if (need_push) + __mptcp_push_pending(sk, 0); + +@@ -3223,7 +3226,7 @@ struct sock *mptcp_sk_clone_init(const struct sock *sk, + * uses the correct data + */ + mptcp_copy_inaddrs(nsk, ssk); +- mptcp_propagate_sndbuf(nsk, ssk); ++ __mptcp_propagate_sndbuf(nsk, ssk); + + mptcp_rcv_space_init(msk, ssk); + bh_unlock_sock(nsk); +@@ -3401,6 +3404,8 @@ static void mptcp_release_cb(struct sock *sk) + __mptcp_set_connected(sk); + if (__test_and_clear_bit(MPTCP_ERROR_REPORT, &msk->cb_flags)) + __mptcp_error_report(sk); ++ if (__test_and_clear_bit(MPTCP_SYNC_SNDBUF, &msk->cb_flags)) ++ __mptcp_sync_sndbuf(sk); + } + + __mptcp_update_rmem(sk); +@@ -3445,6 +3450,14 @@ void mptcp_subflow_process_delegated(struct sock *ssk, long status) + __set_bit(MPTCP_PUSH_PENDING, &mptcp_sk(sk)->cb_flags); + mptcp_data_unlock(sk); + } ++ if (status & BIT(MPTCP_DELEGATE_SNDBUF)) { ++ mptcp_data_lock(sk); ++ if (!sock_owned_by_user(sk)) ++ __mptcp_sync_sndbuf(sk); ++ else ++ __set_bit(MPTCP_SYNC_SNDBUF, &mptcp_sk(sk)->cb_flags); ++ mptcp_data_unlock(sk); ++ } + if (status & BIT(MPTCP_DELEGATE_ACK)) + schedule_3rdack_retransmission(ssk); + } +@@ -3529,6 +3542,7 @@ bool mptcp_finish_join(struct sock *ssk) + /* active subflow, already present inside the conn_list */ + if (!list_empty(&subflow->node)) { + mptcp_subflow_joined(msk, ssk); ++ mptcp_propagate_sndbuf(parent, ssk); + return true; + } + +diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h +index 3612545fa62e0..40866acd91ad5 100644 +--- a/net/mptcp/protocol.h ++++ b/net/mptcp/protocol.h +@@ -123,6 +123,7 @@ + #define MPTCP_RETRANSMIT 4 + #define MPTCP_FLUSH_JOIN_LIST 5 + #define MPTCP_CONNECTED 6 ++#define MPTCP_SYNC_SNDBUF 7 + + struct mptcp_skb_cb { + u64 map_seq; +@@ -447,6 +448,7 @@ DECLARE_PER_CPU(struct mptcp_delegated_action, mptcp_delegated_actions); + #define MPTCP_DELEGATE_SCHEDULED 0 + #define MPTCP_DELEGATE_SEND 1 + #define MPTCP_DELEGATE_ACK 2 ++#define MPTCP_DELEGATE_SNDBUF 3 + + #define MPTCP_DELEGATE_ACTIONS_MASK (~BIT(MPTCP_DELEGATE_SCHEDULED)) + /* MPTCP subflow context */ +@@ -520,6 +522,9 @@ struct mptcp_subflow_context { + + u32 setsockopt_seq; + u32 stale_rcv_tstamp; ++ int cached_sndbuf; /* sndbuf size when last synced with the msk sndbuf, ++ * protected by the msk socket lock ++ */ + + struct sock *tcp_sock; /* tcp sk backpointer */ + struct sock *conn; /* parent mptcp_sock */ +@@ -762,13 +767,52 @@ static inline bool mptcp_data_fin_enabled(const struct mptcp_sock *msk) + READ_ONCE(msk->write_seq) == READ_ONCE(msk->snd_nxt); + } + +-static inline bool mptcp_propagate_sndbuf(struct sock *sk, struct sock *ssk) ++static inline void __mptcp_sync_sndbuf(struct sock *sk) + { +- if ((sk->sk_userlocks & SOCK_SNDBUF_LOCK) || ssk->sk_sndbuf <= READ_ONCE(sk->sk_sndbuf)) +- return false; ++ struct mptcp_subflow_context *subflow; ++ int ssk_sndbuf, new_sndbuf; ++ ++ if (sk->sk_userlocks & SOCK_SNDBUF_LOCK) ++ return; ++ ++ new_sndbuf = sock_net(sk)->ipv4.sysctl_tcp_wmem[0]; ++ mptcp_for_each_subflow(mptcp_sk(sk), subflow) { ++ ssk_sndbuf = READ_ONCE(mptcp_subflow_tcp_sock(subflow)->sk_sndbuf); ++ ++ subflow->cached_sndbuf = ssk_sndbuf; ++ new_sndbuf += ssk_sndbuf; ++ } ++ ++ /* the msk max wmem limit is * tcp wmem[2] */ ++ WRITE_ONCE(sk->sk_sndbuf, new_sndbuf); ++} ++ ++/* The called held both the msk socket and the subflow socket locks, ++ * possibly under BH ++ */ ++static inline void __mptcp_propagate_sndbuf(struct sock *sk, struct sock *ssk) ++{ ++ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); ++ ++ if (READ_ONCE(ssk->sk_sndbuf) != subflow->cached_sndbuf) ++ __mptcp_sync_sndbuf(sk); ++} ++ ++/* the caller held only the subflow socket lock, either in process or ++ * BH context. Additionally this can be called under the msk data lock, ++ * so we can't acquire such lock here: let the delegate action acquires ++ * the needed locks in suitable order. ++ */ ++static inline void mptcp_propagate_sndbuf(struct sock *sk, struct sock *ssk) ++{ ++ struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk); ++ ++ if (likely(READ_ONCE(ssk->sk_sndbuf) == subflow->cached_sndbuf)) ++ return; + +- WRITE_ONCE(sk->sk_sndbuf, ssk->sk_sndbuf); +- return true; ++ local_bh_disable(); ++ mptcp_subflow_delegate(subflow, MPTCP_DELEGATE_SNDBUF); ++ local_bh_enable(); + } + + static inline void mptcp_write_space(struct sock *sk) +diff --git a/net/mptcp/sockopt.c b/net/mptcp/sockopt.c +index 7539b9c8c2fb4..116e3008231bd 100644 +--- a/net/mptcp/sockopt.c ++++ b/net/mptcp/sockopt.c +@@ -95,6 +95,7 @@ static void mptcp_sol_socket_sync_intval(struct mptcp_sock *msk, int optname, in + case SO_SNDBUFFORCE: + ssk->sk_userlocks |= SOCK_SNDBUF_LOCK; + WRITE_ONCE(ssk->sk_sndbuf, sk->sk_sndbuf); ++ mptcp_subflow_ctx(ssk)->cached_sndbuf = sk->sk_sndbuf; + break; + case SO_RCVBUF: + case SO_RCVBUFFORCE: +@@ -1418,8 +1419,10 @@ static void sync_socket_options(struct mptcp_sock *msk, struct sock *ssk) + + if (sk->sk_userlocks & tx_rx_locks) { + ssk->sk_userlocks |= sk->sk_userlocks & tx_rx_locks; +- if (sk->sk_userlocks & SOCK_SNDBUF_LOCK) ++ if (sk->sk_userlocks & SOCK_SNDBUF_LOCK) { + WRITE_ONCE(ssk->sk_sndbuf, sk->sk_sndbuf); ++ mptcp_subflow_ctx(ssk)->cached_sndbuf = sk->sk_sndbuf; ++ } + if (sk->sk_userlocks & SOCK_RCVBUF_LOCK) + WRITE_ONCE(ssk->sk_rcvbuf, sk->sk_rcvbuf); + } +diff --git a/net/mptcp/subflow.c b/net/mptcp/subflow.c +index 9c1f8d1d63d24..d8827427ffc84 100644 +--- a/net/mptcp/subflow.c ++++ b/net/mptcp/subflow.c +@@ -421,6 +421,7 @@ static bool subflow_use_different_dport(struct mptcp_sock *msk, const struct soc + + void __mptcp_set_connected(struct sock *sk) + { ++ __mptcp_propagate_sndbuf(sk, mptcp_sk(sk)->first); + if (sk->sk_state == TCP_SYN_SENT) { + inet_sk_state_store(sk, TCP_ESTABLISHED); + sk->sk_state_change(sk); +@@ -472,7 +473,6 @@ static void subflow_finish_connect(struct sock *sk, const struct sk_buff *skb) + return; + + msk = mptcp_sk(parent); +- mptcp_propagate_sndbuf(parent, sk); + subflow->rel_write_seq = 1; + subflow->conn_finished = 1; + subflow->ssn_offset = TCP_SKB_CB(skb)->seq; +@@ -1728,7 +1728,6 @@ static void subflow_state_change(struct sock *sk) + + msk = mptcp_sk(parent); + if (subflow_simultaneous_connect(sk)) { +- mptcp_propagate_sndbuf(parent, sk); + mptcp_do_fallback(sk); + mptcp_rcv_space_init(msk, sk); + pr_fallback(msk); +-- +2.43.0 + diff --git a/queue-6.6/platform-x86-intel-pmc-add-suspend-callback.patch b/queue-6.6/platform-x86-intel-pmc-add-suspend-callback.patch new file mode 100644 index 00000000000..d6ffab88afa --- /dev/null +++ b/queue-6.6/platform-x86-intel-pmc-add-suspend-callback.patch @@ -0,0 +1,67 @@ +From 79b097974109b091a3d1c63d6d0e20f17f9496f0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 19:25:43 -0800 +Subject: platform/x86/intel/pmc: Add suspend callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David E. Box + +[ Upstream commit 7c13f365aee68b01e7e68ee293a71fdc7571c111 ] + +Add a suspend callback to struct pmc for performing platform specific tasks +before device suspend. This is needed in order to perform GBE LTR ignore on +certain platforms at suspend-time instead of at probe-time and replace the +GBE LTR ignore removal that was done in order to fix a bug introduced by +commit 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and +core_configure()"). + +Fixes: 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and core_configure()") +Signed-off-by: "David E. Box" +Link: https://lore.kernel.org/r/20231223032548.1680738-4-david.e.box@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/pmc/core.c | 3 +++ + drivers/platform/x86/intel/pmc/core.h | 2 ++ + 2 files changed, 5 insertions(+) + +diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c +index e95d3011b9997..5ab470d87ad7e 100644 +--- a/drivers/platform/x86/intel/pmc/core.c ++++ b/drivers/platform/x86/intel/pmc/core.c +@@ -1279,6 +1279,9 @@ static __maybe_unused int pmc_core_suspend(struct device *dev) + struct pmc_dev *pmcdev = dev_get_drvdata(dev); + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + ++ if (pmcdev->suspend) ++ pmcdev->suspend(pmcdev); ++ + /* Check if the syspend will actually use S0ix */ + if (pm_suspend_via_firmware()) + return 0; +diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h +index 0729f593c6a75..38d888e3afa63 100644 +--- a/drivers/platform/x86/intel/pmc/core.h ++++ b/drivers/platform/x86/intel/pmc/core.h +@@ -363,6 +363,7 @@ struct pmc { + * @s0ix_counter: S0ix residency (step adjusted) + * @num_lpm_modes: Count of enabled modes + * @lpm_en_modes: Array of enabled modes from lowest to highest priority ++ * @suspend: Function to perform platform specific suspend + * @resume: Function to perform platform specific resume + * + * pmc_dev contains info about power management controller device. +@@ -379,6 +380,7 @@ struct pmc_dev { + u64 s0ix_counter; + int num_lpm_modes; + int lpm_en_modes[LPM_MAX_NUM_MODES]; ++ void (*suspend)(struct pmc_dev *pmcdev); + int (*resume)(struct pmc_dev *pmcdev); + + bool has_die_c6; +-- +2.43.0 + diff --git a/queue-6.6/platform-x86-intel-pmc-allow-reenabling-ltrs.patch b/queue-6.6/platform-x86-intel-pmc-allow-reenabling-ltrs.patch new file mode 100644 index 00000000000..3ec5bde7eca --- /dev/null +++ b/queue-6.6/platform-x86-intel-pmc-allow-reenabling-ltrs.patch @@ -0,0 +1,136 @@ +From 72d419cf0c408c480966ff3cf654403bd9441594 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 19:25:44 -0800 +Subject: platform/x86/intel/pmc: Allow reenabling LTRs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David E. Box + +[ Upstream commit 6f9cc5c1f94daa98846b2073733d03ced709704b ] + +Commit 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and +core_configure()") caused a network performance regression due to the GBE +LTR ignore that it added during probe. The fix will move the ignore to +occur at suspend-time (so as to not affect suspend power). This will +require the ability to enable the LTR again on resume. Modify +pmc_core_send_ltr_ignore() to allow enabling an LTR. + +Fixes: 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and core_configure()") +Signed-off-by: "David E. Box" +Link: https://lore.kernel.org/r/20231223032548.1680738-5-david.e.box@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/pmc/adl.c | 2 +- + drivers/platform/x86/intel/pmc/cnp.c | 2 +- + drivers/platform/x86/intel/pmc/core.c | 9 ++++++--- + drivers/platform/x86/intel/pmc/core.h | 2 +- + drivers/platform/x86/intel/pmc/mtl.c | 2 +- + drivers/platform/x86/intel/pmc/tgl.c | 2 +- + 6 files changed, 11 insertions(+), 8 deletions(-) + +diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c +index 5006008e01bea..a887c388cf16d 100644 +--- a/drivers/platform/x86/intel/pmc/adl.c ++++ b/drivers/platform/x86/intel/pmc/adl.c +@@ -323,7 +323,7 @@ int adl_core_init(struct pmc_dev *pmcdev) + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3); ++ pmc_core_send_ltr_ignore(pmcdev, 3, 1); + + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c +index 420aaa1d7c769..10498204962cd 100644 +--- a/drivers/platform/x86/intel/pmc/cnp.c ++++ b/drivers/platform/x86/intel/pmc/cnp.c +@@ -218,7 +218,7 @@ int cnp_core_init(struct pmc_dev *pmcdev) + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3); ++ pmc_core_send_ltr_ignore(pmcdev, 3, 1); + + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/core.c b/drivers/platform/x86/intel/pmc/core.c +index 5ab470d87ad7e..022afb97d531c 100644 +--- a/drivers/platform/x86/intel/pmc/core.c ++++ b/drivers/platform/x86/intel/pmc/core.c +@@ -460,7 +460,7 @@ static int pmc_core_pll_show(struct seq_file *s, void *unused) + } + DEFINE_SHOW_ATTRIBUTE(pmc_core_pll); + +-int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) ++int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore) + { + struct pmc *pmc; + const struct pmc_reg_map *map; +@@ -498,7 +498,10 @@ int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value) + mutex_lock(&pmcdev->lock); + + reg = pmc_core_reg_read(pmc, map->ltr_ignore_offset); +- reg |= BIT(ltr_index); ++ if (ignore) ++ reg |= BIT(ltr_index); ++ else ++ reg &= ~BIT(ltr_index); + pmc_core_reg_write(pmc, map->ltr_ignore_offset, reg); + + mutex_unlock(&pmcdev->lock); +@@ -521,7 +524,7 @@ static ssize_t pmc_core_ltr_ignore_write(struct file *file, + if (err) + return err; + +- err = pmc_core_send_ltr_ignore(pmcdev, value); ++ err = pmc_core_send_ltr_ignore(pmcdev, value, 1); + + return err == 0 ? count : err; + } +diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h +index 38d888e3afa63..71ba7d691d691 100644 +--- a/drivers/platform/x86/intel/pmc/core.h ++++ b/drivers/platform/x86/intel/pmc/core.h +@@ -488,7 +488,7 @@ extern const struct pmc_bit_map *mtl_ioem_lpm_maps[]; + extern const struct pmc_reg_map mtl_ioem_reg_map; + + extern void pmc_core_get_tgl_lpm_reqs(struct platform_device *pdev); +-extern int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value); ++int pmc_core_send_ltr_ignore(struct pmc_dev *pmcdev, u32 value, int ignore); + + int pmc_core_resume_common(struct pmc_dev *pmcdev); + int get_primary_reg_base(struct pmc *pmc); +diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c +index 2204bc666980e..71dc11811e112 100644 +--- a/drivers/platform/x86/intel/pmc/mtl.c ++++ b/drivers/platform/x86/intel/pmc/mtl.c +@@ -1006,7 +1006,7 @@ int mtl_core_init(struct pmc_dev *pmcdev) + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3); ++ pmc_core_send_ltr_ignore(pmcdev, 3, 1); + + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c +index 2449940102db4..078263db24c7a 100644 +--- a/drivers/platform/x86/intel/pmc/tgl.c ++++ b/drivers/platform/x86/intel/pmc/tgl.c +@@ -268,7 +268,7 @@ int tgl_core_init(struct pmc_dev *pmcdev) + * when a cable is attached. Tell the PMC to ignore it. + */ + dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3); ++ pmc_core_send_ltr_ignore(pmcdev, 3, 1); + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.6/platform-x86-intel-pmc-move-gbe-ltr-ignore-to-suspen.patch b/queue-6.6/platform-x86-intel-pmc-move-gbe-ltr-ignore-to-suspen.patch new file mode 100644 index 00000000000..23b1fc40799 --- /dev/null +++ b/queue-6.6/platform-x86-intel-pmc-move-gbe-ltr-ignore-to-suspen.patch @@ -0,0 +1,180 @@ +From 135d53f78f786a4e22862e1a5c418a96206048e3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 22 Dec 2023 19:25:45 -0800 +Subject: platform/x86/intel/pmc: Move GBE LTR ignore to suspend callback +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David E. Box + +[ Upstream commit 70681aa0746ae61d7668b9f651221fad5e30c71e ] + +Commit 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and +core_configure()") caused a network performance regression due to the GBE +LTR ignore that it added at probe. This was needed in order to allow the +SoC to enter the deepest Package C state. To fix the regression and at +least support PC10 during suspend, move the LTR ignore from probe to the +suspend callback, and enable it again on resume. This solution will allow +PC10 during suspend but restrict Package C entry at runtime to no deeper +than PC8/9 while a network cable it attach to the PCH LAN. + +Fixes: 804951203aa5 ("platform/x86:intel/pmc: Combine core_init() and core_configure()") +Signed-off-by: "David E. Box" +Link: https://lore.kernel.org/r/20231223032548.1680738-6-david.e.box@linux.intel.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/intel/pmc/adl.c | 9 +++------ + drivers/platform/x86/intel/pmc/cnp.c | 26 ++++++++++++++++++++------ + drivers/platform/x86/intel/pmc/core.h | 3 +++ + drivers/platform/x86/intel/pmc/mtl.c | 9 +++------ + drivers/platform/x86/intel/pmc/tgl.c | 9 ++++----- + 5 files changed, 33 insertions(+), 23 deletions(-) + +diff --git a/drivers/platform/x86/intel/pmc/adl.c b/drivers/platform/x86/intel/pmc/adl.c +index a887c388cf16d..606f7678bcb0a 100644 +--- a/drivers/platform/x86/intel/pmc/adl.c ++++ b/drivers/platform/x86/intel/pmc/adl.c +@@ -314,16 +314,13 @@ int adl_core_init(struct pmc_dev *pmcdev) + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + ++ pmcdev->suspend = cnl_suspend; ++ pmcdev->resume = cnl_resume; ++ + pmc->map = &adl_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + +- /* Due to a hardware limitation, the GBE LTR blocks PC10 +- * when a cable is attached. Tell the PMC to ignore it. +- */ +- dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3, 1); +- + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/cnp.c b/drivers/platform/x86/intel/pmc/cnp.c +index 10498204962cd..98b36651201a0 100644 +--- a/drivers/platform/x86/intel/pmc/cnp.c ++++ b/drivers/platform/x86/intel/pmc/cnp.c +@@ -204,21 +204,35 @@ const struct pmc_reg_map cnp_reg_map = { + .etr3_offset = ETR3_OFFSET, + }; + ++void cnl_suspend(struct pmc_dev *pmcdev) ++{ ++ /* ++ * Due to a hardware limitation, the GBE LTR blocks PC10 ++ * when a cable is attached. To unblock PC10 during suspend, ++ * tell the PMC to ignore it. ++ */ ++ pmc_core_send_ltr_ignore(pmcdev, 3, 1); ++} ++ ++int cnl_resume(struct pmc_dev *pmcdev) ++{ ++ pmc_core_send_ltr_ignore(pmcdev, 3, 0); ++ ++ return pmc_core_resume_common(pmcdev); ++} ++ + int cnp_core_init(struct pmc_dev *pmcdev) + { + struct pmc *pmc = pmcdev->pmcs[PMC_IDX_MAIN]; + int ret; + ++ pmcdev->suspend = cnl_suspend; ++ pmcdev->resume = cnl_resume; ++ + pmc->map = &cnp_reg_map; + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + +- /* Due to a hardware limitation, the GBE LTR blocks PC10 +- * when a cable is attached. Tell the PMC to ignore it. +- */ +- dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3, 1); +- + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/core.h b/drivers/platform/x86/intel/pmc/core.h +index 71ba7d691d691..b66dacbfb94bf 100644 +--- a/drivers/platform/x86/intel/pmc/core.h ++++ b/drivers/platform/x86/intel/pmc/core.h +@@ -502,6 +502,9 @@ int tgl_core_init(struct pmc_dev *pmcdev); + int adl_core_init(struct pmc_dev *pmcdev); + int mtl_core_init(struct pmc_dev *pmcdev); + ++void cnl_suspend(struct pmc_dev *pmcdev); ++int cnl_resume(struct pmc_dev *pmcdev); ++ + #define pmc_for_each_mode(i, mode, pmcdev) \ + for (i = 0, mode = pmcdev->lpm_en_modes[i]; \ + i < pmcdev->num_lpm_modes; \ +diff --git a/drivers/platform/x86/intel/pmc/mtl.c b/drivers/platform/x86/intel/pmc/mtl.c +index 71dc11811e112..504e3e273c323 100644 +--- a/drivers/platform/x86/intel/pmc/mtl.c ++++ b/drivers/platform/x86/intel/pmc/mtl.c +@@ -979,6 +979,8 @@ static void mtl_d3_fixup(void) + static int mtl_resume(struct pmc_dev *pmcdev) + { + mtl_d3_fixup(); ++ pmc_core_send_ltr_ignore(pmcdev, 3, 0); ++ + return pmc_core_resume_common(pmcdev); + } + +@@ -989,6 +991,7 @@ int mtl_core_init(struct pmc_dev *pmcdev) + + mtl_d3_fixup(); + ++ pmcdev->suspend = cnl_suspend; + pmcdev->resume = mtl_resume; + + pmcdev->regmap_list = mtl_pmc_info_list; +@@ -1002,11 +1005,5 @@ int mtl_core_init(struct pmc_dev *pmcdev) + return ret; + } + +- /* Due to a hardware limitation, the GBE LTR blocks PC10 +- * when a cable is attached. Tell the PMC to ignore it. +- */ +- dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3, 1); +- + return 0; + } +diff --git a/drivers/platform/x86/intel/pmc/tgl.c b/drivers/platform/x86/intel/pmc/tgl.c +index 078263db24c7a..e88d3d00c8539 100644 +--- a/drivers/platform/x86/intel/pmc/tgl.c ++++ b/drivers/platform/x86/intel/pmc/tgl.c +@@ -259,16 +259,15 @@ int tgl_core_init(struct pmc_dev *pmcdev) + int ret; + + pmc->map = &tgl_reg_map; ++ ++ pmcdev->suspend = cnl_suspend; ++ pmcdev->resume = cnl_resume; ++ + ret = get_primary_reg_base(pmc); + if (ret) + return ret; + + pmc_core_get_tgl_lpm_reqs(pmcdev->pdev); +- /* Due to a hardware limitation, the GBE LTR blocks PC10 +- * when a cable is attached. Tell the PMC to ignore it. +- */ +- dev_dbg(&pmcdev->pdev->dev, "ignoring GBE LTR\n"); +- pmc_core_send_ltr_ignore(pmcdev, 3, 1); + + return 0; + } +-- +2.43.0 + diff --git a/queue-6.6/series b/queue-6.6/series new file mode 100644 index 00000000000..6d681bb267e --- /dev/null +++ b/queue-6.6/series @@ -0,0 +1,34 @@ +ksmbd-remove-unused-field-in-ksmbd_user-struct.patch +ksmbd-reorganize-ksmbd_iov_pin_rsp.patch +ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_setxattr.patch +ksmbd-fix-missing-rdma-capable-flag-for-ipoib-device.patch +ksmbd-add-support-for-surrogate-pair-conversion.patch +ksmbd-no-need-to-wait-for-binded-connection-terminat.patch +ksmbd-fix-kernel-doc-comment-of-ksmbd_vfs_kern_path_.patch +ksmbd-prevent-memory-leak-on-error-return.patch +ksmbd-separately-allocate-ci-per-dentry.patch +ksmbd-move-oplock-handling-after-unlock-parent-dir.patch +ksmbd-release-interim-response-after-sending-status-.patch +ksmbd-move-setting-smb2_flags_async_command-and-asyn.patch +ksmbd-don-t-update-op_state-as-oplock_state_none-on-.patch +ksmbd-set-epoch-in-create-context-v2-lease.patch +ksmbd-set-v2-lease-capability.patch +ksmbd-downgrade-rwh-lease-caching-state-to-rh-for-di.patch +ksmbd-send-v2-lease-break-notification-for-directory.patch +ksmbd-lazy-v2-lease-break-on-smb2_write.patch +ksmbd-avoid-duplicate-opinfo_put-call-on-error-of-sm.patch +fs-new-accessor-methods-for-atime-and-mtime.patch +client-convert-to-new-timestamp-accessors.patch +fs-cifs-fix-atime-update-check.patch +virtio_ring-fix-syncs-dma-memory-with-different-dire.patch +kexec-fix-kexec_file-dependencies.patch +kexec-select-crypto-from-kexec_file-instead-of-depen.patch +linux-export-fix-alignment-for-64-bit-ksymtab-entrie.patch +linux-export-ensure-natural-alignment-of-kcrctab-arr.patch +mptcp-refactor-sndbuf-auto-tuning.patch +mptcp-fix-possible-null-pointer-dereference-on-close.patch +mptcp-fix-inconsistent-state-on-fastopen-race.patch +block-renumber-queue_flag_hw_wc.patch +platform-x86-intel-pmc-add-suspend-callback.patch +platform-x86-intel-pmc-allow-reenabling-ltrs.patch +platform-x86-intel-pmc-move-gbe-ltr-ignore-to-suspen.patch diff --git a/queue-6.6/virtio_ring-fix-syncs-dma-memory-with-different-dire.patch b/queue-6.6/virtio_ring-fix-syncs-dma-memory-with-different-dire.patch new file mode 100644 index 00000000000..4d4bffab6ff --- /dev/null +++ b/queue-6.6/virtio_ring-fix-syncs-dma-memory-with-different-dire.patch @@ -0,0 +1,100 @@ +From 49d06b3412535c42004abc5175b7e59c8aa4c515 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 1 Dec 2023 11:33:03 +0800 +Subject: virtio_ring: fix syncs DMA memory with different direction + +From: Xuan Zhuo + +[ Upstream commit 1f475cd572ea77ae6474a17e693a96bca927efe9 ] + +Now the APIs virtqueue_dma_sync_single_range_for_{cpu,device} ignore +the parameter 'dir', that is a mistake. + +[ 6.101666] ------------[ cut here ]------------ +[ 6.102079] DMA-API: virtio-pci 0000:00:04.0: device driver syncs DMA memory with different direction [device address=0x00000000ae010000] [size=32752 bytes] [mapped with DMA_FROM_DEVICE] [synced with DMA_BIDIRECTIONAL] +[ 6.103630] WARNING: CPU: 6 PID: 0 at kernel/dma/debug.c:1125 check_sync+0x53e/0x6c0 +[ 6.107420] CPU: 6 PID: 0 Comm: swapper/6 Tainted: G E 6.6.0+ #290 +[ 6.108030] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +[ 6.108936] RIP: 0010:check_sync+0x53e/0x6c0 +[ 6.109289] Code: 24 10 e8 f5 d9 74 00 4c 8b 4c 24 10 4c 8b 44 24 18 48 8b 4c 24 20 48 89 c6 41 56 4c 89 ea 48 c7 c7 b0 f1 50 82 e8 32 fc f3 ff <0f> 0b 48 c7 c7 48 4b 4a 82 e8 74 d9 fc ff 8b 73 4c 48 8d 7b 50 31 +[ 6.110750] RSP: 0018:ffffc90000180cd8 EFLAGS: 00010092 +[ 6.111178] RAX: 00000000000000ce RBX: ffff888100aa5900 RCX: 0000000000000000 +[ 6.111744] RDX: 0000000000000104 RSI: ffffffff824c3208 RDI: 00000000ffffffff +[ 6.112316] RBP: ffffc90000180d40 R08: 0000000000000000 R09: 00000000fffeffff +[ 6.112893] R10: ffffc90000180b98 R11: ffffffff82f63308 R12: ffffffff83d5af00 +[ 6.113460] R13: ffff888100998200 R14: ffffffff824a4b5f R15: 0000000000000286 +[ 6.114027] FS: 0000000000000000(0000) GS:ffff88842fd80000(0000) knlGS:0000000000000000 +[ 6.114665] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +[ 6.115128] CR2: 00007f10f1e03030 CR3: 0000000108272004 CR4: 0000000000770ee0 +[ 6.115701] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +[ 6.116272] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +[ 6.116842] PKRU: 55555554 +[ 6.117069] Call Trace: +[ 6.117275] +[ 6.117452] ? __warn+0x84/0x140 +[ 6.117727] ? check_sync+0x53e/0x6c0 +[ 6.118034] ? __report_bug+0xea/0x100 +[ 6.118353] ? check_sync+0x53e/0x6c0 +[ 6.118653] ? report_bug+0x41/0xc0 +[ 6.118944] ? handle_bug+0x3c/0x70 +[ 6.119237] ? exc_invalid_op+0x18/0x70 +[ 6.119551] ? asm_exc_invalid_op+0x1a/0x20 +[ 6.119900] ? check_sync+0x53e/0x6c0 +[ 6.120199] ? check_sync+0x53e/0x6c0 +[ 6.120499] debug_dma_sync_single_for_cpu+0x5c/0x70 +[ 6.120906] ? dma_sync_single_for_cpu+0xb7/0x100 +[ 6.121291] virtnet_rq_unmap+0x158/0x170 [virtio_net] +[ 6.121716] virtnet_receive+0x196/0x220 [virtio_net] +[ 6.122135] virtnet_poll+0x48/0x1b0 [virtio_net] +[ 6.122524] __napi_poll+0x29/0x1b0 +[ 6.123083] net_rx_action+0x282/0x360 +[ 6.123612] __do_softirq+0xf3/0x2fb +[ 6.124138] __irq_exit_rcu+0x8e/0xf0 +[ 6.124663] common_interrupt+0xbc/0xe0 +[ 6.125202] + +We need to enable CONFIG_DMA_API_DEBUG and work with need sync mode(such +as swiotlb) to reproduce this warn. + +Fixes: 8bd2f71054bd ("virtio_ring: introduce dma sync api for virtqueue") +Reported-by: "Ning, Hongyu" +Closes: https://lore.kernel.org/all/f37cb55a-6fc8-4e21-8789-46d468325eea@linux.intel.com/ +Suggested-by: Jason Wang +Signed-off-by: Xuan Zhuo +Message-Id: <20231201033303.25141-1-xuanzhuo@linux.alibaba.com> +Signed-off-by: Michael S. Tsirkin +Reviewed-by: Parav Pandit +Acked-by: Jason Wang +Tested-by: Hongyu Ning +Signed-off-by: Sasha Levin +--- + drivers/virtio/virtio_ring.c | 6 ++---- + 1 file changed, 2 insertions(+), 4 deletions(-) + +diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c +index 51d8f3299c105..49299b1f9ec74 100644 +--- a/drivers/virtio/virtio_ring.c ++++ b/drivers/virtio/virtio_ring.c +@@ -3219,8 +3219,7 @@ void virtqueue_dma_sync_single_range_for_cpu(struct virtqueue *_vq, + if (!vq->use_dma_api) + return; + +- dma_sync_single_range_for_cpu(dev, addr, offset, size, +- DMA_BIDIRECTIONAL); ++ dma_sync_single_range_for_cpu(dev, addr, offset, size, dir); + } + EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_cpu); + +@@ -3246,8 +3245,7 @@ void virtqueue_dma_sync_single_range_for_device(struct virtqueue *_vq, + if (!vq->use_dma_api) + return; + +- dma_sync_single_range_for_device(dev, addr, offset, size, +- DMA_BIDIRECTIONAL); ++ dma_sync_single_range_for_device(dev, addr, offset, size, dir); + } + EXPORT_SYMBOL_GPL(virtqueue_dma_sync_single_range_for_device); + +-- +2.43.0 +