Linux Audio

Check our new training course

Loading...
v3.1
  1/*
  2 * Copyright (C) 2007 Oracle.  All rights reserved.
  3 *
  4 * This program is free software; you can redistribute it and/or
  5 * modify it under the terms of the GNU General Public
  6 * License v2 as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11 * General Public License for more details.
 12 *
 13 * You should have received a copy of the GNU General Public
 14 * License along with this program; if not, write to the
 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 16 * Boston, MA 021110-1307, USA.
 17 */
 18
 19#include "ctree.h"
 20#include "disk-io.h"
 21#include "transaction.h"
 
 22
 23static int find_name_in_backref(struct btrfs_path *path, const char *name,
 24			 int name_len, struct btrfs_inode_ref **ref_ret)
 25{
 26	struct extent_buffer *leaf;
 27	struct btrfs_inode_ref *ref;
 28	unsigned long ptr;
 29	unsigned long name_ptr;
 30	u32 item_size;
 31	u32 cur_offset = 0;
 32	int len;
 33
 34	leaf = path->nodes[0];
 35	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
 36	ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
 37	while (cur_offset < item_size) {
 38		ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
 39		len = btrfs_inode_ref_name_len(leaf, ref);
 40		name_ptr = (unsigned long)(ref + 1);
 41		cur_offset += len + sizeof(*ref);
 42		if (len != name_len)
 43			continue;
 44		if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) {
 45			*ref_ret = ref;
 46			return 1;
 47		}
 48	}
 49	return 0;
 50}
 51
 52struct btrfs_inode_ref *
 53btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,
 54			struct btrfs_root *root,
 55			struct btrfs_path *path,
 56			const char *name, int name_len,
 57			u64 inode_objectid, u64 ref_objectid, int mod)
 58{
 59	struct btrfs_key key;
 60	struct btrfs_inode_ref *ref;
 61	int ins_len = mod < 0 ? -1 : 0;
 62	int cow = mod != 0;
 63	int ret;
 64
 65	key.objectid = inode_objectid;
 66	key.type = BTRFS_INODE_REF_KEY;
 67	key.offset = ref_objectid;
 68
 69	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
 70	if (ret < 0)
 71		return ERR_PTR(ret);
 72	if (ret > 0)
 73		return NULL;
 74	if (!find_name_in_backref(path, name, name_len, &ref))
 75		return NULL;
 76	return ref;
 77}
 78
 79int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
 80			   struct btrfs_root *root,
 81			   const char *name, int name_len,
 82			   u64 inode_objectid, u64 ref_objectid, u64 *index)
 83{
 84	struct btrfs_path *path;
 85	struct btrfs_key key;
 86	struct btrfs_inode_ref *ref;
 87	struct extent_buffer *leaf;
 88	unsigned long ptr;
 89	unsigned long item_start;
 90	u32 item_size;
 91	u32 sub_item_len;
 92	int ret;
 93	int del_len = name_len + sizeof(*ref);
 94
 95	key.objectid = inode_objectid;
 96	key.offset = ref_objectid;
 97	btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
 98
 99	path = btrfs_alloc_path();
100	if (!path)
101		return -ENOMEM;
102
103	path->leave_spinning = 1;
104
105	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
106	if (ret > 0) {
107		ret = -ENOENT;
108		goto out;
109	} else if (ret < 0) {
110		goto out;
111	}
112	if (!find_name_in_backref(path, name, name_len, &ref)) {
113		ret = -ENOENT;
114		goto out;
115	}
116	leaf = path->nodes[0];
117	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
118
119	if (index)
120		*index = btrfs_inode_ref_index(leaf, ref);
121
122	if (del_len == item_size) {
123		ret = btrfs_del_item(trans, root, path);
124		goto out;
125	}
126	ptr = (unsigned long)ref;
127	sub_item_len = name_len + sizeof(*ref);
128	item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
129	memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
130			      item_size - (ptr + sub_item_len - item_start));
131	ret = btrfs_truncate_item(trans, root, path,
132				  item_size - sub_item_len, 1);
133out:
134	btrfs_free_path(path);
135	return ret;
136}
137
 
