On Thu, Feb 14, 2013 at 07:21:27PM -0500, Tom Lane wrote:
> Bruce Momjian <br...@momjian.us> writes:
> > Agreed.  The attached patch modifies pg_check_dir() to report about
> > invisible and lost+found directory entries, and give more helpful
> > messages to the user.
> 
> I'm not terribly thrilled with special-casing 'lost+found' like that,
> since it's an extremely filesystem-dependent thing that even today
> probably only applies to a minority of our installed platforms.
> 
> The special case for dotfiles might be useful, not because of any
> connection to mount points but just because someone might forget
> that such could be lurking in a directory that "looks empty".

I was ready to give up on this patch, but then I thought, what
percentage does lost+found and dot-file-only directories cover for mount
points?  What other cases are there?

This updated version of the patch reports about dot files if they are
the _only_ files in the directory, and it suggests a top-level mount
point might be the cause.

Does this help?

-- 
  Bruce Momjian  <br...@momjian.us>        http://momjian.us
  EnterpriseDB                             http://enterprisedb.com

  + It's impossible for everything to be true. +
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
new file mode 100644
index 2ea3f6e..b8faf9c
*** a/src/bin/initdb/initdb.c
--- b/src/bin/initdb/initdb.c
*************** void setup_signals(void);
*** 257,262 ****
--- 257,263 ----
  void setup_text_search(void);
  void create_data_directory(void);
  void create_xlog_symlink(void);
+ void warn_on_mount_point(int error);
  void initialize_data_directory(void);
  
  
