[PATCH 5/3] Prepare symlink caching for thread-safety

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 




From: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
Date: Thu, 9 Jul 2009 13:23:59 -0700
Subject: [PATCH 5/3] Prepare symlink caching for thread-safety

This doesn't actually change the external interfaces, so they are still
thread-unsafe, but it makes the code internally pass a pointer to a
local 'struct cache_def' around, so that the core code can be made
thread-safe.

The threaded index preloading will want to verify that the paths leading
up to a pathname are all real directories.

Signed-off-by: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
---

No real changes, but I renamed the static 'cache' data structure 
'default_cache', and made all the internal functions take a pointer 
instead of using the static version.

The functions with external linkage are left semantically unchanged by 
just making them do a simple

	struct cache_def *cache = &default_cache;

and then using that.

 symlinks.c |   75 ++++++++++++++++++++++++++++++++----------------------------
 1 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/symlinks.c b/symlinks.c
index 8dcd632..08ad353 100644
--- a/symlinks.c
+++ b/symlinks.c
@@ -38,13 +38,13 @@ static struct cache_def {
 	int flags;
 	int track_flags;
 	int prefix_len_stat_func;
-} cache;
+} default_cache;
 
-static inline void reset_lstat_cache(void)
+static inline void reset_lstat_cache(struct cache_def *cache)
 {
-	cache.path[0] = '\0';
-	cache.len = 0;
-	cache.flags = 0;
+	cache->path[0] = '\0';
+	cache->len = 0;
+	cache->flags = 0;
 	/*
 	 * The track_flags and prefix_len_stat_func members is only
 	 * set by the safeguard rule inside lstat_cache()
@@ -70,23 +70,23 @@ static inline void reset_lstat_cache(void)
  * of the prefix, where the cache should use the stat() function
  * instead of the lstat() function to test each path component.
  */
-static int lstat_cache(const char *name, int len,
+static int lstat_cache(struct cache_def *cache, const char *name, int len,
 		       int track_flags, int prefix_len_stat_func)
 {
 	int match_len, last_slash, last_slash_dir, previous_slash;
 	int match_flags, ret_flags, save_flags, max_len, ret;
 	struct stat st;
 
-	if (cache.track_flags != track_flags ||
-	    cache.prefix_len_stat_func != prefix_len_stat_func) {
+	if (cache->track_flags != track_flags ||
+	    cache->prefix_len_stat_func != prefix_len_stat_func) {
 		/*
 		 * As a safeguard rule we clear the cache if the
 		 * values of track_flags and/or prefix_len_stat_func
 		 * does not match with the last supplied values.
 		 */
-		reset_lstat_cache();
-		cache.track_flags = track_flags;
-		cache.prefix_len_stat_func = prefix_len_stat_func;
+		reset_lstat_cache(cache);
+		cache->track_flags = track_flags;
+		cache->prefix_len_stat_func = prefix_len_stat_func;
 		match_len = last_slash = 0;
 	} else {
 		/*
@@ -94,10 +94,10 @@ static int lstat_cache(const char *name, int len,
 		 * the 2 "excluding" path types.
 		 */
 		match_len = last_slash =
-			longest_path_match(name, len, cache.path, cache.len,
+			longest_path_match(name, len, cache->path, cache->len,
 					   &previous_slash);
-		match_flags = cache.flags & track_flags & (FL_NOENT|FL_SYMLINK);
-		if (match_flags && match_len == cache.len)
+		match_flags = cache->flags & track_flags & (FL_NOENT|FL_SYMLINK);
+		if (match_flags && match_len == cache->len)
 			return match_flags;
 		/*
 		 * If we now have match_len > 0, we would know that
@@ -121,18 +121,18 @@ static int lstat_cache(const char *name, int len,
 	max_len = len < PATH_MAX ? len : PATH_MAX;
 	while (match_len < max_len) {
 		do {
-			cache.path[match_len] = name[match_len];
+			cache->path[match_len] = name[match_len];
 			match_len++;
 		} while (match_len < max_len && name[match_len] != '/');
 		if (match_len >= max_len && !(track_flags & FL_FULLPATH))
 			break;
 		last_slash = match_len;
-		cache.path[last_slash] = '\0';
+		cache->path[last_slash] = '\0';
 
 		if (last_slash <= prefix_len_stat_func)
-			ret = stat(cache.path, &st);
+			ret = stat(cache->path, &st);
 		else
-			ret = lstat(cache.path, &st);
+			ret = lstat(cache->path, &st);
 
 		if (ret) {
 			ret_flags = FL_LSTATERR;
@@ -156,9 +156,9 @@ static int lstat_cache(const char *name, int len,
 	 */
 	save_flags = ret_flags & track_flags & (FL_NOENT|FL_SYMLINK);
 	if (save_flags && last_slash > 0 && last_slash <= PATH_MAX) {
-		cache.path[last_slash] = '\0';
-		cache.len = last_slash;
-		cache.flags = save_flags;
+		cache->path[last_slash] = '\0';
+		cache->len = last_slash;
+		cache->flags = save_flags;
 	} else if ((track_flags & FL_DIR) &&
 		   last_slash_dir > 0 && last_slash_dir <= PATH_MAX) {
 		/*
@@ -172,11 +172,11 @@ static int lstat_cache(const char *name, int len,
 		 * can still cache the path components before the last
 		 * one (the found symlink or non-existing component).
 		 */
-		cache.path[last_slash_dir] = '\0';
-		cache.len = last_slash_dir;
-		cache.flags = FL_DIR;
+		cache->path[last_slash_dir] = '\0';
+		cache->len = last_slash_dir;
+		cache->flags = FL_DIR;
 	} else {
-		reset_lstat_cache();
+		reset_lstat_cache(cache);
 	}
 	return ret_flags;
 }
@@ -188,16 +188,17 @@ static int lstat_cache(const char *name, int len,
 void invalidate_lstat_cache(const char *name, int len)
 {
 	int match_len, previous_slash;
+	struct cache_def *cache = &default_cache;	/* FIXME */
 
-	match_len = longest_path_match(name, len, cache.path, cache.len,
+	match_len = longest_path_match(name, len, cache->path, cache->len,
 				       &previous_slash);
 	if (len == match_len) {
-		if ((cache.track_flags & FL_DIR) && previous_slash > 0) {
-			cache.path[previous_slash] = '\0';
-			cache.len = previous_slash;
-			cache.flags = FL_DIR;
+		if ((cache->track_flags & FL_DIR) && previous_slash > 0) {
+			cache->path[previous_slash] = '\0';
+			cache->len = previous_slash;
+			cache->flags = FL_DIR;
 		} else {
-			reset_lstat_cache();
+			reset_lstat_cache(cache);
 		}
 	}
 }
@@ -207,7 +208,8 @@ void invalidate_lstat_cache(const char *name, int len)
  */
 void clear_lstat_cache(void)
 {
-	reset_lstat_cache();
+	struct cache_def *cache = &default_cache;	/* FIXME */
+	reset_lstat_cache(cache);
 }
 
 #define USE_ONLY_LSTAT  0
@@ -217,7 +219,8 @@ void clear_lstat_cache(void)
  */
 int has_symlink_leading_path(const char *name, int len)
 {
-	return lstat_cache(name, len,
+	struct cache_def *cache = &default_cache;	/* FIXME */
+	return lstat_cache(cache, name, len,
 			   FL_SYMLINK|FL_DIR, USE_ONLY_LSTAT) &
 		FL_SYMLINK;
 }
@@ -228,7 +231,8 @@ int has_symlink_leading_path(const char *name, int len)
  */
 int has_symlink_or_noent_leading_path(const char *name, int len)
 {
-	return lstat_cache(name, len,
+	struct cache_def *cache = &default_cache;	/* FIXME */
+	return lstat_cache(cache, name, len,
 			   FL_SYMLINK|FL_NOENT|FL_DIR, USE_ONLY_LSTAT) &
 		(FL_SYMLINK|FL_NOENT);
 }
@@ -242,7 +246,8 @@ int has_symlink_or_noent_leading_path(const char *name, int len)
  */
 int has_dirs_only_path(const char *name, int len, int prefix_len)
 {
-	return lstat_cache(name, len,
+	struct cache_def *cache = &default_cache;	/* FIXME */
+	return lstat_cache(cache, name, len,
 			   FL_DIR|FL_FULLPATH, prefix_len) &
 		FL_DIR;
 }
-- 
1.6.3.3.415.ga8877

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]