138int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
139			   struct btrfs_root *root,
140			   const char *name, int name_len,
141			   u64 inode_objectid, u64 ref_objectid, u64 index)
142{
143	struct btrfs_path *path;
144	struct btrfs_key key;
145	struct btrfs_inode_ref *ref;
146	unsigned long ptr;
147	int ret;
148	int ins_len = name_len + sizeof(*ref);
149
150	key.objectid = inode_objectid;
151	key.offset = ref_objectid;
152	btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
153
154	path = btrfs_alloc_path();
155	if (!path)
156		return -ENOMEM;
157
158	path->leave_spinning = 1;
159	ret = btrfs_insert_empty_item(trans, root, path, &key,
160				      ins_len);
161	if (ret == -EEXIST) {
162		u32 old_size;
163
164		if (find_name_in_backref(path, name, name_len, &ref))
165			goto out;
166
167		old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
168		ret = btrfs_extend_item(trans, root, path, ins_len);
169		ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
170				     struct btrfs_inode_ref);
171		ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size);
172		btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
173		btrfs_set_inode_ref_index(path->nodes[0], ref, index);
174		ptr = (unsigned long)(ref + 1);
175		ret = 0;
176	} else if (ret < 0) {
177		if (ret == -EOVERFLOW)
178			ret = -EMLINK;
179		goto out;
180	} else {
181		ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
182				     struct btrfs_inode_ref);
183		btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
184		btrfs_set_inode_ref_index(path->nodes[0], ref, index);
185		ptr = (unsigned long)(ref + 1);
186	}
187	write_extent_buffer(path->nodes[0], name, ptr, name_len);
188	btrfs_mark_buffer_dirty(path->nodes[0]);
189
190out:
191	btrfs_free_path(path);
192	return ret;
193}
194
195int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
196			     struct btrfs_root *root,
197			     struct btrfs_path *path, u64 objectid)
198{
199	struct btrfs_key key;
200	int ret;
201	key.objectid = objectid;
202	btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
203	key.offset = 0;
204
205	ret = btrfs_insert_empty_item(trans, root, path, &key,
206				      sizeof(struct btrfs_inode_item));
207	return ret;
208}
209
210int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
211		       *root, struct btrfs_path *path,
212		       struct btrfs_key *location, int mod)
213{
214	int ins_len = mod < 0 ? -1 : 0;
215	int cow = mod != 0;
216	int ret;
217	int slot;
218	struct extent_buffer *leaf;
219	struct btrfs_key found_key;
220
221	ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
222	if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
223	    location->offset == (u64)-1 && path->slots[0] != 0) {
224		slot = path->slots[0] - 1;
225		leaf = path->nodes[0];
226		btrfs_item_key_to_cpu(leaf, &found_key, slot);
227		if (found_key.objectid == location->objectid &&
228		    btrfs_key_type(&found_key) == btrfs_key_type(location)) {
229			path->slots[0]--;
230			return 0;
231		}
232	}
233	return ret;
234}
v3.5.6
  1/*
  2 * Copyright (C) 2007 Oracle.  All rights reserved.
  3 *
  4 * This program is free software; you can redistribute it and/or
  5 * modify it under the terms of the GNU General Public
  6 * License v2 as published by the Free Software Foundation.
  7 *
  8 * This program is distributed in the hope that it will be useful,
  9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 11 * General Public License for more details.
 12 *
 13 * You should have received a copy of the GNU General Public
 14 * License along with this program; if not, write to the
 15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 16 * Boston, MA 021110-1307, USA.
 17 */
 18
 19#include "ctree.h"
 20#include "disk-io.h"
 21#include "transaction.h"
 22#include "print-tree.h"
 23
 24static int find_name_in_backref(struct btrfs_path *path, const char *name,
 25			 int name_len, struct btrfs_inode_ref **ref_ret)
 26{
 27	struct extent_buffer *leaf;
 28	struct btrfs_inode_ref *ref;
 29	unsigned long ptr;
 30	unsigned long name_ptr;
 31	u32 item_size;
 32	u32 cur_offset = 0;
 33	int len;
 34
 35	leaf = path->nodes[0];
 36	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
 37	ptr = btrfs_item_ptr_offset(leaf, path->slots[0]);
 38	while (cur_offset < item_size) {
 39		ref = (struct btrfs_inode_ref *)(ptr + cur_offset);
 40		len = btrfs_inode_ref_name_len(leaf, ref);
 41		name_ptr = (unsigned long)(ref + 1);
 42		cur_offset += len + sizeof(*ref);
 43		if (len != name_len)
 44			continue;
 45		if (memcmp_extent_buffer(leaf, name, name_ptr, name_len) == 0) {
 46			*ref_ret = ref;
 47			return 1;
 48		}
 49	}
 50	return 0;
 51}
 52
 53struct btrfs_inode_ref *
 54btrfs_lookup_inode_ref(struct btrfs_trans_handle *trans,
 55			struct btrfs_root *root,
 56			struct btrfs_path *path,
 57			const char *name, int name_len,
 58			u64 inode_objectid, u64 ref_objectid, int mod)
 59{
 60	struct btrfs_key key;
 61	struct btrfs_inode_ref *ref;
 62	int ins_len = mod < 0 ? -1 : 0;
 63	int cow = mod != 0;
 64	int ret;
 65
 66	key.objectid = inode_objectid;
 67	key.type = BTRFS_INODE_REF_KEY;
 68	key.offset = ref_objectid;
 69
 70	ret = btrfs_search_slot(trans, root, &key, path, ins_len, cow);
 71	if (ret < 0)
 72		return ERR_PTR(ret);
 73	if (ret > 0)
 74		return NULL;
 75	if (!find_name_in_backref(path, name, name_len, &ref))
 76		return NULL;
 77	return ref;
 78}
 79
 80int btrfs_del_inode_ref(struct btrfs_trans_handle *trans,
 81			   struct btrfs_root *root,
 82			   const char *name, int name_len,
 83			   u64 inode_objectid, u64 ref_objectid, u64 *index)
 84{
 85	struct btrfs_path *path;
 86	struct btrfs_key key;
 87	struct btrfs_inode_ref *ref;
 88	struct extent_buffer *leaf;
 89	unsigned long ptr;
 90	unsigned long item_start;
 91	u32 item_size;
 92	u32 sub_item_len;
 93	int ret;
 94	int del_len = name_len + sizeof(*ref);
 95
 96	key.objectid = inode_objectid;
 97	key.offset = ref_objectid;
 98	btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
 99
100	path = btrfs_alloc_path();
101	if (!path)
102		return -ENOMEM;
103
104	path->leave_spinning = 1;
105
106	ret = btrfs_search_slot(trans, root, &key, path, -1, 1);
107	if (ret > 0) {
108		ret = -ENOENT;
109		goto out;
110	} else if (ret < 0) {
111		goto out;
112	}
113	if (!find_name_in_backref(path, name, name_len, &ref)) {
114		ret = -ENOENT;
115		goto out;
116	}
117	leaf = path->nodes[0];
118	item_size = btrfs_item_size_nr(leaf, path->slots[0]);
119
120	if (index)
121		*index = btrfs_inode_ref_index(leaf, ref);
122
123	if (del_len == item_size) {
124		ret = btrfs_del_item(trans, root, path);
125		goto out;
126	}
127	ptr = (unsigned long)ref;
128	sub_item_len = name_len + sizeof(*ref);
129	item_start = btrfs_item_ptr_offset(leaf, path->slots[0]);
130	memmove_extent_buffer(leaf, ptr, ptr + sub_item_len,
131			      item_size - (ptr + sub_item_len - item_start));
132	btrfs_truncate_item(trans, root, path,
133				  item_size - sub_item_len, 1);
134out:
135	btrfs_free_path(path);
136	return ret;
137}
138
139/* Will return 0, -ENOMEM, -EMLINK, or -EEXIST or anything from the CoW path */
140int btrfs_insert_inode_ref(struct btrfs_trans_handle *trans,
141			   struct btrfs_root *root,
142			   const char *name, int name_len,
143			   u64 inode_objectid, u64 ref_objectid, u64 index)
144{
145	struct btrfs_path *path;
146	struct btrfs_key key;
147	struct btrfs_inode_ref *ref;
148	unsigned long ptr;
149	int ret;
150	int ins_len = name_len + sizeof(*ref);
151
152	key.objectid = inode_objectid;
153	key.offset = ref_objectid;
154	btrfs_set_key_type(&key, BTRFS_INODE_REF_KEY);
155
156	path = btrfs_alloc_path();
157	if (!path)
158		return -ENOMEM;
159
160	path->leave_spinning = 1;
161	ret = btrfs_insert_empty_item(trans, root, path, &key,
162				      ins_len);
163	if (ret == -EEXIST) {
164		u32 old_size;
165
166		if (find_name_in_backref(path, name, name_len, &ref))
167			goto out;
168
169		old_size = btrfs_item_size_nr(path->nodes[0], path->slots[0]);
170		btrfs_extend_item(trans, root, path, ins_len);
171		ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
172				     struct btrfs_inode_ref);
173		ref = (struct btrfs_inode_ref *)((unsigned long)ref + old_size);
174		btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
175		btrfs_set_inode_ref_index(path->nodes[0], ref, index);
176		ptr = (unsigned long)(ref + 1);
177		ret = 0;
178	} else if (ret < 0) {
179		if (ret == -EOVERFLOW)
180			ret = -EMLINK;
181		goto out;
182	} else {
183		ref = btrfs_item_ptr(path->nodes[0], path->slots[0],
184				     struct btrfs_inode_ref);
185		btrfs_set_inode_ref_name_len(path->nodes[0], ref, name_len);
186		btrfs_set_inode_ref_index(path->nodes[0], ref, index);
187		ptr = (unsigned long)(ref + 1);
188	}
189	write_extent_buffer(path->nodes[0], name, ptr, name_len);
190	btrfs_mark_buffer_dirty(path->nodes[0]);
191
192out:
193	btrfs_free_path(path);
194	return ret;
195}
196
197int btrfs_insert_empty_inode(struct btrfs_trans_handle *trans,
198			     struct btrfs_root *root,
199			     struct btrfs_path *path, u64 objectid)
200{
201	struct btrfs_key key;
202	int ret;
203	key.objectid = objectid;
204	btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
205	key.offset = 0;
206
207	ret = btrfs_insert_empty_item(trans, root, path, &key,
208				      sizeof(struct btrfs_inode_item));
209	return ret;
210}
211
212int btrfs_lookup_inode(struct btrfs_trans_handle *trans, struct btrfs_root
213		       *root, struct btrfs_path *path,
214		       struct btrfs_key *location, int mod)
215{
216	int ins_len = mod < 0 ? -1 : 0;
217	int cow = mod != 0;
218	int ret;
219	int slot;
220	struct extent_buffer *leaf;
221	struct btrfs_key found_key;
222
223	ret = btrfs_search_slot(trans, root, location, path, ins_len, cow);
224	if (ret > 0 && btrfs_key_type(location) == BTRFS_ROOT_ITEM_KEY &&
225	    location->offset == (u64)-1 && path->slots[0] != 0) {
226		slot = path->slots[0] - 1;
227		leaf = path->nodes[0];
228		btrfs_item_key_to_cpu(leaf, &found_key, slot);
229		if (found_key.objectid == location->objectid &&
230		    btrfs_key_type(&found_key) == btrfs_key_type(location)) {
231			path->slots[0]--;
232			return 0;
233		}
234	}
235	return ret;
236}