*************** setup_signals(void)
*** 3144,3150 ****
  void
  create_data_directory(void)
  {
! 	switch (pg_check_dir(pg_data))
  	{
  		case 0:
  			/* PGDATA not there, must create it */
--- 3145,3153 ----
  void
  create_data_directory(void)
  {
! 	int ret;
! 
! 	switch ((ret = pg_check_dir(pg_data)))
  	{
  		case 0:
  			/* PGDATA not there, must create it */
*************** create_data_directory(void)
*** 3179,3193 ****
  			break;
  
  		case 2:
  			/* Present and not empty */
  			fprintf(stderr,
  					_("%s: directory \"%s\" exists but is not empty\n"),
  					progname, pg_data);
! 			fprintf(stderr,
! 					_("If you want to create a new database system, either remove or empty\n"
! 					  "the directory \"%s\" or run %s\n"
! 					  "with an argument other than \"%s\".\n"),
! 					pg_data, progname, pg_data);
  			exit(1);			/* no further message needed */
  
  		default:
--- 3182,3201 ----
  			break;
  
  		case 2:
+ 		case 3:
+ 		case 4:
  			/* Present and not empty */
  			fprintf(stderr,
  					_("%s: directory \"%s\" exists but is not empty\n"),
  					progname, pg_data);
! 			if (ret != 4)
! 				warn_on_mount_point(ret);
! 			else
! 				fprintf(stderr,
! 						_("If you want to create a new database system, either remove or empty\n"
! 						  "the directory \"%s\" or run %s\n"
! 						  "with an argument other than \"%s\".\n"),
! 						pg_data, progname, pg_data);
  			exit(1);			/* no further message needed */
  
  		default:
*************** create_xlog_symlink(void)
*** 3206,3211 ****
--- 3214,3220 ----
  	if (strcmp(xlog_dir, "") != 0)
  	{
  		char	   *linkloc;
+ 		int			ret;
  
  		/* clean up xlog directory name, check it's absolute */
  		canonicalize_path(xlog_dir);
*************** create_xlog_symlink(void)
*** 3216,3222 ****
  		}
  
  		/* check if the specified xlog directory exists/is empty */
! 		switch (pg_check_dir(xlog_dir))
  		{
  			case 0:
  				/* xlog directory not there, must create it */
--- 3225,3231 ----
  		}
  
  		/* check if the specified xlog directory exists/is empty */
! 		switch ((ret = pg_check_dir(xlog_dir)))
  		{
  			case 0:
  				/* xlog directory not there, must create it */
*************** create_xlog_symlink(void)
*** 3255,3268 ****
  				break;
  
  			case 2:
  				/* Present and not empty */
  				fprintf(stderr,
  						_("%s: directory \"%s\" exists but is not empty\n"),
  						progname, xlog_dir);
! 				fprintf(stderr,
! 				 _("If you want to store the transaction log there, either\n"
! 				   "remove or empty the directory \"%s\".\n"),
! 						xlog_dir);
  				exit_nicely();
  
  			default:
--- 3264,3282 ----
  				break;
  
  			case 2:
+ 			case 3:
+ 			case 4:
  				/* Present and not empty */
  				fprintf(stderr,
  						_("%s: directory \"%s\" exists but is not empty\n"),
  						progname, xlog_dir);
! 				if (ret != 4)
! 					warn_on_mount_point(ret);
! 				else
! 					fprintf(stderr,
! 					 _("If you want to store the transaction log there, either\n"
! 					   "remove or empty the directory \"%s\".\n"),
! 							xlog_dir);
  				exit_nicely();
  
  			default:
*************** create_xlog_symlink(void)
*** 3291,3296 ****
--- 3305,3325 ----
  }
  
  
+ void
+ warn_on_mount_point(int error)
+ {
+ 	if (error == 2)
+ 		fprintf(stderr,
+ 				_("It contains a dot-prefixed/invisible file, perhaps due to it being a mount point.\n"));
+ 	else if (error == 3)
+ 		fprintf(stderr,
+ 				_("It contains a lost+found directory, perhaps due to it being a mount point.\n"));
+ 
+ 	fprintf(stderr,
+ 			_("Using the top-level directory of a mount point is not recommended.\n"));
+ }
+ 
+ 
  void
  initialize_data_directory(void)
  {
diff --git a/src/bin/pg_basebackup/pg_basebackup.c b/src/bin/pg_basebackup/pg_basebackup.c
new file mode 100644
index b6f7744..fb5a1bd
*** a/src/bin/pg_basebackup/pg_basebackup.c
--- b/src/bin/pg_basebackup/pg_basebackup.c
*************** verify_dir_is_empty_or_create(char *dirn
*** 371,376 ****
--- 371,378 ----
  			 */
  			return;
  		case 2:
+ 		case 3:
+ 		case 4:
  
  			/*
  			 * Exists, not empty
diff --git a/src/port/pgcheckdir.c b/src/port/pgcheckdir.c
new file mode 100644
index 3b8258c..aee5997
*** a/src/port/pgcheckdir.c
--- b/src/port/pgcheckdir.c
*************** pg_check_dir(const char *dir)
*** 31,36 ****
--- 31,37 ----
  	int			result = 1;
  	DIR		   *chkdir;
  	struct dirent *file;
+ 	bool		dot_found = false;
  
  	errno = 0;
  
*************** pg_check_dir(const char *dir)
*** 47,61 ****
  			/* skip this and parent directory */
  			continue;
  		}
  		else
  		{
! 			result = 2;			/* not empty */
  			break;
  		}
  	}
  
  #ifdef WIN32
- 
  	/*
  	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
  	 * released version
--- 48,73 ----
  			/* skip this and parent directory */
  			continue;
  		}
+ #ifndef WIN32
+ 		/* file starts with "." */
+ 		else if (file->d_name[0] == '.')
+ 		{
+ 			dot_found = true;
+ 		}
+ 		else if (strcmp("lost+found", file->d_name) == 0)
+ 		{
+ 			result = 3;			/* not empty, mount point */
+ 			break;
+ 		}
+ #endif
  		else
  		{
! 			result = 4;			/* not empty */
  			break;
  		}
  	}
  
  #ifdef WIN32
  	/*
  	 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
  	 * released version
*************** pg_check_dir(const char *dir)
*** 69,73 ****
--- 81,89 ----
  	if (errno != 0)
  		result = -1;			/* some kind of I/O error? */
  
+ 	/* We report on dot-files if we _only_ find dot files */
+ 	if (result == 1 && dot_found)
+ 		result = 2;
+ 
  	return result;
  }
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to