xref: /linux/fs/btrfs/super.c (revision 134e97313491c3a3d6bc3eca3b7c9c64408cbd08)
12e635a27SChris Mason #include <linux/module.h>
2e20d96d6SChris Mason #include <linux/buffer_head.h>
32e635a27SChris Mason #include <linux/fs.h>
42e635a27SChris Mason #include <linux/pagemap.h>
52e635a27SChris Mason #include <linux/highmem.h>
62e635a27SChris Mason #include <linux/time.h>
72e635a27SChris Mason #include <linux/init.h>
82e635a27SChris Mason #include <linux/string.h>
92e635a27SChris Mason #include <linux/smp_lock.h>
102e635a27SChris Mason #include <linux/backing-dev.h>
112e635a27SChris Mason #include "ctree.h"
12e20d96d6SChris Mason #include "disk-io.h"
13d5719762SChris Mason #include "transaction.h"
142e635a27SChris Mason 
152e635a27SChris Mason #define BTRFS_SUPER_MAGIC 0x9123682E
16e20d96d6SChris Mason 
17e20d96d6SChris Mason static struct inode_operations btrfs_dir_inode_operations;
18e20d96d6SChris Mason static struct super_operations btrfs_super_ops;
19e20d96d6SChris Mason static struct file_operations btrfs_dir_file_operations;
20e20d96d6SChris Mason 
212e635a27SChris Mason #if 0
222e635a27SChris Mason /* some random number */
232e635a27SChris Mason 
242e635a27SChris Mason static struct super_operations ramfs_ops;
252e635a27SChris Mason 
262e635a27SChris Mason static struct backing_dev_info ramfs_backing_dev_info = {
272e635a27SChris Mason 	.ra_pages	= 0,	/* No readahead */
282e635a27SChris Mason 	.capabilities	= BDI_CAP_NO_ACCT_DIRTY | BDI_CAP_NO_WRITEBACK |
292e635a27SChris Mason 			  BDI_CAP_MAP_DIRECT | BDI_CAP_MAP_COPY |
302e635a27SChris Mason 			  BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP,
312e635a27SChris Mason };
322e635a27SChris Mason 
332e635a27SChris Mason struct inode *ramfs_get_inode(struct super_block *sb, int mode, dev_t dev)
342e635a27SChris Mason {
352e635a27SChris Mason 	struct inode * inode = new_inode(sb);
362e635a27SChris Mason 
372e635a27SChris Mason 	if (inode) {
382e635a27SChris Mason 		inode->i_mode = mode;
392e635a27SChris Mason 		inode->i_uid = current->fsuid;
402e635a27SChris Mason 		inode->i_gid = current->fsgid;
412e635a27SChris Mason 		inode->i_blocks = 0;
422e635a27SChris Mason 		inode->i_mapping->a_ops = &ramfs_aops;
432e635a27SChris Mason 		inode->i_mapping->backing_dev_info = &ramfs_backing_dev_info;
442e635a27SChris Mason 		inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
452e635a27SChris Mason 		switch (mode & S_IFMT) {
462e635a27SChris Mason 		default:
472e635a27SChris Mason 			init_special_inode(inode, mode, dev);
482e635a27SChris Mason 			break;
492e635a27SChris Mason 		case S_IFREG:
502e635a27SChris Mason 			inode->i_op = &ramfs_file_inode_operations;
512e635a27SChris Mason 			inode->i_fop = &ramfs_file_operations;
522e635a27SChris Mason 			break;
532e635a27SChris Mason 		case S_IFDIR:
542e635a27SChris Mason 			inode->i_op = &ramfs_dir_inode_operations;
552e635a27SChris Mason 			inode->i_fop = &simple_dir_operations;
562e635a27SChris Mason 
572e635a27SChris Mason 			/* directory inodes start off with i_nlink == 2 (for "." entry) */
582e635a27SChris Mason 			inc_nlink(inode);
592e635a27SChris Mason 			break;
602e635a27SChris Mason 		case S_IFLNK:
612e635a27SChris Mason 			inode->i_op = &page_symlink_inode_operations;
622e635a27SChris Mason 			break;
632e635a27SChris Mason 		}
642e635a27SChris Mason 	}
652e635a27SChris Mason 	return inode;
662e635a27SChris Mason }
672e635a27SChris Mason 
682e635a27SChris Mason /*
692e635a27SChris Mason  * File creation. Allocate an inode, and we're done..
702e635a27SChris Mason  */
712e635a27SChris Mason /* SMP-safe */
722e635a27SChris Mason static int
732e635a27SChris Mason ramfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
742e635a27SChris Mason {
752e635a27SChris Mason 	struct inode * inode = ramfs_get_inode(dir->i_sb, mode, dev);
762e635a27SChris Mason 	int error = -ENOSPC;
772e635a27SChris Mason 
782e635a27SChris Mason 	if (inode) {
792e635a27SChris Mason 		if (dir->i_mode & S_ISGID) {
802e635a27SChris Mason 			inode->i_gid = dir->i_gid;
812e635a27SChris Mason 			if (S_ISDIR(mode))
822e635a27SChris Mason 				inode->i_mode |= S_ISGID;
832e635a27SChris Mason 		}
842e635a27SChris Mason 		d_instantiate(dentry, inode);
852e635a27SChris Mason 		dget(dentry);	/* Extra count - pin the dentry in core */
862e635a27SChris Mason 		error = 0;
872e635a27SChris Mason 		dir->i_mtime = dir->i_ctime = CURRENT_TIME;
882e635a27SChris Mason 	}
892e635a27SChris Mason 	return error;
902e635a27SChris Mason }
912e635a27SChris Mason 
922e635a27SChris Mason static int ramfs_mkdir(struct inode * dir, struct dentry * dentry, int mode)
932e635a27SChris Mason {
942e635a27SChris Mason 	int retval = ramfs_mknod(dir, dentry, mode | S_IFDIR, 0);
952e635a27SChris Mason 	if (!retval)
962e635a27SChris Mason 		inc_nlink(dir);
972e635a27SChris Mason 	return retval;
982e635a27SChris Mason }
992e635a27SChris Mason 
1002e635a27SChris Mason static int ramfs_create(struct inode *dir, struct dentry *dentry, int mode, struct nameidata *nd)
1012e635a27SChris Mason {
1022e635a27SChris Mason 	return ramfs_mknod(dir, dentry, mode | S_IFREG, 0);
1032e635a27SChris Mason }
1042e635a27SChris Mason 
1052e635a27SChris Mason static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * symname)
1062e635a27SChris Mason {
1072e635a27SChris Mason 	struct inode *inode;
1082e635a27SChris Mason 	int error = -ENOSPC;
1092e635a27SChris Mason 
1102e635a27SChris Mason 	inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0);
1112e635a27SChris Mason 	if (inode) {
1122e635a27SChris Mason 		int l = strlen(symname)+1;
1132e635a27SChris Mason 		error = page_symlink(inode, symname, l);
1142e635a27SChris Mason 		if (!error) {
1152e635a27SChris Mason 			if (dir->i_mode & S_ISGID)
1162e635a27SChris Mason 				inode->i_gid = dir->i_gid;
1172e635a27SChris Mason 			d_instantiate(dentry, inode);
1182e635a27SChris Mason 			dget(dentry);
1192e635a27SChris Mason 			dir->i_mtime = dir->i_ctime = CURRENT_TIME;
1202e635a27SChris Mason 		} else
1212e635a27SChris Mason 			iput(inode);
1222e635a27SChris Mason 	}
1232e635a27SChris Mason 	return error;
1242e635a27SChris Mason }
1252e635a27SChris Mason 
1262e635a27SChris Mason static struct inode_operations ramfs_dir_inode_operations = {
1272e635a27SChris Mason 	.create		= ramfs_create,
1282e635a27SChris Mason 	.lookup		= simple_lookup,
1292e635a27SChris Mason 	.link		= simple_link,
1302e635a27SChris Mason 	.unlink		= simple_unlink,
1312e635a27SChris Mason 	.symlink	= ramfs_symlink,
1322e635a27SChris Mason 	.mkdir		= ramfs_mkdir,
1332e635a27SChris Mason 	.rmdir		= simple_rmdir,
1342e635a27SChris Mason 	.mknod		= ramfs_mknod,
1352e635a27SChris Mason 	.rename		= simple_rename,
1362e635a27SChris Mason };
1372e635a27SChris Mason #endif
1382e635a27SChris Mason 
139e20d96d6SChris Mason static void btrfs_read_locked_inode(struct inode *inode)
1402e635a27SChris Mason {
141e20d96d6SChris Mason 	struct btrfs_path path;
142e20d96d6SChris Mason 	struct btrfs_inode_item *inode_item;
143e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(inode->i_sb);
144e20d96d6SChris Mason 	int ret;
145e20d96d6SChris Mason 	btrfs_init_path(&path);
146e20d96d6SChris Mason 	ret = btrfs_lookup_inode(NULL, root, &path, inode->i_ino, 0);
147e20d96d6SChris Mason 	if (ret) {
148e20d96d6SChris Mason 		make_bad_inode(inode);
14978fae27eSChris Mason 		btrfs_release_path(root, &path);
150e20d96d6SChris Mason 		return;
1512e635a27SChris Mason 	}
152e20d96d6SChris Mason 	inode_item = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]),
153e20d96d6SChris Mason 				  path.slots[0],
154e20d96d6SChris Mason 				  struct btrfs_inode_item);
155e20d96d6SChris Mason 
156e20d96d6SChris Mason 	inode->i_mode = btrfs_inode_mode(inode_item);
157e20d96d6SChris Mason 	inode->i_nlink = btrfs_inode_nlink(inode_item);
158e20d96d6SChris Mason 	inode->i_uid = btrfs_inode_uid(inode_item);
159e20d96d6SChris Mason 	inode->i_gid = btrfs_inode_gid(inode_item);
160e20d96d6SChris Mason 	inode->i_size = btrfs_inode_size(inode_item);
161e20d96d6SChris Mason 	inode->i_atime.tv_sec = btrfs_timespec_sec(&inode_item->atime);
162e20d96d6SChris Mason 	inode->i_atime.tv_nsec = btrfs_timespec_nsec(&inode_item->atime);
163e20d96d6SChris Mason 	inode->i_mtime.tv_sec = btrfs_timespec_sec(&inode_item->mtime);
164e20d96d6SChris Mason 	inode->i_mtime.tv_nsec = btrfs_timespec_nsec(&inode_item->mtime);
165e20d96d6SChris Mason 	inode->i_ctime.tv_sec = btrfs_timespec_sec(&inode_item->ctime);
166e20d96d6SChris Mason 	inode->i_ctime.tv_nsec = btrfs_timespec_nsec(&inode_item->ctime);
167e20d96d6SChris Mason 	inode->i_blocks = btrfs_inode_nblocks(inode_item);
168e20d96d6SChris Mason 	inode->i_generation = btrfs_inode_generation(inode_item);
169e20d96d6SChris Mason 	btrfs_release_path(root, &path);
170e20d96d6SChris Mason 	switch (inode->i_mode & S_IFMT) {
171e20d96d6SChris Mason #if 0
172e20d96d6SChris Mason 	default:
173e20d96d6SChris Mason 		init_special_inode(inode, inode->i_mode,
174e20d96d6SChris Mason 				   btrfs_inode_rdev(inode_item));
175e20d96d6SChris Mason 		break;
176e20d96d6SChris Mason #endif
177e20d96d6SChris Mason 	case S_IFREG:
178e20d96d6SChris Mason 		break;
179e20d96d6SChris Mason 	case S_IFDIR:
180e20d96d6SChris Mason 		inode->i_op = &btrfs_dir_inode_operations;
181e20d96d6SChris Mason 		inode->i_fop = &btrfs_dir_file_operations;
182e20d96d6SChris Mason 		break;
183e20d96d6SChris Mason 	case S_IFLNK:
184e20d96d6SChris Mason 		// inode->i_op = &page_symlink_inode_operations;
185e20d96d6SChris Mason 		break;
186e20d96d6SChris Mason 	}
187e20d96d6SChris Mason 	return;
1882e635a27SChris Mason }
1892e635a27SChris Mason 
190*134e9731SChris Mason static int btrfs_unlink(struct inode *dir, struct dentry *dentry)
191*134e9731SChris Mason {
192*134e9731SChris Mason 	struct btrfs_path path;
193*134e9731SChris Mason 	struct btrfs_root *root;
194*134e9731SChris Mason 	struct btrfs_trans_handle *trans;
195*134e9731SChris Mason 	const char *name = dentry->d_name.name;
196*134e9731SChris Mason 	int name_len = dentry->d_name.len;
197*134e9731SChris Mason 	int ret;
198*134e9731SChris Mason 	u64 objectid;
199*134e9731SChris Mason 	struct btrfs_dir_item *di;
200*134e9731SChris Mason 
201*134e9731SChris Mason 	btrfs_init_path(&path);
202*134e9731SChris Mason 	root = btrfs_sb(dir->i_sb);
203*134e9731SChris Mason 	mutex_lock(&root->fs_info->fs_mutex);
204*134e9731SChris Mason 	trans = btrfs_start_transaction(root, 1);
205*134e9731SChris Mason 
206*134e9731SChris Mason 	ret = btrfs_lookup_dir_item(trans, root, &path, dir->i_ino,
207*134e9731SChris Mason 				    name, name_len, -1);
208*134e9731SChris Mason 	if (ret < 0)
209*134e9731SChris Mason 		goto err;
210*134e9731SChris Mason 	if (ret > 0) {
211*134e9731SChris Mason 		ret = -ENOENT;
212*134e9731SChris Mason 		goto err;
213*134e9731SChris Mason 	}
214*134e9731SChris Mason 	di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0],
215*134e9731SChris Mason 			    struct btrfs_dir_item);
216*134e9731SChris Mason 	objectid = btrfs_dir_objectid(di);
217*134e9731SChris Mason 
218*134e9731SChris Mason 	ret = btrfs_del_item(trans, root, &path);
219*134e9731SChris Mason 	BUG_ON(ret);
220*134e9731SChris Mason 	dentry->d_inode->i_ctime = dir->i_ctime;
221*134e9731SChris Mason err:
222*134e9731SChris Mason 	btrfs_release_path(root, &path);
223*134e9731SChris Mason 	btrfs_end_transaction(trans, root);
224*134e9731SChris Mason 	mutex_unlock(&root->fs_info->fs_mutex);
225*134e9731SChris Mason 	if (ret == 0)
226*134e9731SChris Mason 		inode_dec_link_count(dentry->d_inode);
227*134e9731SChris Mason 	return ret;
228*134e9731SChris Mason }
229*134e9731SChris Mason 
230*134e9731SChris Mason static int btrfs_free_inode(struct btrfs_trans_handle *trans,
231*134e9731SChris Mason 			    struct btrfs_root *root,
232*134e9731SChris Mason 			    struct inode *inode)
233*134e9731SChris Mason {
234*134e9731SChris Mason 	u64 objectid = inode->i_ino;
235*134e9731SChris Mason 	struct btrfs_path path;
236*134e9731SChris Mason 	struct btrfs_inode_map_item *map;
237*134e9731SChris Mason 	struct btrfs_key stat_data_key;
238*134e9731SChris Mason 	int ret;
239*134e9731SChris Mason 	clear_inode(inode);
240*134e9731SChris Mason 	btrfs_init_path(&path);
241*134e9731SChris Mason 	ret = btrfs_lookup_inode_map(trans, root, &path, objectid, -1);
242*134e9731SChris Mason 	if (ret) {
243*134e9731SChris Mason 		if (ret > 0)
244*134e9731SChris Mason 			ret = -ENOENT;
245*134e9731SChris Mason 		btrfs_release_path(root, &path);
246*134e9731SChris Mason 		goto error;
247*134e9731SChris Mason 	}
248*134e9731SChris Mason 	map = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0],
249*134e9731SChris Mason 			    struct btrfs_inode_map_item);
250*134e9731SChris Mason 	btrfs_disk_key_to_cpu(&stat_data_key, &map->key);
251*134e9731SChris Mason 	ret = btrfs_del_item(trans, root->fs_info->inode_root, &path);
252*134e9731SChris Mason 	BUG_ON(ret);
253*134e9731SChris Mason 	btrfs_release_path(root, &path);
254*134e9731SChris Mason 	btrfs_init_path(&path);
255*134e9731SChris Mason 
256*134e9731SChris Mason 	ret = btrfs_lookup_inode(trans, root, &path, objectid, -1);
257*134e9731SChris Mason 	BUG_ON(ret);
258*134e9731SChris Mason 	ret = btrfs_del_item(trans, root, &path);
259*134e9731SChris Mason 	BUG_ON(ret);
260*134e9731SChris Mason 	btrfs_release_path(root, &path);
261*134e9731SChris Mason error:
262*134e9731SChris Mason 	return ret;
263*134e9731SChris Mason }
264*134e9731SChris Mason 
265*134e9731SChris Mason static void btrfs_delete_inode(struct inode *inode)
266*134e9731SChris Mason {
267*134e9731SChris Mason 	struct btrfs_trans_handle *trans;
268*134e9731SChris Mason 	struct btrfs_root *root = btrfs_sb(inode->i_sb);
269*134e9731SChris Mason 	truncate_inode_pages(&inode->i_data, 0);
270*134e9731SChris Mason 	if (is_bad_inode(inode)) {
271*134e9731SChris Mason 		goto no_delete;
272*134e9731SChris Mason 	}
273*134e9731SChris Mason 	inode->i_size = 0;
274*134e9731SChris Mason 	if (inode->i_blocks)
275*134e9731SChris Mason 		WARN_ON(1);
276*134e9731SChris Mason 
277*134e9731SChris Mason 	mutex_lock(&root->fs_info->fs_mutex);
278*134e9731SChris Mason 	trans = btrfs_start_transaction(root, 1);
279*134e9731SChris Mason 	btrfs_free_inode(trans, root, inode);
280*134e9731SChris Mason 	btrfs_end_transaction(trans, root);
281*134e9731SChris Mason 	mutex_unlock(&root->fs_info->fs_mutex);
282*134e9731SChris Mason 	return;
283*134e9731SChris Mason no_delete:
284*134e9731SChris Mason 	clear_inode(inode);
285*134e9731SChris Mason }
286*134e9731SChris Mason 
287*134e9731SChris Mason 
288e20d96d6SChris Mason static int btrfs_inode_by_name(struct inode *dir, struct dentry *dentry,
289e20d96d6SChris Mason 			      ino_t *ino)
290e20d96d6SChris Mason {
291e20d96d6SChris Mason 	const char *name = dentry->d_name.name;
292e20d96d6SChris Mason 	int namelen = dentry->d_name.len;
293e20d96d6SChris Mason 	struct btrfs_dir_item *di;
294e20d96d6SChris Mason 	struct btrfs_path path;
295e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(dir->i_sb);
296e20d96d6SChris Mason 	int ret;
297e20d96d6SChris Mason 
298e20d96d6SChris Mason 	btrfs_init_path(&path);
299e20d96d6SChris Mason 	ret = btrfs_lookup_dir_item(NULL, root, &path, dir->i_ino, name,
300e20d96d6SChris Mason 				    namelen, 0);
3017f5c1516SChris Mason 	if (ret || !btrfs_match_dir_item_name(root, &path, name, namelen)) {
302e20d96d6SChris Mason 		*ino = 0;
303e20d96d6SChris Mason 		goto out;
304e20d96d6SChris Mason 	}
305e20d96d6SChris Mason 	di = btrfs_item_ptr(btrfs_buffer_leaf(path.nodes[0]), path.slots[0],
306e20d96d6SChris Mason 			    struct btrfs_dir_item);
307e20d96d6SChris Mason 	*ino = btrfs_dir_objectid(di);
308e20d96d6SChris Mason out:
309e20d96d6SChris Mason 	btrfs_release_path(root, &path);
310e20d96d6SChris Mason 	return ret;
311e20d96d6SChris Mason }
312e20d96d6SChris Mason 
313e20d96d6SChris Mason static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
314e20d96d6SChris Mason 				   struct nameidata *nd)
315e20d96d6SChris Mason {
316e20d96d6SChris Mason 	struct inode * inode;
317e20d96d6SChris Mason 	ino_t ino;
318e20d96d6SChris Mason 	int ret;
319e20d96d6SChris Mason 
320e20d96d6SChris Mason 	if (dentry->d_name.len > BTRFS_NAME_LEN)
321e20d96d6SChris Mason 		return ERR_PTR(-ENAMETOOLONG);
322e20d96d6SChris Mason 
323e20d96d6SChris Mason 	ret = btrfs_inode_by_name(dir, dentry, &ino);
324e20d96d6SChris Mason 	if (ret < 0)
325e20d96d6SChris Mason 		return ERR_PTR(ret);
326e20d96d6SChris Mason 	inode = NULL;
327e20d96d6SChris Mason 	if (ino) {
328e20d96d6SChris Mason 		inode = iget(dir->i_sb, ino);
329e20d96d6SChris Mason 		if (!inode)
330e20d96d6SChris Mason 			return ERR_PTR(-EACCES);
331e20d96d6SChris Mason 	}
332e20d96d6SChris Mason 	return d_splice_alias(inode, dentry);
333e20d96d6SChris Mason }
334e20d96d6SChris Mason 
335e20d96d6SChris Mason static int btrfs_readdir(struct file *filp, void *dirent, filldir_t filldir)
336e20d96d6SChris Mason {
337e20d96d6SChris Mason 	struct inode *inode = filp->f_path.dentry->d_inode;
338e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(inode->i_sb);
339e20d96d6SChris Mason 	struct btrfs_item *item;
340e20d96d6SChris Mason 	struct btrfs_dir_item *di;
341e20d96d6SChris Mason 	struct btrfs_key key;
342e20d96d6SChris Mason 	struct btrfs_path path;
343e20d96d6SChris Mason 	int ret;
344e20d96d6SChris Mason 	u32 nritems;
345e20d96d6SChris Mason 	struct btrfs_leaf *leaf;
346e20d96d6SChris Mason 	int slot;
347e20d96d6SChris Mason 	int advance;
348e20d96d6SChris Mason 	unsigned char d_type = DT_UNKNOWN;
3497f5c1516SChris Mason 	int over = 0;
350e20d96d6SChris Mason 
351e20d96d6SChris Mason 	key.objectid = inode->i_ino;
352e20d96d6SChris Mason 	key.flags = 0;
353e20d96d6SChris Mason 	btrfs_set_key_type(&key, BTRFS_DIR_ITEM_KEY);
354e20d96d6SChris Mason 	key.offset = filp->f_pos;
355e20d96d6SChris Mason 	btrfs_init_path(&path);
356e20d96d6SChris Mason 	ret = btrfs_search_slot(NULL, root, &key, &path, 0, 0);
357e20d96d6SChris Mason 	if (ret < 0) {
358e20d96d6SChris Mason 		goto err;
359e20d96d6SChris Mason 	}
3607f5c1516SChris Mason 	advance = 0;
361e20d96d6SChris Mason 	while(1) {
362e20d96d6SChris Mason 		leaf = btrfs_buffer_leaf(path.nodes[0]);
363e20d96d6SChris Mason 		nritems = btrfs_header_nritems(&leaf->header);
364e20d96d6SChris Mason 		slot = path.slots[0];
365e20d96d6SChris Mason 		if (advance) {
366e20d96d6SChris Mason 			if (slot == nritems -1) {
367e20d96d6SChris Mason 				ret = btrfs_next_leaf(root, &path);
368e20d96d6SChris Mason 				if (ret)
369e20d96d6SChris Mason 					break;
370e20d96d6SChris Mason 				leaf = btrfs_buffer_leaf(path.nodes[0]);
371e20d96d6SChris Mason 				nritems = btrfs_header_nritems(&leaf->header);
372e20d96d6SChris Mason 				slot = path.slots[0];
373*134e9731SChris Mason #if 0
374*134e9731SChris Mason 				page_cache_readahead(
375*134e9731SChris Mason 				     inode->i_sb->s_bdev->bd_inode->i_mapping,
376*134e9731SChris Mason 				     &filp->f_ra, filp,
377*134e9731SChris Mason 				     path.nodes[0]->b_blocknr >>
378*134e9731SChris Mason 				     (PAGE_CACHE_SHIFT - inode->i_blkbits), 1);
379*134e9731SChris Mason #endif
380e20d96d6SChris Mason 			} else {
381e20d96d6SChris Mason 				slot++;
382e20d96d6SChris Mason 				path.slots[0]++;
383e20d96d6SChris Mason 			}
384e20d96d6SChris Mason 		}
385e20d96d6SChris Mason 		advance = 1;
386e20d96d6SChris Mason 		item = leaf->items + slot;
387e20d96d6SChris Mason 		if (btrfs_disk_key_objectid(&item->key) != key.objectid)
388e20d96d6SChris Mason 			break;
389e20d96d6SChris Mason 		if (btrfs_disk_key_type(&item->key) != BTRFS_DIR_ITEM_KEY)
390e20d96d6SChris Mason 			continue;
3917f5c1516SChris Mason 		if (btrfs_disk_key_offset(&item->key) < filp->f_pos)
3927f5c1516SChris Mason 			continue;
393e20d96d6SChris Mason 		di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item);
394e20d96d6SChris Mason 		over = filldir(dirent, (const char *)(di + 1),
395e20d96d6SChris Mason 			       btrfs_dir_name_len(di),
396e20d96d6SChris Mason 			       btrfs_disk_key_offset(&item->key),
397e20d96d6SChris Mason 			       btrfs_dir_objectid(di), d_type);
3987f5c1516SChris Mason 		if (over) {
3997f5c1516SChris Mason 			filp->f_pos = btrfs_disk_key_offset(&item->key);
400e20d96d6SChris Mason 			break;
4017f5c1516SChris Mason 		}
402e20d96d6SChris Mason 		filp->f_pos = btrfs_disk_key_offset(&item->key) + 1;
403e20d96d6SChris Mason 	}
404e20d96d6SChris Mason 	ret = 0;
405e20d96d6SChris Mason err:
406e20d96d6SChris Mason 	btrfs_release_path(root, &path);
407e20d96d6SChris Mason 	return ret;
408e20d96d6SChris Mason }
409e20d96d6SChris Mason 
410e20d96d6SChris Mason static void btrfs_put_super (struct super_block * sb)
411e20d96d6SChris Mason {
412e20d96d6SChris Mason 	struct btrfs_root *root = btrfs_sb(sb);
413e20d96d6SChris Mason 	int ret;
414e20d96d6SChris Mason 
415e20d96d6SChris Mason 	ret = close_ctree(root);
416e20d96d6SChris Mason 	if (ret) {
417e20d96d6SChris Mason 		printk("close ctree returns %d\n", ret);
418e20d96d6SChris Mason 	}
419e20d96d6SChris Mason 	sb->s_fs_info = NULL;
420e20d96d6SChris Mason }
4212e635a27SChris Mason 
4222e635a27SChris Mason static int btrfs_fill_super(struct super_block * sb, void * data, int silent)
4232e635a27SChris Mason {
4242e635a27SChris Mason 	struct inode * inode;
425e20d96d6SChris Mason 	struct dentry * root_dentry;
426e20d96d6SChris Mason 	struct btrfs_super_block *disk_super;
427e20d96d6SChris Mason 	struct buffer_head *bh;
428e20d96d6SChris Mason 	struct btrfs_root *root;
4292e635a27SChris Mason 
4302e635a27SChris Mason 	sb->s_maxbytes = MAX_LFS_FILESIZE;
4312e635a27SChris Mason 	sb->s_blocksize = PAGE_CACHE_SIZE;
4322e635a27SChris Mason 	sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
4332e635a27SChris Mason 	sb->s_magic = BTRFS_SUPER_MAGIC;
434e20d96d6SChris Mason 	sb->s_op = &btrfs_super_ops;
4352e635a27SChris Mason 	sb->s_time_gran = 1;
436e20d96d6SChris Mason 
437e20d96d6SChris Mason 	bh = sb_bread(sb, BTRFS_SUPER_INFO_OFFSET / sb->s_blocksize);
438e20d96d6SChris Mason 	if (!bh) {
439e20d96d6SChris Mason 		printk("btrfs: unable to read on disk super\n");
440e20d96d6SChris Mason 		return -EIO;
441e20d96d6SChris Mason 	}
442e20d96d6SChris Mason 	disk_super = (struct btrfs_super_block *)bh->b_data;
443e20d96d6SChris Mason 	root = open_ctree(sb, bh, disk_super);
444e20d96d6SChris Mason 	sb->s_fs_info = root;
445e20d96d6SChris Mason 	if (!root) {
446e20d96d6SChris Mason 		printk("btrfs: open_ctree failed\n");
447e20d96d6SChris Mason 		return -EIO;
448e20d96d6SChris Mason 	}
449e20d96d6SChris Mason 	printk("read in super total blocks %Lu root %Lu\n",
450e20d96d6SChris Mason 	       btrfs_super_total_blocks(disk_super),
451e20d96d6SChris Mason 	       btrfs_super_root_dir(disk_super));
452e20d96d6SChris Mason 
453e20d96d6SChris Mason 	inode = iget_locked(sb, btrfs_super_root_dir(disk_super));
4542e635a27SChris Mason 	if (!inode)
4552e635a27SChris Mason 		return -ENOMEM;
456e20d96d6SChris Mason 	if (inode->i_state & I_NEW) {
457e20d96d6SChris Mason 		btrfs_read_locked_inode(inode);
458e20d96d6SChris Mason 		unlock_new_inode(inode);
459e20d96d6SChris Mason 	}
4602e635a27SChris Mason 
461e20d96d6SChris Mason 	root_dentry = d_alloc_root(inode);
462e20d96d6SChris Mason 	if (!root_dentry) {
4632e635a27SChris Mason 		iput(inode);
4642e635a27SChris Mason 		return -ENOMEM;
4652e635a27SChris Mason 	}
466e20d96d6SChris Mason 	sb->s_root = root_dentry;
467e20d96d6SChris Mason 
4682e635a27SChris Mason 	return 0;
4692e635a27SChris Mason }
4702e635a27SChris Mason 
471d5719762SChris Mason static void fill_inode_item(struct btrfs_inode_item *item,
472d5719762SChris Mason 			    struct inode *inode)
473d5719762SChris Mason {
474d5719762SChris Mason 	btrfs_set_inode_uid(item, inode->i_uid);
475d5719762SChris Mason 	btrfs_set_inode_gid(item, inode->i_gid);
476d5719762SChris Mason 	btrfs_set_inode_size(item, inode->i_size);
477d5719762SChris Mason 	btrfs_set_inode_mode(item, inode->i_mode);
478d5719762SChris Mason 	btrfs_set_inode_nlink(item, inode->i_nlink);
479d5719762SChris Mason 	btrfs_set_timespec_sec(&item->atime, inode->i_atime.tv_sec);
480d5719762SChris Mason 	btrfs_set_timespec_nsec(&item->atime, inode->i_atime.tv_nsec);
481d5719762SChris Mason 	btrfs_set_timespec_sec(&item->mtime, inode->i_mtime.tv_sec);
482d5719762SChris Mason 	btrfs_set_timespec_nsec(&item->mtime, inode->i_mtime.tv_nsec);
483d5719762SChris Mason 	btrfs_set_timespec_sec(&item->ctime, inode->i_ctime.tv_sec);
484d5719762SChris Mason 	btrfs_set_timespec_nsec(&item->ctime, inode->i_ctime.tv_nsec);
485d5719762SChris Mason 	btrfs_set_inode_nblocks(item, inode->i_blocks);
486d5719762SChris Mason 	btrfs_set_inode_generation(item, inode->i_generation);
487d5719762SChris Mason }
488d5719762SChris Mason 
489d5719762SChris Mason static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
490d5719762SChris Mason 				     struct inode *dir, int mode)
491d5719762SChris Mason {
492d5719762SChris Mason 	struct inode *inode;
493d5719762SChris Mason 	struct btrfs_inode_item inode_item;
494d5719762SChris Mason 	struct btrfs_root *root = btrfs_sb(dir->i_sb);
495d5719762SChris Mason 	struct btrfs_key key;
496d5719762SChris Mason 	int ret;
497d5719762SChris Mason 	u64 objectid;
498d5719762SChris Mason 
499d5719762SChris Mason 	inode = new_inode(dir->i_sb);
500d5719762SChris Mason 	if (!inode)
501d5719762SChris Mason 		return ERR_PTR(-ENOMEM);
502d5719762SChris Mason 
503d5719762SChris Mason 	ret = btrfs_find_free_objectid(trans, root, dir->i_ino, &objectid);
504d5719762SChris Mason 	BUG_ON(ret);
505d5719762SChris Mason 
506d5719762SChris Mason 	inode->i_uid = current->fsuid;
507d5719762SChris Mason 	inode->i_gid = current->fsgid;
508d5719762SChris Mason 	inode->i_mode = mode;
509d5719762SChris Mason 	inode->i_ino = objectid;
510d5719762SChris Mason 	inode->i_blocks = 0;
511d5719762SChris Mason 	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME_SEC;
512d5719762SChris Mason 	fill_inode_item(&inode_item, inode);
513d5719762SChris Mason 
514d5719762SChris Mason 
515d5719762SChris Mason 	key.objectid = objectid;
516d5719762SChris Mason 	key.flags = 0;
517d5719762SChris Mason 	key.offset = 0;
518d5719762SChris Mason 	btrfs_set_key_type(&key, BTRFS_INODE_ITEM_KEY);
519d5719762SChris Mason 	ret = btrfs_insert_inode_map(trans, root, objectid, &key);
520d5719762SChris Mason 	BUG_ON(ret);
521d5719762SChris Mason 
522d5719762SChris Mason 	ret = btrfs_insert_inode(trans, root, objectid, &inode_item);
523d5719762SChris Mason 	BUG_ON(ret);
524d5719762SChris Mason 
525d5719762SChris Mason 	insert_inode_hash(inode);
526d5719762SChris Mason 	// FIXME mark_inode_dirty(inode)
527d5719762SChris Mason 	return inode;
528d5719762SChris Mason }
529d5719762SChris Mason 
530d5719762SChris Mason static int btrfs_add_link(struct btrfs_trans_handle *trans,
531d5719762SChris Mason 			    struct dentry *dentry, struct inode *inode)
532d5719762SChris Mason {
533d5719762SChris Mason 	int ret;
534d5719762SChris Mason 	ret = btrfs_insert_dir_item(trans, btrfs_sb(inode->i_sb),
535d5719762SChris Mason 				    dentry->d_name.name, dentry->d_name.len,
536d5719762SChris Mason 				    dentry->d_parent->d_inode->i_ino,
537d5719762SChris Mason 				    inode->i_ino, 0);
538d5719762SChris Mason 	return ret;
539d5719762SChris Mason }
540d5719762SChris Mason 
541d5719762SChris Mason static int btrfs_add_nondir(struct btrfs_trans_handle *trans,
542d5719762SChris Mason 			    struct dentry *dentry, struct inode *inode)
543d5719762SChris Mason {
544d5719762SChris Mason 	int err = btrfs_add_link(trans, dentry, inode);
545d5719762SChris Mason 	if (!err) {
546d5719762SChris Mason 		d_instantiate(dentry, inode);
547d5719762SChris Mason 		return 0;
548d5719762SChris Mason 	}
549d5719762SChris Mason 	return err;
550d5719762SChris Mason }
551d5719762SChris Mason 
552d5719762SChris Mason static int btrfs_create(struct inode *dir, struct dentry *dentry,
553d5719762SChris Mason 			int mode, struct nameidata *nd)
554d5719762SChris Mason {
555d5719762SChris Mason 	struct btrfs_trans_handle *trans;
556d5719762SChris Mason 	struct btrfs_root *root = btrfs_sb(dir->i_sb);
557d5719762SChris Mason 	struct inode *inode;
558d5719762SChris Mason 	int err;
559*134e9731SChris Mason 	int drop_inode = 0;
560d5719762SChris Mason 
561d561c025SChris Mason 	mutex_lock(&root->fs_info->fs_mutex);
562d5719762SChris Mason 	trans = btrfs_start_transaction(root, 1);
563d5719762SChris Mason 	inode = btrfs_new_inode(trans, dir, mode);
564d5719762SChris Mason 	err = PTR_ERR(inode);
565d5719762SChris Mason 	if (IS_ERR(inode))
566d561c025SChris Mason 		goto out_unlock;
567d5719762SChris Mason 	// FIXME mark the inode dirty
568d5719762SChris Mason 	err = btrfs_add_nondir(trans, dentry, inode);
569*134e9731SChris Mason 	if (err)
570*134e9731SChris Mason 		drop_inode = 1;
571d5719762SChris Mason 	dir->i_sb->s_dirt = 1;
572d5719762SChris Mason 	btrfs_end_transaction(trans, root);
573d561c025SChris Mason out_unlock:
574d561c025SChris Mason 	mutex_unlock(&root->fs_info->fs_mutex);
575*134e9731SChris Mason 	if (drop_inode) {
576*134e9731SChris Mason 		inode_dec_link_count(inode);
577*134e9731SChris Mason 		iput(inode);
578*134e9731SChris Mason 	}
579d5719762SChris Mason 	return err;
580d5719762SChris Mason }
581d5719762SChris Mason 
582d5719762SChris Mason static int btrfs_sync_fs(struct super_block *sb, int wait)
583d5719762SChris Mason {
584d5719762SChris Mason 	struct btrfs_trans_handle *trans;
585d5719762SChris Mason 	struct btrfs_root *root;
586d5719762SChris Mason 	int ret;
587df2ce34cSChris Mason 
588d5719762SChris Mason 	sb->s_dirt = 0;
589d561c025SChris Mason 	if (!wait) {
590d561c025SChris Mason 		filemap_flush(sb->s_bdev->bd_inode->i_mapping);
591df2ce34cSChris Mason 		return 0;
592d561c025SChris Mason 	}
593d561c025SChris Mason 	filemap_write_and_wait(sb->s_bdev->bd_inode->i_mapping);
594df2ce34cSChris Mason 
595d5719762SChris Mason 	root = btrfs_sb(sb);
596d561c025SChris Mason 	mutex_lock(&root->fs_info->fs_mutex);
597d5719762SChris Mason 	trans = btrfs_start_transaction(root, 1);
598d5719762SChris Mason 	ret = btrfs_commit_transaction(trans, root);
599d5719762SChris Mason 	sb->s_dirt = 0;
600d5719762SChris Mason 	BUG_ON(ret);
601d5719762SChris Mason printk("btrfs sync_fs\n");
602d561c025SChris Mason 	mutex_unlock(&root->fs_info->fs_mutex);
603d5719762SChris Mason 	return 0;
604d5719762SChris Mason }
605d5719762SChris Mason 
606d561c025SChris Mason static void btrfs_write_super(struct super_block *sb)
607d561c025SChris Mason {
608d561c025SChris Mason 	btrfs_sync_fs(sb, 1);
609d561c025SChris Mason }
610d561c025SChris Mason 
611d561c025SChris Mason 
6122e635a27SChris Mason static int btrfs_get_sb(struct file_system_type *fs_type,
6132e635a27SChris Mason 	int flags, const char *dev_name, void *data, struct vfsmount *mnt)
6142e635a27SChris Mason {
6152e635a27SChris Mason 	return get_sb_bdev(fs_type, flags, dev_name, data,
6162e635a27SChris Mason 			   btrfs_fill_super, mnt);
6172e635a27SChris Mason }
6182e635a27SChris Mason 
6192e635a27SChris Mason static struct file_system_type btrfs_fs_type = {
6202e635a27SChris Mason 	.owner		= THIS_MODULE,
6212e635a27SChris Mason 	.name		= "btrfs",
6222e635a27SChris Mason 	.get_sb		= btrfs_get_sb,
6232e635a27SChris Mason 	.kill_sb	= kill_block_super,
6242e635a27SChris Mason 	.fs_flags	= FS_REQUIRES_DEV,
6252e635a27SChris Mason };
6262e635a27SChris Mason 
627e20d96d6SChris Mason static struct super_operations btrfs_super_ops = {
628e20d96d6SChris Mason 	.statfs		= simple_statfs,
629*134e9731SChris Mason 	.delete_inode	= btrfs_delete_inode,
630e20d96d6SChris Mason 	.put_super	= btrfs_put_super,
631e20d96d6SChris Mason 	.read_inode	= btrfs_read_locked_inode,
632d5719762SChris Mason 	.write_super	= btrfs_write_super,
633d5719762SChris Mason 	.sync_fs	= btrfs_sync_fs,
634e20d96d6SChris Mason };
635e20d96d6SChris Mason 
636e20d96d6SChris Mason static struct inode_operations btrfs_dir_inode_operations = {
637e20d96d6SChris Mason 	.lookup		= btrfs_lookup,
638d5719762SChris Mason 	.create		= btrfs_create,
639*134e9731SChris Mason 	.unlink		= btrfs_unlink,
640e20d96d6SChris Mason };
641e20d96d6SChris Mason 
642e20d96d6SChris Mason static struct file_operations btrfs_dir_file_operations = {
643e20d96d6SChris Mason 	.llseek		= generic_file_llseek,
644e20d96d6SChris Mason 	.read		= generic_read_dir,
645e20d96d6SChris Mason 	.readdir	= btrfs_readdir,
646e20d96d6SChris Mason };
647e20d96d6SChris Mason 
648e20d96d6SChris Mason 
6492e635a27SChris Mason static int __init init_btrfs_fs(void)
6502e635a27SChris Mason {
6512e635a27SChris Mason 	printk("btrfs loaded!\n");
6522e635a27SChris Mason 	return register_filesystem(&btrfs_fs_type);
6532e635a27SChris Mason }
6542e635a27SChris Mason 
6552e635a27SChris Mason static void __exit exit_btrfs_fs(void)
6562e635a27SChris Mason {
6572e635a27SChris Mason 	unregister_filesystem(&btrfs_fs_type);
6582e635a27SChris Mason 	printk("btrfs unloaded\n");
6592e635a27SChris Mason }
6602e635a27SChris Mason 
6612e635a27SChris Mason module_init(init_btrfs_fs)
6622e635a27SChris Mason module_exit(exit_btrfs_fs)
6632e635a27SChris Mason 
6642e635a27SChris Mason MODULE_LICENSE("GPL");
665