1174604Sscottl/* SPDX-License-Identifier: GPL-2.0-or-later */
2174604Sscottl/*
3174604Sscottl *   Copyright (C) International Business Machines Corp., 2000-2002
4174604Sscottl *   Portions Copyright (C) Christoph Hellwig, 2001-2002
5174604Sscottl */
6174604Sscottl#ifndef	_H_JFS_METAPAGE
7174604Sscottl#define _H_JFS_METAPAGE
8174604Sscottl
9174604Sscottl#include <linux/pagemap.h>
10174604Sscottl
11174604Sscottlstruct metapage {
12174604Sscottl	/* Common logsyncblk prefix (see jfs_logmgr.h) */
13174604Sscottl	u16 xflag;
14174604Sscottl	u16 unused;
15174604Sscottl	lid_t lid;
16174604Sscottl	int lsn;
17174604Sscottl	struct list_head synclist;
18174604Sscottl	/* End of logsyncblk prefix */
19174604Sscottl
20174604Sscottl	unsigned long flag;	/* See Below */
21174604Sscottl	unsigned long count;	/* Reference count */
22174604Sscottl	void *data;		/* Data pointer */
23174604Sscottl	sector_t index;		/* block address of page */
24174604Sscottl	wait_queue_head_t wait;
25174604Sscottl
26174604Sscottl	/* implementation */
27174604Sscottl	struct page *page;
28174604Sscottl	struct super_block *sb;
29174604Sscottl	unsigned int logical_size;
30174604Sscottl
31174604Sscottl	/* Journal management */
32174604Sscottl	int clsn;
33174604Sscottl	int nohomeok;
34174604Sscottl	struct jfs_log *log;
35174604Sscottl};
36174604Sscottl
37174604Sscottl/* metapage flag */
38174604Sscottl#define META_locked	0
39174604Sscottl#define META_dirty	2
40174604Sscottl#define META_sync	3
41174604Sscottl#define META_discard	4
42174604Sscottl#define META_forcewrite	5
43174604Sscottl#define META_io		6
44174604Sscottl
45174604Sscottl#define mark_metapage_dirty(mp) set_bit(META_dirty, &(mp)->flag)
46174604Sscottl
47174604Sscottl/* function prototypes */
48174604Sscottlextern int metapage_init(void);
49174604Sscottlextern void metapage_exit(void);
50174604Sscottlextern struct metapage *__get_metapage(struct inode *inode,
51174604Sscottl				  unsigned long lblock, unsigned int size,
52174604Sscottl				  int absolute, unsigned long new);
53174604Sscottl
54174604Sscottl#define read_metapage(inode, lblock, size, absolute)\
55174604Sscottl	 __get_metapage(inode, lblock, size, absolute, false)
56174604Sscottl
57174604Sscottl#define get_metapage(inode, lblock, size, absolute)\
58174604Sscottl	 __get_metapage(inode, lblock, size, absolute, true)
59174604Sscottl
60174604Sscottlextern void release_metapage(struct metapage *);
61174604Sscottlextern void grab_metapage(struct metapage *);
62174604Sscottlextern void force_metapage(struct metapage *);
63174604Sscottl
64174604Sscottl/*
65174604Sscottl * hold_metapage and put_metapage are used in conjunction.  The page lock
66174604Sscottl * is not dropped between the two, so no other threads can get or release
67174604Sscottl * the metapage
68174604Sscottl */
69174604Sscottlextern void hold_metapage(struct metapage *);
70174604Sscottlextern void put_metapage(struct metapage *);
71174604Sscottl
72174604Sscottlstatic inline void write_metapage(struct metapage *mp)
73174604Sscottl{
74174604Sscottl	set_bit(META_dirty, &mp->flag);
75174604Sscottl	release_metapage(mp);
76174604Sscottl}
77174604Sscottl
78174604Sscottlstatic inline void flush_metapage(struct metapage *mp)
79174604Sscottl{
80174604Sscottl	set_bit(META_sync, &mp->flag);
81174604Sscottl	write_metapage(mp);
82174604Sscottl}
83174604Sscottl
84174604Sscottlstatic inline void discard_metapage(struct metapage *mp)
85174604Sscottl{
86174604Sscottl	clear_bit(META_dirty, &mp->flag);
87174604Sscottl	set_bit(META_discard, &mp->flag);
88174604Sscottl	release_metapage(mp);
89174604Sscottl}
90174604Sscottl
91174604Sscottlstatic inline void metapage_nohomeok(struct metapage *mp)
92174604Sscottl{
93174604Sscottl	struct page *page = mp->page;
94174604Sscottl	lock_page(page);
95174604Sscottl	if (!mp->nohomeok++) {
96174604Sscottl		mark_metapage_dirty(mp);
97174604Sscottl		get_page(page);
98174604Sscottl		wait_on_page_writeback(page);
99174604Sscottl	}
100174604Sscottl	unlock_page(page);
101174604Sscottl}
102174604Sscottl
103174604Sscottl/*
104174604Sscottl * This serializes access to mp->lsn when metapages are added to logsynclist
105174604Sscottl * without setting nohomeok.  i.e. updating imap & dmap
106174604Sscottl */
107174604Sscottlstatic inline void metapage_wait_for_io(struct metapage *mp)
108174604Sscottl{
109174604Sscottl	if (test_bit(META_io, &mp->flag))
110174604Sscottl		wait_on_page_writeback(mp->page);
111174604Sscottl}
112174604Sscottl
113174604Sscottl/*
114174604Sscottl * This is called when already holding the metapage
115174604Sscottl */
116174604Sscottlstatic inline void _metapage_homeok(struct metapage *mp)
117174604Sscottl{
118174604Sscottl	if (!--mp->nohomeok)
119174604Sscottl		put_page(mp->page);
120174604Sscottl}
121174604Sscottl
122174604Sscottlstatic inline void metapage_homeok(struct metapage *mp)
123174604Sscottl{
124174604Sscottl	hold_metapage(mp);
125174604Sscottl	_metapage_homeok(mp);
126174604Sscottl	put_metapage(mp);
127174604Sscottl}
128174604Sscottl
129174604Sscottlextern const struct address_space_operations jfs_metapage_aops;
130174604Sscottl
131174604Sscottl/*
132174604Sscottl * This routines invalidate all pages for an extent.
133174604Sscottl */
134174604Sscottlextern void __invalidate_metapages(struct inode *, s64, int);
135174604Sscottl#define invalidate_pxd_metapages(ip, pxd) \
136174604Sscottl	__invalidate_metapages((ip), addressPXD(&(pxd)), lengthPXD(&(pxd)))
137174604Sscottl#define invalidate_dxd_metapages(ip, dxd) \
138174604Sscottl	__invalidate_metapages((ip), addressDXD(&(dxd)), lengthDXD(&(dxd)))
139174604Sscottl#define invalidate_xad_metapages(ip, xad) \
140174604Sscottl	__invalidate_metapages((ip), addressXAD(&(xad)), lengthXAD(&(xad)))
141174604Sscottl
142174604Sscottl#endif				/* _H_JFS_METAPAGE */
143174604Sscottl