xref: /openbmc/linux/fs/btrfs/btrfs_inode.h (revision f2f121ab500d0457cc9c6f54269d21ffdf5bd304)
19888c340SDavid Sterba /* SPDX-License-Identifier: GPL-2.0 */
26cbd5570SChris Mason /*
36cbd5570SChris Mason  * Copyright (C) 2007 Oracle.  All rights reserved.
46cbd5570SChris Mason  */
56cbd5570SChris Mason 
69888c340SDavid Sterba #ifndef BTRFS_INODE_H
79888c340SDavid Sterba #define BTRFS_INODE_H
82c90e5d6SChris Mason 
9778ba82bSFilipe David Borba Manana #include <linux/hash.h>
10e3b318d1SOmar Sandoval #include <linux/refcount.h>
11a52d9a80SChris Mason #include "extent_map.h"
12d1310b2eSChris Mason #include "extent_io.h"
13e6dcd2dcSChris Mason #include "ordered-data.h"
1416cdcec7SMiao Xie #include "delayed-inode.h"
15a52d9a80SChris Mason 
1672ac3c0dSJosef Bacik /*
1772ac3c0dSJosef Bacik  * ordered_data_close is set by truncate when a file that used
1872ac3c0dSJosef Bacik  * to have good data has been truncated to zero.  When it is set
1972ac3c0dSJosef Bacik  * the btrfs file release call will add this inode to the
2072ac3c0dSJosef Bacik  * ordered operations list so that we make sure to flush out any
2172ac3c0dSJosef Bacik  * new data the application may have written before commit.
2272ac3c0dSJosef Bacik  */
237efc3e34SOmar Sandoval enum {
241fd4033dSNikolay Borisov 	BTRFS_INODE_FLUSH_ON_CLOSE,
257efc3e34SOmar Sandoval 	BTRFS_INODE_DUMMY,
267efc3e34SOmar Sandoval 	BTRFS_INODE_IN_DEFRAG,
277efc3e34SOmar Sandoval 	BTRFS_INODE_HAS_ASYNC_EXTENT,
2848778179SFilipe Manana 	 /*
2948778179SFilipe Manana 	  * Always set under the VFS' inode lock, otherwise it can cause races
3048778179SFilipe Manana 	  * during fsync (we start as a fast fsync and then end up in a full
3148778179SFilipe Manana 	  * fsync racing with ordered extent completion).
3248778179SFilipe Manana 	  */
337efc3e34SOmar Sandoval 	BTRFS_INODE_NEEDS_FULL_SYNC,
347efc3e34SOmar Sandoval 	BTRFS_INODE_COPY_EVERYTHING,
357efc3e34SOmar Sandoval 	BTRFS_INODE_IN_DELALLOC_LIST,
367efc3e34SOmar Sandoval 	BTRFS_INODE_HAS_PROPS,
373cd24c69SEthan Lien 	BTRFS_INODE_SNAPSHOT_FLUSH,
38*f2f121abSFilipe Manana 	/*
39*f2f121abSFilipe Manana 	 * Set and used when logging an inode and it serves to signal that an
40*f2f121abSFilipe Manana 	 * inode does not have xattrs, so subsequent fsyncs can avoid searching
41*f2f121abSFilipe Manana 	 * for xattrs to log. This bit must be cleared whenever a xattr is added
42*f2f121abSFilipe Manana 	 * to an inode.
43*f2f121abSFilipe Manana 	 */
44*f2f121abSFilipe Manana 	BTRFS_INODE_NO_XATTRS,
457efc3e34SOmar Sandoval };
4672ac3c0dSJosef Bacik 
47f1ace244SAneesh /* in memory btrfs inode */
482c90e5d6SChris Mason struct btrfs_inode {
49d352ac68SChris Mason 	/* which subvolume this inode belongs to */
50d6e4a428SChris Mason 	struct btrfs_root *root;
51d352ac68SChris Mason 
52d352ac68SChris Mason 	/* key used to find this inode on disk.  This is used by the code
53d352ac68SChris Mason 	 * to read in roots of subvolumes
54d352ac68SChris Mason 	 */
55d6e4a428SChris Mason 	struct btrfs_key location;
56d352ac68SChris Mason 
572f2ff0eeSFilipe Manana 	/*
582f2ff0eeSFilipe Manana 	 * Lock for counters and all fields used to determine if the inode is in
592f2ff0eeSFilipe Manana 	 * the log or not (last_trans, last_sub_trans, last_log_commit,
602766ff61SFilipe Manana 	 * logged_trans), to access/update new_delalloc_bytes and to update the
612766ff61SFilipe Manana 	 * VFS' inode number of bytes used.
622f2ff0eeSFilipe Manana 	 */
639e0baf60SJosef Bacik 	spinlock_t lock;
649e0baf60SJosef Bacik 
65d352ac68SChris Mason 	/* the extent_tree has caches of all the extent mappings to disk */
66a52d9a80SChris Mason 	struct extent_map_tree extent_tree;
67d352ac68SChris Mason 
68d352ac68SChris Mason 	/* the io_tree does range state (DIRTY, LOCKED etc) */
69d1310b2eSChris Mason 	struct extent_io_tree io_tree;
70d352ac68SChris Mason 
71d352ac68SChris Mason 	/* special utility tree used to record which mirrors have already been
72d352ac68SChris Mason 	 * tried when checksums fail for a given block
73d352ac68SChris Mason 	 */
747e38326fSChris Mason 	struct extent_io_tree io_failure_tree;
75d352ac68SChris Mason 
7641a2ee75SJosef Bacik 	/*
7741a2ee75SJosef Bacik 	 * Keep track of where the inode has extent items mapped in order to
7841a2ee75SJosef Bacik 	 * make sure the i_size adjustments are accurate
7941a2ee75SJosef Bacik 	 */
8041a2ee75SJosef Bacik 	struct extent_io_tree file_extent_tree;
8141a2ee75SJosef Bacik 
82d352ac68SChris Mason 	/* held while logging the inode in tree-log.c */
83e02119d5SChris Mason 	struct mutex log_mutex;
84d352ac68SChris Mason 
85d352ac68SChris Mason 	/* used to order data wrt metadata */
86e6dcd2dcSChris Mason 	struct btrfs_ordered_inode_tree ordered_tree;
8715ee9bc7SJosef Bacik 
88d352ac68SChris Mason 	/* list of all the delalloc inodes in the FS.  There are times we need
89d352ac68SChris Mason 	 * to write all the delalloc pages to disk, and this list is used
90d352ac68SChris Mason 	 * to walk them all.
91d352ac68SChris Mason 	 */
92ea8c2819SChris Mason 	struct list_head delalloc_inodes;
93ea8c2819SChris Mason 
945d4f98a2SYan Zheng 	/* node for the red-black tree that links inodes in subvolume root */
955d4f98a2SYan Zheng 	struct rb_node rb_node;
965d4f98a2SYan Zheng 
9772ac3c0dSJosef Bacik 	unsigned long runtime_flags;
9872ac3c0dSJosef Bacik 
999c931c5aSNathaniel Yazdani 	/* Keep track of who's O_SYNC/fsyncing currently */
100b812ce28SJosef Bacik 	atomic_t sync_writers;
101b812ce28SJosef Bacik 
102d352ac68SChris Mason 	/* full 64 bit generation number, struct vfs_inode doesn't have a big
103d352ac68SChris Mason 	 * enough field for this.
104d352ac68SChris Mason 	 */
105e02119d5SChris Mason 	u64 generation;
106e02119d5SChris Mason 
10715ee9bc7SJosef Bacik 	/*
10815ee9bc7SJosef Bacik 	 * transid of the trans_handle that last modified this inode
10915ee9bc7SJosef Bacik 	 */
11015ee9bc7SJosef Bacik 	u64 last_trans;
111257c62e1SChris Mason 
112257c62e1SChris Mason 	/*
113e02119d5SChris Mason 	 * transid that last logged this inode
114e02119d5SChris Mason 	 */
115e02119d5SChris Mason 	u64 logged_trans;
11649eb7e46SChris Mason 
117bb14a59bSMiao Xie 	/*
118bb14a59bSMiao Xie 	 * log transid when this inode was last modified
119bb14a59bSMiao Xie 	 */
120bb14a59bSMiao Xie 	int last_sub_trans;
121bb14a59bSMiao Xie 
122bb14a59bSMiao Xie 	/* a local copy of root's last_log_commit */
123bb14a59bSMiao Xie 	int last_log_commit;
124bb14a59bSMiao Xie 
125d352ac68SChris Mason 	/* total number of bytes pending delalloc, used by stat to calc the
126d352ac68SChris Mason 	 * real block usage of the file
127d352ac68SChris Mason 	 */
1289069218dSChris Mason 	u64 delalloc_bytes;
129d352ac68SChris Mason 
130d352ac68SChris Mason 	/*
131a7e3b975SFilipe Manana 	 * Total number of bytes pending delalloc that fall within a file
132a7e3b975SFilipe Manana 	 * range that is either a hole or beyond EOF (and no prealloc extent
133a7e3b975SFilipe Manana 	 * exists in the range). This is always <= delalloc_bytes.
134a7e3b975SFilipe Manana 	 */
135a7e3b975SFilipe Manana 	u64 new_delalloc_bytes;
136a7e3b975SFilipe Manana 
137a7e3b975SFilipe Manana 	/*
13847059d93SWang Shilong 	 * total number of bytes pending defrag, used by stat to check whether
13947059d93SWang Shilong 	 * it needs COW.
14047059d93SWang Shilong 	 */
14147059d93SWang Shilong 	u64 defrag_bytes;
14247059d93SWang Shilong 
14347059d93SWang Shilong 	/*
144d352ac68SChris Mason 	 * the size of the file stored in the metadata on disk.  data=ordered
145d352ac68SChris Mason 	 * means the in-memory i_size might be larger than the size on disk
146d352ac68SChris Mason 	 * because not all the blocks are written yet.
147d352ac68SChris Mason 	 */
148dbe674a9SChris Mason 	u64 disk_i_size;
149d352ac68SChris Mason 
150aec7477bSJosef Bacik 	/*
151aec7477bSJosef Bacik 	 * if this is a directory then index_cnt is the counter for the index
152aec7477bSJosef Bacik 	 * number for new files that are created
153aec7477bSJosef Bacik 	 */
154aec7477bSJosef Bacik 	u64 index_cnt;
155d352ac68SChris Mason 
15667de1176SMiao Xie 	/* Cache the directory index number to speed the dir/file remove */
15767de1176SMiao Xie 	u64 dir_index;
15867de1176SMiao Xie 
15912fcfd22SChris Mason 	/* the fsync log has some corner cases that mean we have to check
16012fcfd22SChris Mason 	 * directories to see if any unlinks have been done before
16112fcfd22SChris Mason 	 * the directory was logged.  See tree-log.c for all the
16212fcfd22SChris Mason 	 * details
16312fcfd22SChris Mason 	 */
16412fcfd22SChris Mason 	u64 last_unlink_trans;
16512fcfd22SChris Mason 
1667709cde3SJosef Bacik 	/*
1673ebac17cSFilipe Manana 	 * The id/generation of the last transaction where this inode was
1683ebac17cSFilipe Manana 	 * either the source or the destination of a clone/dedupe operation.
1693ebac17cSFilipe Manana 	 * Used when logging an inode to know if there are shared extents that
1703ebac17cSFilipe Manana 	 * need special care when logging checksum items, to avoid duplicate
1713ebac17cSFilipe Manana 	 * checksum items in a log (which can lead to a corruption where we end
1723ebac17cSFilipe Manana 	 * up with missing checksum ranges after log replay).
1733ebac17cSFilipe Manana 	 * Protected by the vfs inode lock.
1743ebac17cSFilipe Manana 	 */
1753ebac17cSFilipe Manana 	u64 last_reflink_trans;
1763ebac17cSFilipe Manana 
1773ebac17cSFilipe Manana 	/*
1787709cde3SJosef Bacik 	 * Number of bytes outstanding that are going to need csums.  This is
1797709cde3SJosef Bacik 	 * used in ENOSPC accounting.
1807709cde3SJosef Bacik 	 */
1817709cde3SJosef Bacik 	u64 csum_bytes;
1827709cde3SJosef Bacik 
183f1bdcc0aSJosef Bacik 	/* flags field from the on disk inode */
184f1bdcc0aSJosef Bacik 	u32 flags;
185f1bdcc0aSJosef Bacik 
1865a3f23d5SChris Mason 	/*
18732c00affSJosef Bacik 	 * Counters to keep track of the number of extent item's we may use due
18832c00affSJosef Bacik 	 * to delalloc and such.  outstanding_extents is the number of extent
18932c00affSJosef Bacik 	 * items we think we'll end up using, and reserved_extents is the number
19032c00affSJosef Bacik 	 * of extent items we've reserved metadata for.
1919ed74f2dSJosef Bacik 	 */
1929e0baf60SJosef Bacik 	unsigned outstanding_extents;
19369fe2d75SJosef Bacik 
19469fe2d75SJosef Bacik 	struct btrfs_block_rsv block_rsv;
1959ed74f2dSJosef Bacik 
1969ed74f2dSJosef Bacik 	/*
197b52aa8c9SDavid Sterba 	 * Cached values of inode properties
1981e701a32SChris Mason 	 */
199b52aa8c9SDavid Sterba 	unsigned prop_compress;		/* per-file compression algorithm */
200eec63c65SDavid Sterba 	/*
201eec63c65SDavid Sterba 	 * Force compression on the file using the defrag ioctl, could be
202eec63c65SDavid Sterba 	 * different from prop_compress and takes precedence if set
203eec63c65SDavid Sterba 	 */
204eec63c65SDavid Sterba 	unsigned defrag_compress;
2051e701a32SChris Mason 
20616cdcec7SMiao Xie 	struct btrfs_delayed_node *delayed_node;
20716cdcec7SMiao Xie 
2089cc97d64Schandan r 	/* File creation time. */
209d3c6be6fSArnd Bergmann 	struct timespec64 i_otime;
2109cc97d64Schandan r 
2118089fe62SDavid Sterba 	/* Hook into fs_info->delayed_iputs */
2128089fe62SDavid Sterba 	struct list_head delayed_iput;
2138089fe62SDavid Sterba 
214d352ac68SChris Mason 	struct inode vfs_inode;
2152c90e5d6SChris Mason };
216dbe674a9SChris Mason 
2176fee248dSNikolay Borisov static inline u32 btrfs_inode_sectorsize(const struct btrfs_inode *inode)
2186fee248dSNikolay Borisov {
2196fee248dSNikolay Borisov 	return inode->root->fs_info->sectorsize;
2206fee248dSNikolay Borisov }
2216fee248dSNikolay Borisov 
2229a35b637SJeff Mahoney static inline struct btrfs_inode *BTRFS_I(const struct inode *inode)
2232c90e5d6SChris Mason {
2242c90e5d6SChris Mason 	return container_of(inode, struct btrfs_inode, vfs_inode);
2252c90e5d6SChris Mason }
2262c90e5d6SChris Mason 
227778ba82bSFilipe David Borba Manana static inline unsigned long btrfs_inode_hash(u64 objectid,
228778ba82bSFilipe David Borba Manana 					     const struct btrfs_root *root)
229778ba82bSFilipe David Borba Manana {
2304fd786e6SMisono Tomohiro 	u64 h = objectid ^ (root->root_key.objectid * GOLDEN_RATIO_PRIME);
231778ba82bSFilipe David Borba Manana 
232778ba82bSFilipe David Borba Manana #if BITS_PER_LONG == 32
233778ba82bSFilipe David Borba Manana 	h = (h >> 32) ^ (h & 0xffffffff);
234778ba82bSFilipe David Borba Manana #endif
235778ba82bSFilipe David Borba Manana 
236778ba82bSFilipe David Borba Manana 	return (unsigned long)h;
237778ba82bSFilipe David Borba Manana }
238778ba82bSFilipe David Borba Manana 
239778ba82bSFilipe David Borba Manana static inline void btrfs_insert_inode_hash(struct inode *inode)
240778ba82bSFilipe David Borba Manana {
241778ba82bSFilipe David Borba Manana 	unsigned long h = btrfs_inode_hash(inode->i_ino, BTRFS_I(inode)->root);
242778ba82bSFilipe David Borba Manana 
243778ba82bSFilipe David Borba Manana 	__insert_inode_hash(inode, h);
244778ba82bSFilipe David Borba Manana }
245778ba82bSFilipe David Borba Manana 
2469a35b637SJeff Mahoney static inline u64 btrfs_ino(const struct btrfs_inode *inode)
24733345d01SLi Zefan {
2484a0cc7caSNikolay Borisov 	u64 ino = inode->location.objectid;
24933345d01SLi Zefan 
25014c7cca7SLiu Bo 	/*
25114c7cca7SLiu Bo 	 * !ino: btree_inode
25214c7cca7SLiu Bo 	 * type == BTRFS_ROOT_ITEM_KEY: subvol dir
25314c7cca7SLiu Bo 	 */
2544a0cc7caSNikolay Borisov 	if (!ino || inode->location.type == BTRFS_ROOT_ITEM_KEY)
2554a0cc7caSNikolay Borisov 		ino = inode->vfs_inode.i_ino;
25633345d01SLi Zefan 	return ino;
25733345d01SLi Zefan }
25833345d01SLi Zefan 
2596ef06d27SNikolay Borisov static inline void btrfs_i_size_write(struct btrfs_inode *inode, u64 size)
260dbe674a9SChris Mason {
2616ef06d27SNikolay Borisov 	i_size_write(&inode->vfs_inode, size);
2626ef06d27SNikolay Borisov 	inode->disk_i_size = size;
263dbe674a9SChris Mason }
264dbe674a9SChris Mason 
26570ddc553SNikolay Borisov static inline bool btrfs_is_free_space_inode(struct btrfs_inode *inode)
2662cf8572dSChris Mason {
26770ddc553SNikolay Borisov 	struct btrfs_root *root = inode->root;
26883eea1f1SLiu Bo 
26951a8cf9dSLiu Bo 	if (root == root->fs_info->tree_root &&
27070ddc553SNikolay Borisov 	    btrfs_ino(inode) != BTRFS_BTREE_INODE_OBJECTID)
27151a8cf9dSLiu Bo 		return true;
27270ddc553SNikolay Borisov 	if (inode->location.objectid == BTRFS_FREE_INO_OBJECTID)
2732cf8572dSChris Mason 		return true;
2742cf8572dSChris Mason 	return false;
2752cf8572dSChris Mason }
2762cf8572dSChris Mason 
27706f2548fSNikolay Borisov static inline bool is_data_inode(struct inode *inode)
27806f2548fSNikolay Borisov {
27906f2548fSNikolay Borisov 	return btrfs_ino(BTRFS_I(inode)) != BTRFS_BTREE_INODE_OBJECTID;
28006f2548fSNikolay Borisov }
28106f2548fSNikolay Borisov 
2828b62f87bSJosef Bacik static inline void btrfs_mod_outstanding_extents(struct btrfs_inode *inode,
2838b62f87bSJosef Bacik 						 int mod)
2848b62f87bSJosef Bacik {
2858b62f87bSJosef Bacik 	lockdep_assert_held(&inode->lock);
2868b62f87bSJosef Bacik 	inode->outstanding_extents += mod;
2878b62f87bSJosef Bacik 	if (btrfs_is_free_space_inode(inode))
2888b62f87bSJosef Bacik 		return;
289dd48d407SJosef Bacik 	trace_btrfs_inode_mod_outstanding_extents(inode->root, btrfs_ino(inode),
290dd48d407SJosef Bacik 						  mod);
2918b62f87bSJosef Bacik }
2928b62f87bSJosef Bacik 
2930f8939b8SNikolay Borisov static inline int btrfs_inode_in_log(struct btrfs_inode *inode, u64 generation)
29422ee6985SJosef Bacik {
2952f2ff0eeSFilipe Manana 	int ret = 0;
2962f2ff0eeSFilipe Manana 
2970f8939b8SNikolay Borisov 	spin_lock(&inode->lock);
2980f8939b8SNikolay Borisov 	if (inode->logged_trans == generation &&
2990f8939b8SNikolay Borisov 	    inode->last_sub_trans <= inode->last_log_commit &&
3000f8939b8SNikolay Borisov 	    inode->last_sub_trans <= inode->root->last_log_commit) {
301125c4cf9SFilipe Manana 		/*
302125c4cf9SFilipe Manana 		 * After a ranged fsync we might have left some extent maps
303125c4cf9SFilipe Manana 		 * (that fall outside the fsync's range). So return false
304125c4cf9SFilipe Manana 		 * here if the list isn't empty, to make sure btrfs_log_inode()
305125c4cf9SFilipe Manana 		 * will be called and process those extent maps.
306125c4cf9SFilipe Manana 		 */
307125c4cf9SFilipe Manana 		smp_mb();
3080f8939b8SNikolay Borisov 		if (list_empty(&inode->extent_tree.modified_extents))
3092f2ff0eeSFilipe Manana 			ret = 1;
310125c4cf9SFilipe Manana 	}
3110f8939b8SNikolay Borisov 	spin_unlock(&inode->lock);
3122f2ff0eeSFilipe Manana 	return ret;
31322ee6985SJosef Bacik }
31422ee6985SJosef Bacik 
315facc8a22SMiao Xie struct btrfs_dio_private {
316facc8a22SMiao Xie 	struct inode *inode;
317facc8a22SMiao Xie 	u64 logical_offset;
318facc8a22SMiao Xie 	u64 disk_bytenr;
319facc8a22SMiao Xie 	u64 bytes;
320facc8a22SMiao Xie 
321e3b318d1SOmar Sandoval 	/*
322e3b318d1SOmar Sandoval 	 * References to this structure. There is one reference per in-flight
323e3b318d1SOmar Sandoval 	 * bio plus one while we're still setting up.
324e3b318d1SOmar Sandoval 	 */
325e3b318d1SOmar Sandoval 	refcount_t refs;
326facc8a22SMiao Xie 
327facc8a22SMiao Xie 	/* dio_bio came from fs/direct-io.c */
328facc8a22SMiao Xie 	struct bio *dio_bio;
329c1dc0896SMiao Xie 
33085879573SOmar Sandoval 	/* Array of checksums */
33185879573SOmar Sandoval 	u8 csums[];
332facc8a22SMiao Xie };
333facc8a22SMiao Xie 
3347ebc7e5fSJohannes Thumshirn /* Array of bytes with variable length, hexadecimal format 0x1234 */
3357ebc7e5fSJohannes Thumshirn #define CSUM_FMT				"0x%*phN"
3367ebc7e5fSJohannes Thumshirn #define CSUM_FMT_VALUE(size, bytes)		size, bytes
3377ebc7e5fSJohannes Thumshirn 
3380970a22eSNikolay Borisov static inline void btrfs_print_data_csum_error(struct btrfs_inode *inode,
339ea41d6b2SJohannes Thumshirn 		u64 logical_start, u8 *csum, u8 *csum_expected, int mirror_num)
3406f6b643eSQu Wenruo {
3410970a22eSNikolay Borisov 	struct btrfs_root *root = inode->root;
342223486c2SDavid Sterba 	const u32 csum_size = root->fs_info->csum_size;
3436f6b643eSQu Wenruo 
3446f6b643eSQu Wenruo 	/* Output minus objectid, which is more meaningful */
3454fd786e6SMisono Tomohiro 	if (root->root_key.objectid >= BTRFS_LAST_FREE_OBJECTID)
3466f6b643eSQu Wenruo 		btrfs_warn_rl(root->fs_info,
3477ebc7e5fSJohannes Thumshirn "csum failed root %lld ino %lld off %llu csum " CSUM_FMT " expected csum " CSUM_FMT " mirror %d",
3484fd786e6SMisono Tomohiro 			root->root_key.objectid, btrfs_ino(inode),
3497ebc7e5fSJohannes Thumshirn 			logical_start,
350ea41d6b2SJohannes Thumshirn 			CSUM_FMT_VALUE(csum_size, csum),
351ea41d6b2SJohannes Thumshirn 			CSUM_FMT_VALUE(csum_size, csum_expected),
3527ebc7e5fSJohannes Thumshirn 			mirror_num);
3536f6b643eSQu Wenruo 	else
3546f6b643eSQu Wenruo 		btrfs_warn_rl(root->fs_info,
3557ebc7e5fSJohannes Thumshirn "csum failed root %llu ino %llu off %llu csum " CSUM_FMT " expected csum " CSUM_FMT " mirror %d",
3564fd786e6SMisono Tomohiro 			root->root_key.objectid, btrfs_ino(inode),
3577ebc7e5fSJohannes Thumshirn 			logical_start,
358ea41d6b2SJohannes Thumshirn 			CSUM_FMT_VALUE(csum_size, csum),
359ea41d6b2SJohannes Thumshirn 			CSUM_FMT_VALUE(csum_size, csum_expected),
3607ebc7e5fSJohannes Thumshirn 			mirror_num);
3616f6b643eSQu Wenruo }
3626f6b643eSQu Wenruo 
3632c90e5d6SChris Mason #endif
364