U-Boot Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Gabriel Dalimonte <gabriel.dalimonte@gmail.com>
To: u-boot@lists.denx.de
Cc: Gabriel Dalimonte <gabriel.dalimonte@gmail.com>,
	Heinrich Schuchardt <xypron.glpk@gmx.de>,
	Tom Rini <trini@konsulko.com>
Subject: [PATCH v2 4/6] fs: fat: update parent dirs metadata on dentry create/delete
Date: Mon, 17 Feb 2025 13:26:45 -0500	[thread overview]
Message-ID: <20250217182648.31294-5-gabriel.dalimonte@gmail.com> (raw)
In-Reply-To: <20250217182648.31294-1-gabriel.dalimonte@gmail.com>

POSIX filesystem functions that create or remove directory entries contain
text along the lines of "[function] shall mark for update the last data
modification and last file status change timestamps of the parent
directory of each file." [1][2][3] The common theme is these timestamp
updates occur when a directory entry is added or removed. The
create_link() and delete_dentry_link() functions have been changed to
update the modification timestamp on the directory where the direntry
change occurs. This differs slightly from Linux in the case of rename(),
where Linux will not update `new_path`'s parent directory's timestamp if
it is replacing an existing file. (via `vfat_add_entry` [4])

The timestamps are not updated if the build configuration does not support
RTCs. This is an effort to minimize introducing erratic timestamps where
they would go from [current date] -> 2000-01-01 (error timestamp in the
FAT driver). I would assume an unchanged timestamp would be more valuable
than a default timestamp in these cases.

[1] https://pubs.opengroup.org/onlinepubs/9799919799/functions/rename.html
[2] https://pubs.opengroup.org/onlinepubs/9799919799/functions/unlink.html
[3] https://pubs.opengroup.org/onlinepubs/9799919799/functions/open.html
[4] https://elixir.bootlin.com/linux/v6.12.6/source/fs/fat/namei_vfat.c#L682

Signed-off-by: Gabriel Dalimonte <gabriel.dalimonte@gmail.com>

---

Changes in v2:
 - remove setting ATTR_ARCH on parent dirs during renames
 - skip updating timestamps if no RTC present
 - make fat_itr stack allocated in update_parent_dir_props
 - update parent dir props in create_link and delete_dentry_link


---
 fs/fat/fat_write.c | 78 +++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 74 insertions(+), 4 deletions(-)

diff --git a/fs/fat/fat_write.c b/fs/fat/fat_write.c
index d4952e259ff..0b924541187 100644
--- a/fs/fat/fat_write.c
+++ b/fs/fat/fat_write.c
@@ -1237,6 +1237,64 @@ static int fat_itr_parent(fat_itr *itr)
 	return fat_itr_resolve(itr, "..", TYPE_DIR);
 }
 
