xref: /netbsd-src/share/examples/puffs/pgfs/check.sql (revision 49413e37758aefe75effb0f891d65c98cc944d13)
1-- $NetBSD: check.sql,v 1.1 2011/10/12 01:05:00 yamt Exp $
2
3-- Copyright (c)2010,2011 YAMAMOTO Takashi,
4-- All rights reserved.
5--
6-- Redistribution and use in source and binary forms, with or without
7-- modification, are permitted provided that the following conditions
8-- are met:
9-- 1. Redistributions of source code must retain the above copyright
10--    notice, this list of conditions and the following disclaimer.
11-- 2. Redistributions in binary form must reproduce the above copyright
12--    notice, this list of conditions and the following disclaimer in the
13--    documentation and/or other materials provided with the distribution.
14--
15-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18-- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25-- SUCH DAMAGE.
26
27-- filesystem consistency checks.  ie. something like "fsck -n"
28
29BEGIN;
30SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
31SET TRANSACTION READ ONLY;
32SET search_path TO pgfs;
33SELECT count(*) AS "unreferenced files (dirent)"
34	FROM file f LEFT JOIN dirent d
35	ON f.fileid = d.child_fileid
36	WHERE f.fileid <> 1 AND d.child_fileid IS NULL;
37SELECT count(*) AS "unreferenced files (nlink)"
38	FROM file f
39	WHERE f.nlink = 0;
40SELECT count(*) AS "regular files without datafork"
41	FROM file f LEFT JOIN datafork df
42	ON f.fileid = df.fileid
43	WHERE df.fileid IS NULL AND f.type IN ('regular', 'link');
44SELECT count(*) AS "broken datafork reference"
45	FROM file f INNER JOIN datafork df
46	ON f.fileid = df.fileid
47	WHERE f.type NOT IN ('regular', 'link');
48SELECT count(*) AS "unreferenced dataforks"
49	FROM file f RIGHT JOIN datafork df
50	ON f.fileid = df.fileid
51	WHERE f.fileid IS NULL;
52SELECT count(*) AS "dataforks without large object"
53	FROM datafork df LEFT JOIN pg_largeobject_metadata lm
54	ON df.loid = lm.oid
55	WHERE lm.oid IS NULL;
56SELECT count(*) AS "unreferenced large objects"
57	FROM datafork df RIGHT JOIN pg_largeobject_metadata lm
58	ON df.loid = lm.oid
59	WHERE df.loid IS NULL;
60SELECT count(*) AS "dirent broken parent_fileid references"
61	FROM dirent d LEFT JOIN file f
62	ON d.parent_fileid = f.fileid
63	WHERE f.fileid IS NULL OR f.type <> 'directory';
64SELECT count(*) AS "dirent broken child_fileid references"
65	FROM dirent d LEFT JOIN file f
66	ON d.child_fileid = f.fileid
67	WHERE f.fileid IS NULL;
68SELECT count(*) AS "dirent loops" FROM file f WHERE EXISTS (
69	WITH RECURSIVE r AS
70	(
71			SELECT d.* FROM dirent d
72				WHERE d.child_fileid = f.fileid
73		UNION ALL
74			SELECT d.* FROM dirent d INNER JOIN r
75				ON d.child_fileid = r.parent_fileid
76	)
77	SELECT * FROM r WHERE r.parent_fileid = f.fileid);
78SELECT count(*) AS "broken nlink"
79	FROM
80	(
81	SELECT coalesce(fp.fileid, fc.fileid) AS fileid,
82		coalesce(fp.nlink, 0) + coalesce(fc.nlink, 0) +
83		CASE
84			WHEN coalesce(fp.fileid, fc.fileid) = 1 THEN 1
85			ELSE 0
86		END
87		AS nlink
88		FROM
89		(
90		SELECT child_fileid AS fileid, count(*) AS nlink
91			FROM dirent
92			GROUP BY child_fileid
93		) fp
94		FULL JOIN
95		(
96		SELECT count(*) AS nlink, d.parent_fileid AS fileid
97			FROM dirent d
98			JOIN file f
99			ON d.child_fileid = f.fileid
100			WHERE f.type = 'directory'
101			GROUP BY parent_fileid
102		) fc
103		ON fp.fileid = fc.fileid
104	) d
105	FULL JOIN file f
106	ON d.fileid = f.fileid
107	WHERE (d.nlink IS NULL AND (f.fileid <> 1 AND f.nlink <> 0))
108	    OR f.nlink IS NULL
109	    OR d.nlink <> f.nlink;
110COMMIT;
111