linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page()
@ 2022-12-31  7:57 Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 1/4] fs/sysv: Use the offset_in_page() helper Fabio M. De Francesco
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Fabio M. De Francesco @ 2022-12-31  7:57 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, linux-fsdevel
  Cc: Fabio M. De Francesco, Al Viro, Ira Weiny

kmap() is deprecated in favor of kmap_local_page().

There are two main problems with kmap(): (1) It comes with an overhead as
the mapping space is restricted and protected by a global lock for
synchronization and (2) it also requires global TLB invalidation when the
kmap’s pool wraps and it might block when the mapping space is fully
utilized until a slot becomes available.

With kmap_local_page() the mappings are per thread, CPU local, can take
page faults, and can be called from any context (including interrupts).
It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore,
the tasks can be preempted and, when they are scheduled to run again, the
kernel virtual addresses are restored and still valid.

kmap_local_page() in fs/sysv does not violate any of the strict rules of
its use, therefore it should be preferred.

Therefore, replace kmap() with kmap_local_page() in fs/sysv. kunmap_local()
requires the mapping address, so return that address from dir_get_page()
to be used in dir_put_page().

I had submitted a patch with the same purpose but it has been replaced
by this series.[1] This is based on a long series of very appreciated
comments and suggestions kindly provided by Al Viro (again thanks!).[2][3][4]

Since this is a very different thing, versioning restarts from scratch.

[1] https://lore.kernel.org/lkml/20221016164636.8696-1-fmdefrancesco@gmail.com/
[2] https://lore.kernel.org/lkml/Y4E++JERgUMoqfjG@ZenIV/#t
[3] https://lore.kernel.org/lkml/Y4FG0O7VWTTng5yh@ZenIV/#t
[4] https://lore.kernel.org/lkml/Y4ONIFJatIGsVNpf@ZenIV/#t

Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>

Fabio M. De Francesco (4):
  fs/sysv: Use the offset_in_page() helper
  fs/sysv: Change the signature of dir_get_page()
  fs/sysv: Use dir_put_page() in sysv_rename()
  fs/sysv: Replace kmap() with kmap_local_page()

 fs/sysv/dir.c   | 117 +++++++++++++++++++++++++++---------------------
 fs/sysv/namei.c |   9 ++--
 fs/sysv/sysv.h  |   1 +
 3 files changed, 71 insertions(+), 56 deletions(-)

-- 
2.39.0


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/4] fs/sysv: Use the offset_in_page() helper
  2022-12-31  7:57 [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
@ 2022-12-31  7:57 ` Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 2/4] fs/sysv: Change the signature of dir_get_page() Fabio M. De Francesco
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Fabio M. De Francesco @ 2022-12-31  7:57 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, linux-fsdevel
  Cc: Fabio M. De Francesco, Ira Weiny, Al Viro

Use the offset_in_page() helper because it is more suitable than doing
explicit subtractions between pointers to directory entries and kernel
virtual addresses of mapped pages.

Cc: Ira Weiny <ira.weiny@intel.com>
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
---
 fs/sysv/dir.c | 9 +++------
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 88e38cd8f5c9..685379bc9d64 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -206,8 +206,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 	return -EINVAL;
 
 got_it:
-	pos = page_offset(page) +
-			(char*)de - (char*)page_address(page);
+	pos = page_offset(page) + offset_in_page(de);
 	lock_page(page);
 	err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
 	if (err)
@@ -230,8 +229,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
 {
 	struct inode *inode = page->mapping->host;
-	char *kaddr = (char*)page_address(page);
-	loff_t pos = page_offset(page) + (char *)de - kaddr;
+	loff_t pos = page_offset(page) + offset_in_page(de);
 	int err;
 
 	lock_page(page);
@@ -328,8 +326,7 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
 	struct inode *inode)
 {
 	struct inode *dir = page->mapping->host;
-	loff_t pos = page_offset(page) +
-			(char *)de-(char*)page_address(page);
+	loff_t pos = page_offset(page) + offset_in_page(de);
 	int err;
 
 	lock_page(page);
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/4] fs/sysv: Change the signature of dir_get_page()
  2022-12-31  7:57 [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 1/4] fs/sysv: Use the offset_in_page() helper Fabio M. De Francesco
@ 2022-12-31  7:57 ` Fabio M. De Francesco
  2023-01-04 11:59   ` Dan Carpenter
  2022-12-31  7:57 ` [PATCH 3/4] fs/sysv: Use dir_put_page() in sysv_rename() Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 4/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
  3 siblings, 1 reply; 7+ messages in thread
From: Fabio M. De Francesco @ 2022-12-31  7:57 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, linux-fsdevel
  Cc: Fabio M. De Francesco, Ira Weiny, Al Viro

Change the signature of dir_get_page() in order to prepare this function
to the conversion to the use of kmap_local_page(). Change also those call
sites which are required to conform to the new signature.

Cc: Ira Weiny <ira.weiny@intel.com>
Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
---
 fs/sysv/dir.c | 50 ++++++++++++++++++++++++--------------------------
 1 file changed, 24 insertions(+), 26 deletions(-)

diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 685379bc9d64..0a8b5828c390 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -52,13 +52,15 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
 	return err;
 }
 