+/**
+ * update_parent_dir_props - updates the modified time for the parent directory
+ *
+ * @dir_itr:	iterator positioned anywhere in a directory whose parent
+ * should be updated
+ * @Return:	0 for success, -errno otherwise
+ */
+static int update_parent_dir_props(fat_itr *dir_itr)
+{
+	int ret = 0;
+
+	fat_itr itr;
+	fsdata fsdata = { .fatbuf = NULL, }, *mydata = &fsdata;
+	__u32 target_clust = dir_itr->start_clust;
+
+	/* Short circuit if no RTC because it only updates timestamps */
+	if (!CONFIG_IS_ENABLED(DM_RTC))
+		return ret;
+
+	/* duplicate fsdata */
+	itr = *dir_itr;
+	fsdata = *itr.fsdata;
+
+	/* allocate local fat buffer */
+	fsdata.fatbuf = malloc_cache_aligned(FATBUFSIZE);
+	if (!fsdata.fatbuf) {
+		log_debug("Error: allocating memory\n");
+		ret = -ENOMEM;
+		return ret;
+	}
+
+	fsdata.fatbufnum = -1;
+	itr.fsdata = &fsdata;
+
+	if (!itr.is_root) {
+		ret = fat_itr_parent(&itr);
+		if (ret)
+			goto exit;
+
+		while (fat_itr_next(&itr)) {
+			if (START(itr.dent) == target_clust)
+				goto update;
+		}
+
+		/* dent not found */
+		ret = -EIO;
+		goto exit;
+update:
+		dentry_set_time(itr.dent);
+		ret = flush_dir(&itr);
+	}
+
+exit:
+	free(fsdata.fatbuf);
+
+	return ret;
+}
+
 /**
  * create_link() - inserts a directory entry for a file or directory
  *
@@ -1270,8 +1328,9 @@ static int create_link(fat_itr *itr, char *basename, __u32 clust, __u32 size,
 	}
 
 	fill_dentry(itr->fsdata, itr->dent, shortname, clust, size, attr);
+	ret = update_parent_dir_props(itr);
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -1612,20 +1671,25 @@ static int delete_long_name(fat_itr *itr)
  */
 static int delete_dentry_link(fat_itr *itr)
 {
+	int ret;
+
 	itr->dent = itr->dent_start;
 	itr->remaining = itr->dent_rem;
 	/* Delete long name */
 	if ((itr->dent->attr & ATTR_VFAT) == ATTR_VFAT &&
 	    (itr->dent->nameext.name[0] & LAST_LONG_ENTRY_MASK)) {
-		int ret;
-
 		ret = delete_long_name(itr);
 		if (ret)
 			return ret;
 	}
 	/* Delete short name */
 	delete_single_dentry(itr);
-	return flush_dir(itr);
+
+	ret = flush_dir(itr);
+	if (ret)
+		return ret;
+
+	return update_parent_dir_props(itr);
 }
 
 /**
@@ -2047,6 +2111,10 @@ int fat_rename(const char *old_path, const char *new_path)
 		*new_itr->dent = *old_itr->dent;
 		new_itr->dent->nameext = new_name;
 		new_itr->dent->lcase = lcase;
+
+		ret = update_parent_dir_props(new_itr);
+		if (ret)
+			goto exit;
 	} else {
 		/* reset iterator to the start of the directory */
 		ret = fat_move_to_cluster(new_itr, new_itr->start_clust);
@@ -2089,6 +2157,8 @@ int fat_rename(const char *old_path, const char *new_path)
 		ret = flush_dir(new_itr);
 		if (ret)
 			goto exit;
+		/* restore directory location to update parent props below */
+		fat_itr_child(new_itr, new_itr);
 	}
 
 	/* refresh old in case write happened to the same block. */
-- 
2.34.1


  parent reply	other threads:[~2025-02-18  5:36 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-02-17 18:26 [PATCH v2 0/6] This series adds support for file renaming to EFI_FILE_PROTOCOL.SetInfo() Gabriel Dalimonte
2025-02-17 18:26 ` [PATCH v2 1/6] fs: fat: factor out dentry link create/delete Gabriel Dalimonte
2025-02-17 18:26 ` [PATCH v2 2/6] fs: add rename infrastructure Gabriel Dalimonte
2025-02-20  7:33   ` Ilias Apalodimas
2025-02-17 18:26 ` [PATCH v2 3/6] fs: fat: add rename Gabriel Dalimonte
2025-02-17 18:26 ` Gabriel Dalimonte [this message]
2025-02-17 18:26 ` [PATCH v2 5/6] efi_loader: move path out of file_handle Gabriel Dalimonte
2025-02-20  7:55   ` Ilias Apalodimas
2025-03-04  2:30     ` Gabriel D'Alimonte
2025-02-17 18:26 ` [PATCH v2 6/6] efi_loader: support file rename in SetInfo() Gabriel Dalimonte
2025-02-20  8:21   ` Ilias Apalodimas
2025-02-20  8:30     ` Ilias Apalodimas
2025-03-08 14:04 ` [PATCH v2 0/6] This series adds support for file renaming to EFI_FILE_PROTOCOL.SetInfo() Tom Rini

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250217182648.31294-5-gabriel.dalimonte@gmail.com \
    --to=gabriel.dalimonte@gmail.com \
    --cc=trini@konsulko.com \
    --cc=u-boot@lists.denx.de \
    --cc=xypron.glpk@gmx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox