VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   32 Branches   54 Tags
b24413180f560 (Greg Kroah-Hartman 2017-11-01 15:07:57 +0100   1) // SPDX-License-Identifier: GPL-2.0
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   2) /*
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   3)  *  linux/fs/hfsplus/bnode.c
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   4)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   5)  * Copyright (C) 2001
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   6)  * Brad Boyer (flar@allandria.com)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   7)  * (C) 2003 Ardis Technologies <roman@ardistech.com>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   8)  *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700   9)  * Handle basic btree node operations
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  10)  */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  11) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  12) #include <linux/string.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  13) #include <linux/slab.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  14) #include <linux/pagemap.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  15) #include <linux/fs.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  16) #include <linux/swap.h>
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  17) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  18) #include "hfsplus_fs.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  19) #include "hfsplus_raw.h"
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  20) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  21) /* Copy a specified range of bytes from the raw data of a node */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  22) void hfs_bnode_read(struct hfs_bnode *node, void *buf, int off, int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  23) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  24) 	struct page **pagep;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  25) 	int l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  26) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  27) 	off += node->page_offset;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  28) 	pagep = node->page + (off >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  29) 	off &= ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  30) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  31) 	l = min_t(int, len, PAGE_SIZE - off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  32) 	memcpy(buf, kmap(*pagep) + off, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  33) 	kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  34) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  35) 	while ((len -= l) != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  36) 		buf += l;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  37) 		l = min_t(int, len, PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  38) 		memcpy(buf, kmap(*++pagep), l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  39) 		kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  40) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  41) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  42) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  43) u16 hfs_bnode_read_u16(struct hfs_bnode *node, int off)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  44) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  45) 	__be16 data;
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200  46) 	/* TODO: optimize later... */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  47) 	hfs_bnode_read(node, &data, off, 2);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  48) 	return be16_to_cpu(data);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  49) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  50) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  51) u8 hfs_bnode_read_u8(struct hfs_bnode *node, int off)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  52) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  53) 	u8 data;
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200  54) 	/* TODO: optimize later... */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  55) 	hfs_bnode_read(node, &data, off, 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  56) 	return data;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  57) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  58) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  59) void hfs_bnode_read_key(struct hfs_bnode *node, void *key, int off)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  60) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  61) 	struct hfs_btree *tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  62) 	int key_len;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  63) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  64) 	tree = node->tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  65) 	if (node->type == HFS_NODE_LEAF ||
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800  66) 	    tree->attributes & HFS_TREE_VARIDXKEYS ||
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800  67) 	    node->tree->cnid == HFSPLUS_ATTR_CNID)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  68) 		key_len = hfs_bnode_read_u16(node, off) + 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  69) 	else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  70) 		key_len = tree->max_key_len + 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  71) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  72) 	hfs_bnode_read(node, key, off, key_len);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  73) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  74) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  75) void hfs_bnode_write(struct hfs_bnode *node, void *buf, int off, int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  76) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  77) 	struct page **pagep;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  78) 	int l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  79) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  80) 	off += node->page_offset;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  81) 	pagep = node->page + (off >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  82) 	off &= ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  83) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  84) 	l = min_t(int, len, PAGE_SIZE - off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  85) 	memcpy(kmap(*pagep) + off, buf, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  86) 	set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  87) 	kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  88) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  89) 	while ((len -= l) != 0) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  90) 		buf += l;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300  91) 		l = min_t(int, len, PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  92) 		memcpy(kmap(*++pagep), buf, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  93) 		set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  94) 		kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  95) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  96) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  97) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  98) void hfs_bnode_write_u16(struct hfs_bnode *node, int off, u16 data)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700  99) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 100) 	__be16 v = cpu_to_be16(data);
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200 101) 	/* TODO: optimize later... */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 102) 	hfs_bnode_write(node, &v, off, 2);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 103) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 104) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 105) void hfs_bnode_clear(struct hfs_bnode *node, int off, int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 106) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 107) 	struct page **pagep;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 108) 	int l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 109) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 110) 	off += node->page_offset;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 111) 	pagep = node->page + (off >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 112) 	off &= ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 113) 
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 114) 	l = min_t(int, len, PAGE_SIZE - off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 115) 	memset(kmap(*pagep) + off, 0, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 116) 	set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 117) 	kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 118) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 119) 	while ((len -= l) != 0) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 120) 		l = min_t(int, len, PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 121) 		memset(kmap(*++pagep), 0, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 122) 		set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 123) 		kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 124) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 125) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 126) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 127) void hfs_bnode_copy(struct hfs_bnode *dst_node, int dst,
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 128) 		    struct hfs_bnode *src_node, int src, int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 129) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 130) 	struct page **src_page, **dst_page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 131) 	int l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 132) 
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 133) 	hfs_dbg(BNODE_MOD, "copybytes: %u,%u,%u\n", dst, src, len);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 134) 	if (!len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 135) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 136) 	src += src_node->page_offset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 137) 	dst += dst_node->page_offset;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 138) 	src_page = src_node->page + (src >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 139) 	src &= ~PAGE_MASK;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 140) 	dst_page = dst_node->page + (dst >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 141) 	dst &= ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 142) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 143) 	if (src == dst) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 144) 		l = min_t(int, len, PAGE_SIZE - src);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 145) 		memcpy(kmap(*dst_page) + src, kmap(*src_page) + src, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 146) 		kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 147) 		set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 148) 		kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 149) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 150) 		while ((len -= l) != 0) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 151) 			l = min_t(int, len, PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 152) 			memcpy(kmap(*++dst_page), kmap(*++src_page), l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 153) 			kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 154) 			set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 155) 			kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 156) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 157) 	} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 158) 		void *src_ptr, *dst_ptr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 159) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 160) 		do {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 161) 			src_ptr = kmap(*src_page) + src;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 162) 			dst_ptr = kmap(*dst_page) + dst;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 163) 			if (PAGE_SIZE - src < PAGE_SIZE - dst) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 164) 				l = PAGE_SIZE - src;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 165) 				src = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 166) 				dst += l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 167) 			} else {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 168) 				l = PAGE_SIZE - dst;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 169) 				src += l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 170) 				dst = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 171) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 172) 			l = min(len, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 173) 			memcpy(dst_ptr, src_ptr, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 174) 			kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 175) 			set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 176) 			kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 177) 			if (!dst)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 178) 				dst_page++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 179) 			else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 180) 				src_page++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 181) 		} while ((len -= l));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 182) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 183) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 184) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 185) void hfs_bnode_move(struct hfs_bnode *node, int dst, int src, int len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 186) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 187) 	struct page **src_page, **dst_page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 188) 	int l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 189) 
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 190) 	hfs_dbg(BNODE_MOD, "movebytes: %u,%u,%u\n", dst, src, len);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 191) 	if (!len)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 192) 		return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 193) 	src += node->page_offset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 194) 	dst += node->page_offset;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 195) 	if (dst > src) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 196) 		src += len - 1;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 197) 		src_page = node->page + (src >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 198) 		src = (src & ~PAGE_MASK) + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 199) 		dst += len - 1;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 200) 		dst_page = node->page + (dst >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 201) 		dst = (dst & ~PAGE_MASK) + 1;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 202) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 203) 		if (src == dst) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 204) 			while (src < len) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 205) 				memmove(kmap(*dst_page), kmap(*src_page), src);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 206) 				kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 207) 				set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 208) 				kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 209) 				len -= src;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 210) 				src = PAGE_SIZE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 211) 				src_page--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 212) 				dst_page--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 213) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 214) 			src -= len;
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 215) 			memmove(kmap(*dst_page) + src,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 216) 				kmap(*src_page) + src, len);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 217) 			kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 218) 			set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 219) 			kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 220) 		} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 221) 			void *src_ptr, *dst_ptr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 222) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 223) 			do {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 224) 				src_ptr = kmap(*src_page) + src;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 225) 				dst_ptr = kmap(*dst_page) + dst;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 226) 				if (src < dst) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 227) 					l = src;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 228) 					src = PAGE_SIZE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 229) 					dst -= l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 230) 				} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 231) 					l = dst;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 232) 					src -= l;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 233) 					dst = PAGE_SIZE;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 234) 				}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 235) 				l = min(len, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 236) 				memmove(dst_ptr - l, src_ptr - l, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 237) 				kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 238) 				set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 239) 				kunmap(*dst_page);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 240) 				if (dst == PAGE_SIZE)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 241) 					dst_page--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 242) 				else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 243) 					src_page--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 244) 			} while ((len -= l));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 245) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 246) 	} else {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 247) 		src_page = node->page + (src >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 248) 		src &= ~PAGE_MASK;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 249) 		dst_page = node->page + (dst >> PAGE_SHIFT);
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 250) 		dst &= ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 251) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 252) 		if (src == dst) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 253) 			l = min_t(int, len, PAGE_SIZE - src);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 254) 			memmove(kmap(*dst_page) + src,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 255) 				kmap(*src_page) + src, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 256) 			kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 257) 			set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 258) 			kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 259) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 260) 			while ((len -= l) != 0) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 261) 				l = min_t(int, len, PAGE_SIZE);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 262) 				memmove(kmap(*++dst_page),
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 263) 					kmap(*++src_page), l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 264) 				kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 265) 				set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 266) 				kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 267) 			}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 268) 		} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 269) 			void *src_ptr, *dst_ptr;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 270) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 271) 			do {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 272) 				src_ptr = kmap(*src_page) + src;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 273) 				dst_ptr = kmap(*dst_page) + dst;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 274) 				if (PAGE_SIZE - src <
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 275) 						PAGE_SIZE - dst) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 276) 					l = PAGE_SIZE - src;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 277) 					src = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 278) 					dst += l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 279) 				} else {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 280) 					l = PAGE_SIZE - dst;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 281) 					src += l;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 282) 					dst = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 283) 				}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 284) 				l = min(len, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 285) 				memmove(dst_ptr, src_ptr, l);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 286) 				kunmap(*src_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 287) 				set_page_dirty(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 288) 				kunmap(*dst_page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 289) 				if (!dst)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 290) 					dst_page++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 291) 				else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 292) 					src_page++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 293) 			} while ((len -= l));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 294) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 295) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 296) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 297) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 298) void hfs_bnode_dump(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 299) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 300) 	struct hfs_bnode_desc desc;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 301) 	__be32 cnid;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 302) 	int i, off, key_off;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 303) 
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 304) 	hfs_dbg(BNODE_MOD, "bnode: %d\n", node->this);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 305) 	hfs_bnode_read(node, &desc, 0, sizeof(desc));
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 306) 	hfs_dbg(BNODE_MOD, "%d, %d, %d, %d, %d\n",
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 307) 		be32_to_cpu(desc.next), be32_to_cpu(desc.prev),
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 308) 		desc.type, desc.height, be16_to_cpu(desc.num_recs));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 309) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 310) 	off = node->tree->node_size - 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 311) 	for (i = be16_to_cpu(desc.num_recs); i >= 0; off -= 2, i--) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 312) 		key_off = hfs_bnode_read_u16(node, off);
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 313) 		hfs_dbg(BNODE_MOD, " %d", key_off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 314) 		if (i && node->type == HFS_NODE_INDEX) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 315) 			int tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 316) 
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 317) 			if (node->tree->attributes & HFS_TREE_VARIDXKEYS ||
324ef39a8a4f6 (Vyacheslav Dubeyko 2013-02-27 17:03:04 -0800 318) 					node->tree->cnid == HFSPLUS_ATTR_CNID)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 319) 				tmp = hfs_bnode_read_u16(node, key_off) + 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 320) 			else
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 321) 				tmp = node->tree->max_key_len + 2;
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 322) 			hfs_dbg_cont(BNODE_MOD, " (%d", tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 323) 			hfs_bnode_read(node, &cnid, key_off + tmp, 4);
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 324) 			hfs_dbg_cont(BNODE_MOD, ",%d)", be32_to_cpu(cnid));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 325) 		} else if (i && node->type == HFS_NODE_LEAF) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 326) 			int tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 327) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 328) 			tmp = hfs_bnode_read_u16(node, key_off);
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 329) 			hfs_dbg_cont(BNODE_MOD, " (%d)", tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 330) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 331) 	}
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 332) 	hfs_dbg_cont(BNODE_MOD, "\n");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 333) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 334) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 335) void hfs_bnode_unlink(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 336) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 337) 	struct hfs_btree *tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 338) 	struct hfs_bnode *tmp;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 339) 	__be32 cnid;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 340) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 341) 	tree = node->tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 342) 	if (node->prev) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 343) 		tmp = hfs_bnode_find(tree, node->prev);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 344) 		if (IS_ERR(tmp))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 345) 			return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 346) 		tmp->next = node->next;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 347) 		cnid = cpu_to_be32(tmp->next);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 348) 		hfs_bnode_write(tmp, &cnid,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 349) 			offsetof(struct hfs_bnode_desc, next), 4);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 350) 		hfs_bnode_put(tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 351) 	} else if (node->type == HFS_NODE_LEAF)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 352) 		tree->leaf_head = node->next;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 353) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 354) 	if (node->next) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 355) 		tmp = hfs_bnode_find(tree, node->next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 356) 		if (IS_ERR(tmp))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 357) 			return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 358) 		tmp->prev = node->prev;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 359) 		cnid = cpu_to_be32(tmp->prev);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 360) 		hfs_bnode_write(tmp, &cnid,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 361) 			offsetof(struct hfs_bnode_desc, prev), 4);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 362) 		hfs_bnode_put(tmp);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 363) 	} else if (node->type == HFS_NODE_LEAF)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 364) 		tree->leaf_tail = node->prev;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 365) 
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200 366) 	/* move down? */
b2837fcf4994e (Anton Salikhmetov  2010-12-16 18:08:41 +0200 367) 	if (!node->prev && !node->next)
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 368) 		hfs_dbg(BNODE_MOD, "hfs_btree_del_level\n");
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 369) 	if (!node->parent) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 370) 		tree->root = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 371) 		tree->depth = 0;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 372) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 373) 	set_bit(HFS_BNODE_DELETED, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 374) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 375) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 376) static inline int hfs_bnode_hash(u32 num)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 377) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 378) 	num = (num >> 16) + num;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 379) 	num += num >> 8;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 380) 	return num & (NODE_HASH_SIZE - 1);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 381) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 382) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 383) struct hfs_bnode *hfs_bnode_findhash(struct hfs_btree *tree, u32 cnid)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 384) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 385) 	struct hfs_bnode *node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 386) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 387) 	if (cnid >= tree->node_count) {
e46707d153318 (Fabian Frederick   2014-06-06 14:36:25 -0700 388) 		pr_err("request for non-existent node %d in B*Tree\n",
e46707d153318 (Fabian Frederick   2014-06-06 14:36:25 -0700 389) 		       cnid);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 390) 		return NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 391) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 392) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 393) 	for (node = tree->node_hash[hfs_bnode_hash(cnid)];
b2837fcf4994e (Anton Salikhmetov  2010-12-16 18:08:41 +0200 394) 			node; node = node->next_hash)
b2837fcf4994e (Anton Salikhmetov  2010-12-16 18:08:41 +0200 395) 		if (node->this == cnid)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 396) 			return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 397) 	return NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 398) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 399) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 400) static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 401) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 402) 	struct hfs_bnode *node, *node2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 403) 	struct address_space *mapping;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 404) 	struct page *page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 405) 	int size, block, i, hash;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 406) 	loff_t off;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 407) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 408) 	if (cnid >= tree->node_count) {
e46707d153318 (Fabian Frederick   2014-06-06 14:36:25 -0700 409) 		pr_err("request for non-existent node %d in B*Tree\n",
e46707d153318 (Fabian Frederick   2014-06-06 14:36:25 -0700 410) 		       cnid);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 411) 		return NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 412) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 413) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 414) 	size = sizeof(struct hfs_bnode) + tree->pages_per_bnode *
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 415) 		sizeof(struct page *);
f8314dc60ccba (Panagiotis Issaris 2006-09-27 01:49:37 -0700 416) 	node = kzalloc(size, GFP_KERNEL);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 417) 	if (!node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 418) 		return NULL;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 419) 	node->tree = tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 420) 	node->this = cnid;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 421) 	set_bit(HFS_BNODE_NEW, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 422) 	atomic_set(&node->refcnt, 1);
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 423) 	hfs_dbg(BNODE_REFS, "new_node(%d:%d): 1\n",
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 424) 		node->tree->cnid, node->this);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 425) 	init_waitqueue_head(&node->lock_wq);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 426) 	spin_lock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 427) 	node2 = hfs_bnode_findhash(tree, cnid);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 428) 	if (!node2) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 429) 		hash = hfs_bnode_hash(cnid);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 430) 		node->next_hash = tree->node_hash[hash];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 431) 		tree->node_hash[hash] = node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 432) 		tree->node_hash_cnt++;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 433) 	} else {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 434) 		spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 435) 		kfree(node);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 436) 		wait_event(node2->lock_wq,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 437) 			!test_bit(HFS_BNODE_NEW, &node2->flags));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 438) 		return node2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 439) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 440) 	spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 441) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 442) 	mapping = tree->inode->i_mapping;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 443) 	off = (loff_t)cnid << tree->node_size_shift;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 444) 	block = off >> PAGE_SHIFT;
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 445) 	node->page_offset = off & ~PAGE_MASK;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 446) 	for (i = 0; i < tree->pages_per_bnode; block++, i++) {
090d2b185d868 (Pekka Enberg       2006-06-23 02:05:08 -0700 447) 		page = read_mapping_page(mapping, block, NULL);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 448) 		if (IS_ERR(page))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 449) 			goto fail;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 450) 		if (PageError(page)) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 451) 			put_page(page);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 452) 			goto fail;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 453) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 454) 		node->page[i] = page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 455) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 456) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 457) 	return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 458) fail:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 459) 	set_bit(HFS_BNODE_ERROR, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 460) 	return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 461) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 462) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 463) void hfs_bnode_unhash(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 464) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 465) 	struct hfs_bnode **p;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 466) 
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 467) 	hfs_dbg(BNODE_REFS, "remove_node(%d:%d): %d\n",
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 468) 		node->tree->cnid, node->this, atomic_read(&node->refcnt));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 469) 	for (p = &node->tree->node_hash[hfs_bnode_hash(node->this)];
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 470) 	     *p && *p != node; p = &(*p)->next_hash)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 471) 		;
0bf3ba538a150 (Eric Sesterhenn    2006-04-01 01:14:43 +0200 472) 	BUG_ON(!*p);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 473) 	*p = node->next_hash;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 474) 	node->tree->node_hash_cnt--;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 475) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 476) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 477) /* Load a particular node out of a tree */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 478) struct hfs_bnode *hfs_bnode_find(struct hfs_btree *tree, u32 num)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 479) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 480) 	struct hfs_bnode *node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 481) 	struct hfs_bnode_desc *desc;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 482) 	int i, rec_off, off, next_off;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 483) 	int entry_size, key_size;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 484) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 485) 	spin_lock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 486) 	node = hfs_bnode_findhash(tree, num);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 487) 	if (node) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 488) 		hfs_bnode_get(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 489) 		spin_unlock(&tree->hash_lock);
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 490) 		wait_event(node->lock_wq,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 491) 			!test_bit(HFS_BNODE_NEW, &node->flags));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 492) 		if (test_bit(HFS_BNODE_ERROR, &node->flags))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 493) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 494) 		return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 495) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 496) 	spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 497) 	node = __hfs_bnode_create(tree, num);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 498) 	if (!node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 499) 		return ERR_PTR(-ENOMEM);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 500) 	if (test_bit(HFS_BNODE_ERROR, &node->flags))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 501) 		goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 502) 	if (!test_bit(HFS_BNODE_NEW, &node->flags))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 503) 		return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 504) 
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 505) 	desc = (struct hfs_bnode_desc *)(kmap(node->page[0]) +
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 506) 			node->page_offset);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 507) 	node->prev = be32_to_cpu(desc->prev);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 508) 	node->next = be32_to_cpu(desc->next);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 509) 	node->num_recs = be16_to_cpu(desc->num_recs);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 510) 	node->type = desc->type;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 511) 	node->height = desc->height;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 512) 	kunmap(node->page[0]);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 513) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 514) 	switch (node->type) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 515) 	case HFS_NODE_HEADER:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 516) 	case HFS_NODE_MAP:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 517) 		if (node->height != 0)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 518) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 519) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 520) 	case HFS_NODE_LEAF:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 521) 		if (node->height != 1)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 522) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 523) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 524) 	case HFS_NODE_INDEX:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 525) 		if (node->height <= 1 || node->height > tree->depth)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 526) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 527) 		break;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 528) 	default:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 529) 		goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 530) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 531) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 532) 	rec_off = tree->node_size - 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 533) 	off = hfs_bnode_read_u16(node, rec_off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 534) 	if (off != sizeof(struct hfs_bnode_desc))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 535) 		goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 536) 	for (i = 1; i <= node->num_recs; off = next_off, i++) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 537) 		rec_off -= 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 538) 		next_off = hfs_bnode_read_u16(node, rec_off);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 539) 		if (next_off <= off ||
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 540) 		    next_off > tree->node_size ||
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 541) 		    next_off & 1)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 542) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 543) 		entry_size = next_off - off;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 544) 		if (node->type != HFS_NODE_INDEX &&
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 545) 		    node->type != HFS_NODE_LEAF)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 546) 			continue;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 547) 		key_size = hfs_bnode_read_u16(node, off) + 2;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 548) 		if (key_size >= entry_size || key_size & 1)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 549) 			goto node_error;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 550) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 551) 	clear_bit(HFS_BNODE_NEW, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 552) 	wake_up(&node->lock_wq);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 553) 	return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 554) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 555) node_error:
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 556) 	set_bit(HFS_BNODE_ERROR, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 557) 	clear_bit(HFS_BNODE_NEW, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 558) 	wake_up(&node->lock_wq);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 559) 	hfs_bnode_put(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 560) 	return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 561) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 562) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 563) void hfs_bnode_free(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 564) {
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200 565) 	int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 566) 
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200 567) 	for (i = 0; i < node->tree->pages_per_bnode; i++)
21f2296a598c4 (Anton Salikhmetov  2010-12-16 18:08:39 +0200 568) 		if (node->page[i])
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 569) 			put_page(node->page[i]);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 570) 	kfree(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 571) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 572) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 573) struct hfs_bnode *hfs_bnode_create(struct hfs_btree *tree, u32 num)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 574) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 575) 	struct hfs_bnode *node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 576) 	struct page **pagep;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 577) 	int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 578) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 579) 	spin_lock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 580) 	node = hfs_bnode_findhash(tree, num);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 581) 	spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 582) 	if (node) {
d614267329f2b (Joe Perches        2013-04-30 15:27:55 -0700 583) 		pr_crit("new node %u already hashed?\n", num);
634725a92938b (Roman Zippel       2006-01-18 17:43:05 -0800 584) 		WARN_ON(1);
634725a92938b (Roman Zippel       2006-01-18 17:43:05 -0800 585) 		return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 586) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 587) 	node = __hfs_bnode_create(tree, num);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 588) 	if (!node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 589) 		return ERR_PTR(-ENOMEM);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 590) 	if (test_bit(HFS_BNODE_ERROR, &node->flags)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 591) 		hfs_bnode_put(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 592) 		return ERR_PTR(-EIO);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 593) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 594) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 595) 	pagep = node->page;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 596) 	memset(kmap(*pagep) + node->page_offset, 0,
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 597) 	       min_t(int, PAGE_SIZE, tree->node_size));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 598) 	set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 599) 	kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 600) 	for (i = 1; i < tree->pages_per_bnode; i++) {
09cbfeaf1a5a6 (Kirill A. Shutemov 2016-04-01 15:29:47 +0300 601) 		memset(kmap(*++pagep), 0, PAGE_SIZE);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 602) 		set_page_dirty(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 603) 		kunmap(*pagep);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 604) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 605) 	clear_bit(HFS_BNODE_NEW, &node->flags);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 606) 	wake_up(&node->lock_wq);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 607) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 608) 	return node;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 609) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 610) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 611) void hfs_bnode_get(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 612) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 613) 	if (node) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 614) 		atomic_inc(&node->refcnt);
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 615) 		hfs_dbg(BNODE_REFS, "get_node(%d:%d): %d\n",
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 616) 			node->tree->cnid, node->this,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 617) 			atomic_read(&node->refcnt));
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 618) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 619) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 620) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 621) /* Dispose of resources used by a node */
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 622) void hfs_bnode_put(struct hfs_bnode *node)
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 623) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 624) 	if (node) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 625) 		struct hfs_btree *tree = node->tree;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 626) 		int i;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 627) 
c2b3e1f76e5c9 (Joe Perches        2013-04-30 15:27:54 -0700 628) 		hfs_dbg(BNODE_REFS, "put_node(%d:%d): %d\n",
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 629) 			node->tree->cnid, node->this,
2753cc281c9a0 (Anton Salikhmetov  2010-12-16 18:08:38 +0200 630) 			atomic_read(&node->refcnt));
0bf3ba538a150 (Eric Sesterhenn    2006-04-01 01:14:43 +0200 631) 		BUG_ON(!atomic_read(&node->refcnt));
a5e3985fa0140 (Roman Zippel       2005-09-06 15:18:47 -0700 632) 		if (!atomic_dec_and_lock(&node->refcnt, &tree->hash_lock))
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 633) 			return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 634) 		for (i = 0; i < tree->pages_per_bnode; i++) {
74f9c9c258249 (Roman Zippel       2005-08-01 21:11:41 -0700 635) 			if (!node->page[i])
74f9c9c258249 (Roman Zippel       2005-08-01 21:11:41 -0700 636) 				continue;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 637) 			mark_page_accessed(node->page[i]);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 638) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 639) 
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 640) 		if (test_bit(HFS_BNODE_DELETED, &node->flags)) {
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 641) 			hfs_bnode_unhash(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 642) 			spin_unlock(&tree->hash_lock);
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 643) 			if (hfs_bnode_need_zeroout(tree))
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 644) 				hfs_bnode_clear(node, 0, tree->node_size);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 645) 			hfs_bmap_free(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 646) 			hfs_bnode_free(node);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 647) 			return;
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 648) 		}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 649) 		spin_unlock(&tree->hash_lock);
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 650) 	}
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 651) }
^1da177e4c3f4 (Linus Torvalds     2005-04-16 15:20:36 -0700 652) 
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 653) /*
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 654)  * Unused nodes have to be zeroed if this is the catalog tree and
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 655)  * a corresponding flag in the volume header is set.
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 656)  */
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 657) bool hfs_bnode_need_zeroout(struct hfs_btree *tree)
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 658) {
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 659) 	struct super_block *sb = tree->inode->i_sb;
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 660) 	struct hfsplus_sb_info *sbi = HFSPLUS_SB(sb);
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 661) 	const u32 volume_attr = be32_to_cpu(sbi->s_vhdr->attributes);
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 662) 
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 663) 	return tree->cnid == HFSPLUS_CAT_CNID &&
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 664) 		volume_attr & HFSPLUS_VOL_UNUSED_NODE_FIX;
2cd282a1bc6b9 (Sergei Antonov     2014-06-06 14:36:28 -0700 665) }