11.1Syamt-- $NetBSD: check.sql,v 1.1 2011/10/12 01:05:00 yamt Exp $
21.1Syamt
31.1Syamt-- Copyright (c)2010,2011 YAMAMOTO Takashi,
41.1Syamt-- All rights reserved.
51.1Syamt--
61.1Syamt-- Redistribution and use in source and binary forms, with or without
71.1Syamt-- modification, are permitted provided that the following conditions
81.1Syamt-- are met:
91.1Syamt-- 1. Redistributions of source code must retain the above copyright
101.1Syamt--    notice, this list of conditions and the following disclaimer.
111.1Syamt-- 2. Redistributions in binary form must reproduce the above copyright
121.1Syamt--    notice, this list of conditions and the following disclaimer in the
131.1Syamt--    documentation and/or other materials provided with the distribution.
141.1Syamt--
151.1Syamt-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161.1Syamt-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171.1Syamt-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181.1Syamt-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191.1Syamt-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201.1Syamt-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211.1Syamt-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221.1Syamt-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231.1Syamt-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241.1Syamt-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251.1Syamt-- SUCH DAMAGE.
261.1Syamt
271.1Syamt-- filesystem consistency checks.  ie. something like "fsck -n"
281.1Syamt
291.1SyamtBEGIN;
301.1SyamtSET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
311.1SyamtSET TRANSACTION READ ONLY;
321.1SyamtSET search_path TO pgfs;
331.1SyamtSELECT count(*) AS "unreferenced files (dirent)"
341.1Syamt	FROM file f LEFT JOIN dirent d
351.1Syamt	ON f.fileid = d.child_fileid
361.1Syamt	WHERE f.fileid <> 1 AND d.child_fileid IS NULL;
371.1SyamtSELECT count(*) AS "unreferenced files (nlink)"
381.1Syamt	FROM file f
391.1Syamt	WHERE f.nlink = 0;
401.1SyamtSELECT count(*) AS "regular files without datafork"
411.1Syamt	FROM file f LEFT JOIN datafork df
421.1Syamt	ON f.fileid = df.fileid
431.1Syamt	WHERE df.fileid IS NULL AND f.type IN ('regular', 'link');
441.1SyamtSELECT count(*) AS "broken datafork reference"
451.1Syamt	FROM file f INNER JOIN datafork df
461.1Syamt	ON f.fileid = df.fileid
471.1Syamt	WHERE f.type NOT IN ('regular', 'link');
481.1SyamtSELECT count(*) AS "unreferenced dataforks"
491.1Syamt	FROM file f RIGHT JOIN datafork df
501.1Syamt	ON f.fileid = df.fileid
511.1Syamt	WHERE f.fileid IS NULL;
521.1SyamtSELECT count(*) AS "dataforks without large object"
531.1Syamt	FROM datafork df LEFT JOIN pg_largeobject_metadata lm
541.1Syamt	ON df.loid = lm.oid
551.1Syamt	WHERE lm.oid IS NULL;
561.1SyamtSELECT count(*) AS "unreferenced large objects"
571.1Syamt	FROM datafork df RIGHT JOIN pg_largeobject_metadata lm
581.1Syamt	ON df.loid = lm.oid
591.1Syamt	WHERE df.loid IS NULL;
601.1SyamtSELECT count(*) AS "dirent broken parent_fileid references"
611.1Syamt	FROM dirent d LEFT JOIN file f
621.1Syamt	ON d.parent_fileid = f.fileid
631.1Syamt	WHERE f.fileid IS NULL OR f.type <> 'directory';
641.1SyamtSELECT count(*) AS "dirent broken child_fileid references"
651.1Syamt	FROM dirent d LEFT JOIN file f
661.1Syamt	ON d.child_fileid = f.fileid
671.1Syamt	WHERE f.fileid IS NULL;
681.1SyamtSELECT count(*) AS "dirent loops" FROM file f WHERE EXISTS (
691.1Syamt	WITH RECURSIVE r AS
701.1Syamt	(
711.1Syamt			SELECT d.* FROM dirent d
721.1Syamt				WHERE d.child_fileid = f.fileid
731.1Syamt		UNION ALL
741.1Syamt			SELECT d.* FROM dirent d INNER JOIN r
751.1Syamt				ON d.child_fileid = r.parent_fileid
761.1Syamt	)
771.1Syamt	SELECT * FROM r WHERE r.parent_fileid = f.fileid);
781.1SyamtSELECT count(*) AS "broken nlink"
791.1Syamt	FROM
801.1Syamt	(
811.1Syamt	SELECT coalesce(fp.fileid, fc.fileid) AS fileid,
821.1Syamt		coalesce(fp.nlink, 0) + coalesce(fc.nlink, 0) +
831.1Syamt		CASE
841.1Syamt			WHEN coalesce(fp.fileid, fc.fileid) = 1 THEN 1
851.1Syamt			ELSE 0
861.1Syamt		END
871.1Syamt		AS nlink
881.1Syamt		FROM
891.1Syamt		(
901.1Syamt		SELECT child_fileid AS fileid, count(*) AS nlink
911.1Syamt			FROM dirent
921.1Syamt			GROUP BY child_fileid
931.1Syamt		) fp
941.1Syamt		FULL JOIN
951.1Syamt		(
961.1Syamt		SELECT count(*) AS nlink, d.parent_fileid AS fileid
971.1Syamt			FROM dirent d
981.1Syamt			JOIN file f
991.1Syamt			ON d.child_fileid = f.fileid
1001.1Syamt			WHERE f.type = 'directory'
1011.1Syamt			GROUP BY parent_fileid
1021.1Syamt		) fc
1031.1Syamt		ON fp.fileid = fc.fileid
1041.1Syamt	) d
1051.1Syamt	FULL JOIN file f
1061.1Syamt	ON d.fileid = f.fileid
1071.1Syamt	WHERE (d.nlink IS NULL AND (f.fileid <> 1 AND f.nlink <> 0))
1081.1Syamt	    OR f.nlink IS NULL
1091.1Syamt	    OR d.nlink <> f.nlink;
1101.1SyamtCOMMIT;
111