-static struct page * dir_get_page(struct inode *dir, unsigned long n)
+static void *dir_get_page(struct inode *dir, unsigned long n, struct page **p)
 {
 	struct address_space *mapping = dir->i_mapping;
 	struct page *page = read_mapping_page(mapping, n, NULL);
-	if (!IS_ERR(page))
-		kmap(page);
-	return page;
+	if (IS_ERR(page))
+		return ERR_CAST(page);
+	kmap(page);
+	*p = page;
+	return page_address(page);
 }
 
 static int sysv_readdir(struct file *file, struct dir_context *ctx)
@@ -80,11 +82,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
 	for ( ; n < npages; n++, offset = 0) {
 		char *kaddr, *limit;
 		struct sysv_dir_entry *de;
-		struct page *page = dir_get_page(inode, n);
+		struct page *page;
 
-		if (IS_ERR(page))
+		kaddr = dir_get_page(inode, n, &page);
+		if (IS_ERR(kaddr))
 			continue;
-		kaddr = (char *)page_address(page);
 		de = (struct sysv_dir_entry *)(kaddr+offset);
 		limit = kaddr + PAGE_SIZE - SYSV_DIRSIZE;
 		for ( ;(char*)de <= limit; de++, ctx->pos += sizeof(*de)) {
@@ -142,11 +144,10 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
 	n = start;
 
 	do {
-		char *kaddr;
-		page = dir_get_page(dir, n);
-		if (!IS_ERR(page)) {
-			kaddr = (char*)page_address(page);
-			de = (struct sysv_dir_entry *) kaddr;
+		char *kaddr = dir_get_page(dir, n, &page);
+
+		if (!IS_ERR(kaddr)) {
+			de = (struct sysv_dir_entry *)kaddr;
 			kaddr += PAGE_SIZE - SYSV_DIRSIZE;
 			for ( ; (char *) de <= kaddr ; de++) {
 				if (!de->inode)
@@ -185,11 +186,10 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 
 	/* We take care of directory expansion in the same loop */
 	for (n = 0; n <= npages; n++) {
-		page = dir_get_page(dir, n);
+		kaddr = dir_get_page(dir, n, &page);
 		err = PTR_ERR(page);
-		if (IS_ERR(page))
-			goto out;
-		kaddr = (char*)page_address(page);
+		if (IS_ERR(kaddr))
+			return PTR_ERR(kaddr);
 		de = (struct sysv_dir_entry *)kaddr;
 		kaddr += PAGE_SIZE - SYSV_DIRSIZE;
 		while ((char *)de <= kaddr) {
@@ -219,7 +219,6 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 	mark_inode_dirty(dir);
 out_page:
 	dir_put_page(page);
-out:
 	return err;
 out_unlock:
 	unlock_page(page);
@@ -288,12 +287,11 @@ int sysv_empty_dir(struct inode * inode)
 	for (i = 0; i < npages; i++) {
 		char *kaddr;
 		struct sysv_dir_entry * de;
-		page = dir_get_page(inode, i);
 
-		if (IS_ERR(page))
+		kaddr = dir_get_page(inode, i, &page);
+		if (IS_ERR(kaddr))
 			continue;
 
-		kaddr = (char *)page_address(page);
 		de = (struct sysv_dir_entry *)kaddr;
 		kaddr += PAGE_SIZE-SYSV_DIRSIZE;
 
@@ -339,16 +337,16 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
 	mark_inode_dirty(dir);
 }
 
-struct sysv_dir_entry * sysv_dotdot (struct inode *dir, struct page **p)
+struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct page **p)
 {
-	struct page *page = dir_get_page(dir, 0);
-	struct sysv_dir_entry *de = NULL;
+	struct page *page = NULL;
+	struct sysv_dir_entry *de = dir_get_page(dir, 0, &page);
 
-	if (!IS_ERR(page)) {
-		de = (struct sysv_dir_entry*) page_address(page) + 1;
+	if (!IS_ERR(de)) {
 		*p = page;
+		return (struct sysv_dir_entry *)page_address(page) + 1;
 	}
-	return de;
+	return NULL;
 }
 
 ino_t sysv_inode_by_name(struct dentry *dentry)
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 3/4] fs/sysv: Use dir_put_page() in sysv_rename()
  2022-12-31  7:57 [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 1/4] fs/sysv: Use the offset_in_page() helper Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 2/4] fs/sysv: Change the signature of dir_get_page() Fabio M. De Francesco
@ 2022-12-31  7:57 ` Fabio M. De Francesco
  2022-12-31  7:57 ` [PATCH 4/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
  3 siblings, 0 replies; 7+ messages in thread
From: Fabio M. De Francesco @ 2022-12-31  7:57 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, linux-fsdevel
  Cc: Fabio M. De Francesco, Al Viro, Ira Weiny

Use the dir_put_page() helper in sysv_rename() instead of open-coding two
kunmap() + put_page().

Cc: Al Viro <viro@zeniv.linux.org.uk>
Suggested-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
---
 fs/sysv/dir.c   | 2 +-
 fs/sysv/namei.c | 9 +++------
 fs/sysv/sysv.h  | 1 +
 3 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index 0a8b5828c390..a37747e9e9a3 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -28,7 +28,7 @@ const struct file_operations sysv_dir_operations = {
 	.fsync		= generic_file_fsync,
 };
 
-static inline void dir_put_page(struct page *page)
+inline void dir_put_page(struct page *page)
 {
 	kunmap(page);
 	put_page(page);
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index b2e6abc06a2d..981c1d76f342 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -250,13 +250,10 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 	return 0;
 
 out_dir:
-	if (dir_de) {
-		kunmap(dir_page);
-		put_page(dir_page);
-	}
+	if (dir_de)
+		dir_put_page(dir_page);
 out_old:
-	kunmap(old_page);
-	put_page(old_page);
+	dir_put_page(old_page);
 out:
 	return err;
 }
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index 99ddf033da4f..b250ac1dd348 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -148,6 +148,7 @@ extern void sysv_destroy_icache(void);
 
 
 /* dir.c */
+extern void dir_put_page(struct page *page);
 extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
 extern int sysv_add_link(struct dentry *, struct inode *);
 extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 4/4] fs/sysv: Replace kmap() with kmap_local_page()
  2022-12-31  7:57 [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
                   ` (2 preceding siblings ...)
  2022-12-31  7:57 ` [PATCH 3/4] fs/sysv: Use dir_put_page() in sysv_rename() Fabio M. De Francesco
@ 2022-12-31  7:57 ` Fabio M. De Francesco
  3 siblings, 0 replies; 7+ messages in thread
From: Fabio M. De Francesco @ 2022-12-31  7:57 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, linux-fsdevel
  Cc: Fabio M. De Francesco, Al Viro, Ira Weiny

kmap() is being deprecated in favor of kmap_local_page().

There are two main problems with kmap(): (1) It comes with an overhead as
the mapping space is restricted and protected by a global lock for
synchronization and (2) it also requires global TLB invalidation when the
kmap’s pool wraps and it might block when the mapping space is fully
utilized until a slot becomes available.

With kmap_local_page() the mappings are per thread, CPU local, can take
page faults, and can be called from any context (including interrupts).
It is faster than kmap() in kernels with HIGHMEM enabled. Furthermore,
the tasks can be preempted and, when they are scheduled to run again, the
kernel virtual addresses are restored and still valid.

Since kmap_local_page() would not break the strict rules of local mappings
(i.e., the thread locality and the stack based nesting), this function can
be easily and safely replace the deprecated API.

Therefore, replace kmap() with kmap_local_page() in fs/sysv. kunmap_local()
requires the mapping address, so return that address from dir_get_page()
to be used in dir_put_page().

Suggested-by: Al Viro <viro@zeniv.linux.org.uk>
Suggested-by: Ira Weiny <ira.weiny@intel.com>
Signed-off-by: Fabio M. De Francesco <fmdefrancesco@gmail.com>
---
 fs/sysv/dir.c   | 64 +++++++++++++++++++++++++++++++++----------------
 fs/sysv/namei.c |  4 ++--
 fs/sysv/sysv.h  |  2 +-
 3 files changed, 46 insertions(+), 24 deletions(-)

diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c
index a37747e9e9a3..ab409aa24757 100644
--- a/fs/sysv/dir.c
+++ b/fs/sysv/dir.c
@@ -28,9 +28,9 @@ const struct file_operations sysv_dir_operations = {
 	.fsync		= generic_file_fsync,
 };
 
-inline void dir_put_page(struct page *page)
+inline void dir_put_page(struct page *page, void *page_addr)
 {
-	kunmap(page);
+	kunmap_local(page_addr);
 	put_page(page);
 }
 
@@ -52,15 +52,21 @@ static int dir_commit_chunk(struct page *page, loff_t pos, unsigned len)
 	return err;
 }
 
+/*
+ * Calls to dir_get_page()/dir_put_page() must be nested according to the
+ * rules documented in mm/highmem.rst.
+ *
+ * NOTE: sysv_find_entry() and sysv_dotdot() act as calls to dir_get_page()
+ * and must be treated accordingly for nesting purposes.
+ */
 static void *dir_get_page(struct inode *dir, unsigned long n, struct page **p)
 {
 	struct address_space *mapping = dir->i_mapping;
 	struct page *page = read_mapping_page(mapping, n, NULL);
 	if (IS_ERR(page))
 		return ERR_CAST(page);
-	kmap(page);
 	*p = page;
-	return page_address(page);
+	return kmap_local_page(page);
 }
 
 static int sysv_readdir(struct file *file, struct dir_context *ctx)
@@ -98,11 +104,11 @@ static int sysv_readdir(struct file *file, struct dir_context *ctx)
 			if (!dir_emit(ctx, name, strnlen(name,SYSV_NAMELEN),
 					fs16_to_cpu(SYSV_SB(sb), de->inode),
 					DT_UNKNOWN)) {
-				dir_put_page(page);
+				dir_put_page(page, kaddr);
 				return 0;
 			}
 		}
-		dir_put_page(page);
+		dir_put_page(page, kaddr);
 	}
 	return 0;
 }
@@ -125,6 +131,11 @@ static inline int namecompare(int len, int maxlen,
  * returns the cache buffer in which the entry was found, and the entry
  * itself (as a parameter - res_dir). It does NOT read the inode of the
  * entry - you'll have to do that yourself if you want to.
+ *
+ * On Success dir_put_page() should be called on *res_page.
+ *
+ * sysv_find_entry() acts as a call to dir_get_page() and must be treated
+ * accordingly for nesting purposes.
  */
 struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_page)
 {
@@ -156,7 +167,7 @@ struct sysv_dir_entry *sysv_find_entry(struct dentry *dentry, struct page **res_
 							name, de->name))
 					goto found;
 			}
-			dir_put_page(page);
+			dir_put_page(page, kaddr);
 		}
 
 		if (++n >= npages)
@@ -200,7 +211,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 				goto out_page;
 			de++;
 		}
-		dir_put_page(page);
+		dir_put_page(page, kaddr);
 	}
 	BUG();
 	return -EINVAL;
@@ -218,7 +229,7 @@ int sysv_add_link(struct dentry *dentry, struct inode *inode)
 	dir->i_mtime = dir->i_ctime = current_time(dir);
 	mark_inode_dirty(dir);
 out_page:
-	dir_put_page(page);
+	dir_put_page(page, kaddr);
 	return err;
 out_unlock:
 	unlock_page(page);
@@ -229,6 +240,12 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
 {
 	struct inode *inode = page->mapping->host;
 	loff_t pos = page_offset(page) + offset_in_page(de);
+	/*
+	 * The "de" dentry points somewhere in the same page whose we need the
+	 * address of; therefore, we can simply get the base address "kaddr" by
+	 * masking the previous with PAGE_MASK.
+	 */
+	char *kaddr = (char *)((unsigned long)de & PAGE_MASK);
 	int err;
 
 	lock_page(page);
@@ -236,7 +253,7 @@ int sysv_delete_entry(struct sysv_dir_entry *de, struct page *page)
 	BUG_ON(err);
 	de->inode = 0;
 	err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
-	dir_put_page(page);
+	dir_put_page(page, kaddr);
 	inode->i_ctime = inode->i_mtime = current_time(inode);
 	mark_inode_dirty(inode);
 	return err;
@@ -256,9 +273,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
 		unlock_page(page);
 		goto fail;
 	}
-	kmap(page);
-
-	base = (char*)page_address(page);
+	base = kmap_local_page(page);
 	memset(base, 0, PAGE_SIZE);
 
 	de = (struct sysv_dir_entry *) base;
@@ -268,7 +283,7 @@ int sysv_make_empty(struct inode *inode, struct inode *dir)
 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), dir->i_ino);
 	strcpy(de->name,"..");
 
-	kunmap(page);
+	kunmap_local(base);
 	err = dir_commit_chunk(page, 0, 2 * SYSV_DIRSIZE);
 fail:
 	put_page(page);
@@ -283,10 +298,10 @@ int sysv_empty_dir(struct inode * inode)
 	struct super_block *sb = inode->i_sb;
 	struct page *page = NULL;
 	unsigned long i, npages = dir_pages(inode);
+	char *kaddr;
 
 	for (i = 0; i < npages; i++) {
-		char *kaddr;
-		struct sysv_dir_entry * de;
+		struct sysv_dir_entry *de;
 
 		kaddr = dir_get_page(inode, i, &page);
 		if (IS_ERR(kaddr))
@@ -310,12 +325,12 @@ int sysv_empty_dir(struct inode * inode)
 			if (de->name[1] != '.' || de->name[2])
 				goto not_empty;
 		}
-		dir_put_page(page);
+		dir_put_page(page, kaddr);
 	}
 	return 1;
 
 not_empty:
-	dir_put_page(page);
+	dir_put_page(page, kaddr);
 	return 0;
 }
 
@@ -332,11 +347,18 @@ void sysv_set_link(struct sysv_dir_entry *de, struct page *page,
 	BUG_ON(err);
 	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
 	err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
-	dir_put_page(page);
+	dir_put_page(page, de);
 	dir->i_mtime = dir->i_ctime = current_time(dir);
 	mark_inode_dirty(dir);
 }
 
+/*
+ * Calls to dir_get_page()/dir_put_page() must be nested according to the
+ * rules documented in mm/highmem.rst.
+ *
+ * sysv_dotdot() acts as a call to dir_get_page() and must be treated
+ * accordingly for nesting purposes.
+ */
 struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct page **p)
 {
 	struct page *page = NULL;
@@ -344,7 +366,7 @@ struct sysv_dir_entry *sysv_dotdot(struct inode *dir, struct page **p)
 
 	if (!IS_ERR(de)) {
 		*p = page;
-		return (struct sysv_dir_entry *)page_address(page) + 1;
+		return (struct sysv_dir_entry *)de + 1;
 	}
 	return NULL;
 }
@@ -357,7 +379,7 @@ ino_t sysv_inode_by_name(struct dentry *dentry)
 	
 	if (de) {
 		res = fs16_to_cpu(SYSV_SB(dentry->d_sb), de->inode);
-		dir_put_page(page);
+		dir_put_page(page, de);
 	}
 	return res;
 }
diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c
index 981c1d76f342..371cf9012052 100644
--- a/fs/sysv/namei.c
+++ b/fs/sysv/namei.c
@@ -251,9 +251,9 @@ static int sysv_rename(struct user_namespace *mnt_userns, struct inode *old_dir,
 
 out_dir:
 	if (dir_de)
-		dir_put_page(dir_page);
+		dir_put_page(dir_page, dir_de);
 out_old:
-	dir_put_page(old_page);
+	dir_put_page(old_page, old_de);
 out:
 	return err;
 }
diff --git a/fs/sysv/sysv.h b/fs/sysv/sysv.h
index b250ac1dd348..50f19bfd8d10 100644
--- a/fs/sysv/sysv.h
+++ b/fs/sysv/sysv.h
@@ -148,7 +148,7 @@ extern void sysv_destroy_icache(void);
 
 
 /* dir.c */
-extern void dir_put_page(struct page *page);
+extern void dir_put_page(struct page *page, void *vaddr);
 extern struct sysv_dir_entry *sysv_find_entry(struct dentry *, struct page **);
 extern int sysv_add_link(struct dentry *, struct inode *);
 extern int sysv_delete_entry(struct sysv_dir_entry *, struct page *);
-- 
2.39.0


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] fs/sysv: Change the signature of dir_get_page()
  2022-12-31  7:57 ` [PATCH 2/4] fs/sysv: Change the signature of dir_get_page() Fabio M. De Francesco
@ 2023-01-04 11:59   ` Dan Carpenter
  2023-01-04 13:02     ` Fabio M. De Francesco
  0 siblings, 1 reply; 7+ messages in thread
From: Dan Carpenter @ 2023-01-04 11:59 UTC (permalink / raw)
  To: oe-kbuild, Fabio M. De Francesco, Christoph Hellwig,
	linux-kernel, linux-fsdevel
  Cc: lkp, oe-kbuild-all, Fabio M. De Francesco, Ira Weiny, Al Viro

Hi Fabio,

https://git-scm.com/docs/git-format-patch#_base_tree_information]

url:    https://github.com/intel-lab-lkp/linux/commits/Fabio-M-De-Francesco/fs-sysv-Use-the-offset_in_page-helper/20221231-155850
base:   git://git.infradead.org/users/hch/configfs.git for-next
patch link:    https://lore.kernel.org/r/20221231075717.10258-3-fmdefrancesco%40gmail.com
patch subject: [PATCH 2/4] fs/sysv: Change the signature of dir_get_page()
config: xtensa-randconfig-m031-20230101
compiler: xtensa-linux-gcc (GCC) 12.1.0

If you fix the issue, kindly add following tag where applicable
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <error27@gmail.com>

smatch warnings:
fs/sysv/dir.c:190 sysv_add_link() warn: passing zero to 'PTR_ERR'

vim +/PTR_ERR +190 fs/sysv/dir.c

^1da177e4c3f41 Linus Torvalds        2005-04-16  174  int sysv_add_link(struct dentry *dentry, struct inode *inode)
^1da177e4c3f41 Linus Torvalds        2005-04-16  175  {
2b0143b5c986be David Howells         2015-03-17  176  	struct inode *dir = d_inode(dentry->d_parent);
^1da177e4c3f41 Linus Torvalds        2005-04-16  177  	const char * name = dentry->d_name.name;
^1da177e4c3f41 Linus Torvalds        2005-04-16  178  	int namelen = dentry->d_name.len;
^1da177e4c3f41 Linus Torvalds        2005-04-16  179  	struct page *page = NULL;
^1da177e4c3f41 Linus Torvalds        2005-04-16  180  	struct sysv_dir_entry * de;
^1da177e4c3f41 Linus Torvalds        2005-04-16  181  	unsigned long npages = dir_pages(dir);
^1da177e4c3f41 Linus Torvalds        2005-04-16  182  	unsigned long n;
^1da177e4c3f41 Linus Torvalds        2005-04-16  183  	char *kaddr;
26a6441aadde86 Nicholas Piggin       2007-10-16  184  	loff_t pos;
^1da177e4c3f41 Linus Torvalds        2005-04-16  185  	int err;
^1da177e4c3f41 Linus Torvalds        2005-04-16  186  
^1da177e4c3f41 Linus Torvalds        2005-04-16  187  	/* We take care of directory expansion in the same loop */
^1da177e4c3f41 Linus Torvalds        2005-04-16  188  	for (n = 0; n <= npages; n++) {
4b8a9c0afda16b Fabio M. De Francesco 2022-12-31  189  		kaddr = dir_get_page(dir, n, &page);
^1da177e4c3f41 Linus Torvalds        2005-04-16 @190  		err = PTR_ERR(page);

This "err" assignment is a dead store (pointless/never used).

4b8a9c0afda16b Fabio M. De Francesco 2022-12-31  191  		if (IS_ERR(kaddr))
4b8a9c0afda16b Fabio M. De Francesco 2022-12-31  192  			return PTR_ERR(kaddr);
^1da177e4c3f41 Linus Torvalds        2005-04-16  193  		de = (struct sysv_dir_entry *)kaddr;
09cbfeaf1a5a67 Kirill A. Shutemov    2016-04-01  194  		kaddr += PAGE_SIZE - SYSV_DIRSIZE;
^1da177e4c3f41 Linus Torvalds        2005-04-16  195  		while ((char *)de <= kaddr) {
^1da177e4c3f41 Linus Torvalds        2005-04-16  196  			if (!de->inode)
^1da177e4c3f41 Linus Torvalds        2005-04-16  197  				goto got_it;
^1da177e4c3f41 Linus Torvalds        2005-04-16  198  			err = -EEXIST;
^1da177e4c3f41 Linus Torvalds        2005-04-16  199  			if (namecompare(namelen, SYSV_NAMELEN, name, de->name)) 
^1da177e4c3f41 Linus Torvalds        2005-04-16  200  				goto out_page;
^1da177e4c3f41 Linus Torvalds        2005-04-16  201  			de++;
^1da177e4c3f41 Linus Torvalds        2005-04-16  202  		}
^1da177e4c3f41 Linus Torvalds        2005-04-16  203  		dir_put_page(page);
^1da177e4c3f41 Linus Torvalds        2005-04-16  204  	}
^1da177e4c3f41 Linus Torvalds        2005-04-16  205  	BUG();
^1da177e4c3f41 Linus Torvalds        2005-04-16  206  	return -EINVAL;
^1da177e4c3f41 Linus Torvalds        2005-04-16  207  
^1da177e4c3f41 Linus Torvalds        2005-04-16  208  got_it:
1023904333f9cb Fabio M. De Francesco 2022-12-31  209  	pos = page_offset(page) + offset_in_page(de);
^1da177e4c3f41 Linus Torvalds        2005-04-16  210  	lock_page(page);
f4e420dc423148 Christoph Hellwig     2010-06-04  211  	err = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE);
^1da177e4c3f41 Linus Torvalds        2005-04-16  212  	if (err)
^1da177e4c3f41 Linus Torvalds        2005-04-16  213  		goto out_unlock;
^1da177e4c3f41 Linus Torvalds        2005-04-16  214  	memcpy (de->name, name, namelen);
^1da177e4c3f41 Linus Torvalds        2005-04-16  215  	memset (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2);
^1da177e4c3f41 Linus Torvalds        2005-04-16  216  	de->inode = cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino);
26a6441aadde86 Nicholas Piggin       2007-10-16  217  	err = dir_commit_chunk(page, pos, SYSV_DIRSIZE);
02027d42c3f747 Deepa Dinamani        2016-09-14  218  	dir->i_mtime = dir->i_ctime = current_time(dir);
^1da177e4c3f41 Linus Torvalds        2005-04-16  219  	mark_inode_dirty(dir);
^1da177e4c3f41 Linus Torvalds        2005-04-16  220  out_page:
^1da177e4c3f41 Linus Torvalds        2005-04-16  221  	dir_put_page(page);
^1da177e4c3f41 Linus Torvalds        2005-04-16  222  	return err;
^1da177e4c3f41 Linus Torvalds        2005-04-16  223  out_unlock:
^1da177e4c3f41 Linus Torvalds        2005-04-16  224  	unlock_page(page);
^1da177e4c3f41 Linus Torvalds        2005-04-16  225  	goto out_page;
^1da177e4c3f41 Linus Torvalds        2005-04-16  226  }

-- 
0-DAY CI Kernel Test Service
https://01.org/lkp



^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 2/4] fs/sysv: Change the signature of dir_get_page()
  2023-01-04 11:59   ` Dan Carpenter
@ 2023-01-04 13:02     ` Fabio M. De Francesco
  0 siblings, 0 replies; 7+ messages in thread
From: Fabio M. De Francesco @ 2023-01-04 13:02 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: oe-kbuild, Christoph Hellwig, linux-kernel, linux-fsdevel, lkp,
	oe-kbuild-all, Ira Weiny, Al Viro

On mercoledì 4 gennaio 2023 12:59:24 CET Dan Carpenter wrote:
> Hi Fabio,
> 
> https://git-scm.com/docs/git-format-patch#_base_tree_information]
> 
> url:   
> https://github.com/intel-lab-lkp/linux/commits/Fabio-M-De-Francesco/fs-sysv-U
> se-the-offset_in_page-helper/20221231-155850 base:  
> git://git.infradead.org/users/hch/configfs.git for-next
> patch link:   
> https://lore.kernel.org/r/20221231075717.10258-3-fmdefrancesco%40gmail.com
> patch subject: [PATCH 2/4] fs/sysv: Change the signature of dir_get_page()
> config: xtensa-randconfig-m031-20230101
> compiler: xtensa-linux-gcc (GCC) 12.1.0
> 
> If you fix the issue, kindly add following tag where applicable
> 
> | Reported-by: kernel test robot <lkp@intel.com>
> | Reported-by: Dan Carpenter <error27@gmail.com>
> 
> smatch warnings:
> fs/sysv/dir.c:190 sysv_add_link() warn: passing zero to 'PTR_ERR'
> 
> vim +/PTR_ERR +190 fs/sysv/dir.c
> 
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  174  int 
sysv_add_link(struct
> dentry *dentry, struct inode *inode) ^1da177e4c3f41 Linus Torvalds       
> 2005-04-16  175  {
> 2b0143b5c986be David Howells         2015-03-17  176  	struct inode *dir 
=
> d_inode(dentry->d_parent); ^1da177e4c3f41 Linus Torvalds        2005-04-16 
> 177  	const char * name = dentry->d_name.name; ^1da177e4c3f41 Linus 
Torvalds 
>       2005-04-16  178  	int namelen = dentry->d_name.len; 
^1da177e4c3f41
> Linus Torvalds        2005-04-16  179  	struct page *page = NULL;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  180  	struct 
sysv_dir_entry
> * de; ^1da177e4c3f41 Linus Torvalds        2005-04-16  181  	
unsigned long
> npages = dir_pages(dir); ^1da177e4c3f41 Linus Torvalds        2005-04-16  
182
>  	unsigned long n; ^1da177e4c3f41 Linus Torvalds        2005-04-16  
183 
> 	char *kaddr;
> 26a6441aadde86 Nicholas Piggin       2007-10-16  184  	loff_t pos;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  185  	int err;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  186
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  187  	/* We take care 
of
> directory expansion in the same loop */ ^1da177e4c3f41 Linus Torvalds       
> 2005-04-16  188  	for (n = 0; n <= npages; n++) { 4b8a9c0afda16b Fabio M. De
> Francesco 2022-12-31  189  		kaddr = dir_get_page(dir, n, &page);
> ^1da177e4c3f41 Linus Torvalds        2005-04-16 @190  		err = 
PTR_ERR(page);
> 
> This "err" assignment is a dead store (pointless/never used).

Hi Dan,

Thanks for catching it.
I'll wait for comments on this series one or two more days and then delete 
that assignment.

Again thanks,

Fabio

> 4b8a9c0afda16b Fabio M. De Francesco 2022-12-31  191  		if 
(IS_ERR(kaddr))
> 4b8a9c0afda16b Fabio M. De Francesco 2022-12-31  192  			
return
> PTR_ERR(kaddr); ^1da177e4c3f41 Linus Torvalds        2005-04-16  193  	
	de =
> (struct sysv_dir_entry *)kaddr; 09cbfeaf1a5a67 Kirill A. Shutemov   
> 2016-04-01  194  		kaddr += PAGE_SIZE - SYSV_DIRSIZE; 
^1da177e4c3f41 Linus
> Torvalds        2005-04-16  195  		while ((char *)de <= kaddr) 
{
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  196  			
if (!de->inode)
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  197  			
	goto got_it;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  198  			
err = -EEXIST;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  199  			
if
> (namecompare(namelen, SYSV_NAMELEN, name, de->name)) ^1da177e4c3f41 Linus
> Torvalds        2005-04-16  200  				goto 
out_page; ^1da177e4c3f41 Linus
> Torvalds        2005-04-16  201  			de++;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  202  		}
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  203  		
dir_put_page(page);
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  204  	}
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  205  	BUG();
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  206  	return -EINVAL;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  207
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  208  got_it:
> 1023904333f9cb Fabio M. De Francesco 2022-12-31  209  	pos = 
page_offset(page)
> + offset_in_page(de); ^1da177e4c3f41 Linus Torvalds        2005-04-16  210 
> 	lock_page(page); f4e420dc423148 Christoph Hellwig     2010-06-04  
211  	err
> = sysv_prepare_chunk(page, pos, SYSV_DIRSIZE); ^1da177e4c3f41 Linus Torvalds 
>       2005-04-16  212  	if (err)
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  213  		goto 
out_unlock;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  214  	memcpy (de->name, 
name,
> namelen); ^1da177e4c3f41 Linus Torvalds        2005-04-16  215  	memset
> (de->name + namelen, 0, SYSV_DIRSIZE - namelen - 2); ^1da177e4c3f41 Linus
> Torvalds        2005-04-16  216  	de->inode =
> cpu_to_fs16(SYSV_SB(inode->i_sb), inode->i_ino); 26a6441aadde86 Nicholas
> Piggin       2007-10-16  217  	err = dir_commit_chunk(page, pos,
> SYSV_DIRSIZE); 02027d42c3f747 Deepa Dinamani        2016-09-14  218 
> 	dir->i_mtime = dir->i_ctime = current_time(dir); ^1da177e4c3f41 
Linus
> Torvalds        2005-04-16  219  	mark_inode_dirty(dir); ^1da177e4c3f41 
Linus
> Torvalds        2005-04-16  220  out_page:
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  221  	
dir_put_page(page);
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  222  	return err;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  223  out_unlock:
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  224  	
unlock_page(page);
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  225  	goto out_page;
> ^1da177e4c3f41 Linus Torvalds        2005-04-16  226  }
> 
> --
> 0-DAY CI Kernel Test Service
> https://01.org/lkp





^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2023-01-04 13:02 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-31  7:57 [PATCH 0/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco
2022-12-31  7:57 ` [PATCH 1/4] fs/sysv: Use the offset_in_page() helper Fabio M. De Francesco
2022-12-31  7:57 ` [PATCH 2/4] fs/sysv: Change the signature of dir_get_page() Fabio M. De Francesco
2023-01-04 11:59   ` Dan Carpenter
2023-01-04 13:02     ` Fabio M. De Francesco
2022-12-31  7:57 ` [PATCH 3/4] fs/sysv: Use dir_put_page() in sysv_rename() Fabio M. De Francesco
2022-12-31  7:57 ` [PATCH 4/4] fs/sysv: Replace kmap() with kmap_local_page() Fabio M. De Francesco

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).