aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/bio.c1
-rw-r--r--fs/btrfs/disk-io.c26
-rw-r--r--fs/btrfs/transaction.c12
-rw-r--r--fs/fat/cache.c6
-rw-r--r--fs/fat/dir.c2
-rw-r--r--fs/fat/fat.h7
-rw-r--r--fs/fat/fatent.c4
-rw-r--r--fs/fat/file.c184
-rw-r--r--fs/fat/inode.c28
-rw-r--r--fs/fat/misc.c22
-rw-r--r--fs/fat/namei_msdos.c2
-rw-r--r--fs/fat/namei_vfat.c2
-rw-r--r--fs/nilfs2/bmap.c272
-rw-r--r--fs/nilfs2/bmap.h135
-rw-r--r--fs/nilfs2/btnode.c9
-rw-r--r--fs/nilfs2/btnode.h2
-rw-r--r--fs/nilfs2/btree.c366
-rw-r--r--fs/nilfs2/btree.h31
-rw-r--r--fs/nilfs2/cpfile.c47
-rw-r--r--fs/nilfs2/cpfile.h4
-rw-r--r--fs/nilfs2/dat.c36
-rw-r--r--fs/nilfs2/dat.h2
-rw-r--r--fs/nilfs2/direct.c139
-rw-r--r--fs/nilfs2/direct.h20
-rw-r--r--fs/nilfs2/gcinode.c5
-rw-r--r--fs/nilfs2/inode.c18
-rw-r--r--fs/nilfs2/ioctl.c35
-rw-r--r--fs/nilfs2/mdt.c3
-rw-r--r--fs/nilfs2/nilfs.h1
-rw-r--r--fs/nilfs2/recovery.c37
-rw-r--r--fs/nilfs2/segbuf.c3
-rw-r--r--fs/nilfs2/seglist.h85
-rw-r--r--fs/nilfs2/segment.c130
-rw-r--r--fs/nilfs2/segment.h12
-rw-r--r--fs/nilfs2/sufile.c119
-rw-r--r--fs/nilfs2/sufile.h62
-rw-r--r--fs/nilfs2/super.c9
-rw-r--r--fs/nilfs2/the_nilfs.c1
-rw-r--r--fs/ocfs2/alloc.c80
-rw-r--r--fs/ocfs2/blockcheck.c184
-rw-r--r--fs/ocfs2/blockcheck.h29
-rw-r--r--fs/ocfs2/cluster/masklog.h35
-rw-r--r--fs/ocfs2/cluster/tcp.c7
-rw-r--r--fs/ocfs2/dir.c21
-rw-r--r--fs/ocfs2/dlmglue.c51
-rw-r--r--fs/ocfs2/dlmglue.h11
-rw-r--r--fs/ocfs2/file.c56
-rw-r--r--fs/ocfs2/journal.c111
-rw-r--r--fs/ocfs2/journal.h4
-rw-r--r--fs/ocfs2/ocfs2.h16
-rw-r--r--fs/ocfs2/ocfs2_lockid.h5
-rw-r--r--fs/ocfs2/quota_global.c4
-rw-r--r--fs/ocfs2/quota_local.c21
-rw-r--r--fs/ocfs2/super.c66
-rw-r--r--fs/ocfs2/xattr.c5
-rw-r--r--fs/ramfs/inode.c9
-rw-r--r--fs/ubifs/super.c3
57 files changed, 1518 insertions, 1079 deletions
diff --git a/fs/bio.c b/fs/bio.c
index 5f80848c320c..24c914043532 100644
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -25,7 +25,6 @@
25#include <linux/module.h> 25#include <linux/module.h>
26#include <linux/mempool.h> 26#include <linux/mempool.h>
27#include <linux/workqueue.h> 27#include <linux/workqueue.h>
28#include <linux/blktrace_api.h>
29#include <scsi/sg.h> /* for struct sg_iovec */ 28#include <scsi/sg.h> /* for struct sg_iovec */
30 29
31#include <trace/events/block.h> 30#include <trace/events/block.h>
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 0d50d49d990a..d28d29c95f7c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -42,6 +42,8 @@
42static struct extent_io_ops btree_extent_io_ops; 42static struct extent_io_ops btree_extent_io_ops;
43static void end_workqueue_fn(struct btrfs_work *work); 43static void end_workqueue_fn(struct btrfs_work *work);
44 44
45static atomic_t btrfs_bdi_num = ATOMIC_INIT(0);
46
45/* 47/*
46 * end_io_wq structs are used to do processing in task context when an IO is 48 * end_io_wq structs are used to do processing in task context when an IO is
47 * complete. This is used during reads to verify checksums, and it is used 49 * complete. This is used during reads to verify checksums, and it is used
@@ -1342,12 +1344,25 @@ static void btrfs_unplug_io_fn(struct backing_dev_info *bdi, struct page *page)
1342 free_extent_map(em); 1344 free_extent_map(em);
1343} 1345}
1344 1346
1347/*
1348 * If this fails, caller must call bdi_destroy() to get rid of the
1349 * bdi again.
1350 */
1345static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi) 1351static int setup_bdi(struct btrfs_fs_info *info, struct backing_dev_info *bdi)
1346{ 1352{
1347 bdi_init(bdi); 1353 int err;
1354
1355 bdi->capabilities = BDI_CAP_MAP_COPY;
1356 err = bdi_init(bdi);
1357 if (err)
1358 return err;
1359
1360 err = bdi_register(bdi, NULL, "btrfs-%d",
1361 atomic_inc_return(&btrfs_bdi_num));
1362 if (err)
1363 return err;
1364
1348 bdi->ra_pages = default_backing_dev_info.ra_pages; 1365 bdi->ra_pages = default_backing_dev_info.ra_pages;
1349 bdi->state = 0;
1350 bdi->capabilities = default_backing_dev_info.capabilities;
1351 bdi->unplug_io_fn = btrfs_unplug_io_fn; 1366 bdi->unplug_io_fn = btrfs_unplug_io_fn;
1352 bdi->unplug_io_data = info; 1367 bdi->unplug_io_data = info;
1353 bdi->congested_fn = btrfs_congested_fn; 1368 bdi->congested_fn = btrfs_congested_fn;
@@ -1569,7 +1584,8 @@ struct btrfs_root *open_ctree(struct super_block *sb,
1569 fs_info->sb = sb; 1584 fs_info->sb = sb;
1570 fs_info->max_extent = (u64)-1; 1585 fs_info->max_extent = (u64)-1;
1571 fs_info->max_inline = 8192 * 1024; 1586 fs_info->max_inline = 8192 * 1024;
1572 setup_bdi(fs_info, &fs_info->bdi); 1587 if (setup_bdi(fs_info, &fs_info->bdi))
1588 goto fail_bdi;
1573 fs_info->btree_inode = new_inode(sb); 1589 fs_info->btree_inode = new_inode(sb);
1574 fs_info->btree_inode->i_ino = 1; 1590 fs_info->btree_inode->i_ino = 1;
1575 fs_info->btree_inode->i_nlink = 1; 1591 fs_info->btree_inode->i_nlink = 1;
@@ -1946,8 +1962,8 @@ fail_iput:
1946 1962
1947 btrfs_close_devices(fs_info->fs_devices); 1963 btrfs_close_devices(fs_info->fs_devices);
1948 btrfs_mapping_tree_free(&fs_info->mapping_tree); 1964 btrfs_mapping_tree_free(&fs_info->mapping_tree);
1965fail_bdi:
1949 bdi_destroy(&fs_info->bdi); 1966 bdi_destroy(&fs_info->bdi);
1950
1951fail: 1967fail:
1952 kfree(extent_root); 1968 kfree(extent_root);
1953 kfree(tree_root); 1969 kfree(tree_root);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 2e177d7f4bb9..4e83457ea253 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -543,13 +543,13 @@ static noinline int commit_fs_roots(struct btrfs_trans_handle *trans,
543 btrfs_free_log(trans, root); 543 btrfs_free_log(trans, root);
544 btrfs_update_reloc_root(trans, root); 544 btrfs_update_reloc_root(trans, root);
545 545
546 if (root->commit_root == root->node) 546 if (root->commit_root != root->node) {
547 continue; 547 free_extent_buffer(root->commit_root);
548 548 root->commit_root = btrfs_root_node(root);
549 free_extent_buffer(root->commit_root); 549 btrfs_set_root_node(&root->root_item,
550 root->commit_root = btrfs_root_node(root); 550 root->node);
551 }
551 552
552 btrfs_set_root_node(&root->root_item, root->node);
553 err = btrfs_update_root(trans, fs_info->tree_root, 553 err = btrfs_update_root(trans, fs_info->tree_root,
554 &root->root_key, 554 &root->root_key,
555 &root->root_item); 555 &root->root_item);
diff --git a/fs/fat/cache.c b/fs/fat/cache.c
index b42602298087..923990e4f16e 100644
--- a/fs/fat/cache.c
+++ b/fs/fat/cache.c
@@ -241,7 +241,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
241 while (*fclus < cluster) { 241 while (*fclus < cluster) {
242 /* prevent the infinite loop of cluster chain */ 242 /* prevent the infinite loop of cluster chain */
243 if (*fclus > limit) { 243 if (*fclus > limit) {
244 fat_fs_panic(sb, "%s: detected the cluster chain loop" 244 fat_fs_error(sb, "%s: detected the cluster chain loop"
245 " (i_pos %lld)", __func__, 245 " (i_pos %lld)", __func__,
246 MSDOS_I(inode)->i_pos); 246 MSDOS_I(inode)->i_pos);
247 nr = -EIO; 247 nr = -EIO;
@@ -252,7 +252,7 @@ int fat_get_cluster(struct inode *inode, int cluster, int *fclus, int *dclus)
252 if (nr < 0) 252 if (nr < 0)
253 goto out; 253 goto out;
254 else if (nr == FAT_ENT_FREE) { 254 else if (nr == FAT_ENT_FREE) {
255 fat_fs_panic(sb, "%s: invalid cluster chain" 255 fat_fs_error(sb, "%s: invalid cluster chain"
256 " (i_pos %lld)", __func__, 256 " (i_pos %lld)", __func__,
257 MSDOS_I(inode)->i_pos); 257 MSDOS_I(inode)->i_pos);
258 nr = -EIO; 258 nr = -EIO;
@@ -285,7 +285,7 @@ static int fat_bmap_cluster(struct inode *inode, int cluster)
285 if (ret < 0) 285 if (ret < 0)
286 return ret; 286 return ret;
287 else if (ret == FAT_ENT_EOF) { 287 else if (ret == FAT_ENT_EOF) {
288 fat_fs_panic(sb, "%s: request beyond EOF (i_pos %lld)", 288 fat_fs_error(sb, "%s: request beyond EOF (i_pos %lld)",
289 __func__, MSDOS_I(inode)->i_pos); 289 __func__, MSDOS_I(inode)->i_pos);
290 return -EIO; 290 return -EIO;
291 } 291 }
diff --git a/fs/fat/dir.c b/fs/fat/dir.c
index f3500294eec5..3b8e71b412fd 100644
--- a/fs/fat/dir.c
+++ b/fs/fat/dir.c
@@ -1334,7 +1334,7 @@ found:
1334 goto error_remove; 1334 goto error_remove;
1335 } 1335 }
1336 if (dir->i_size & (sbi->cluster_size - 1)) { 1336 if (dir->i_size & (sbi->cluster_size - 1)) {
1337 fat_fs_panic(sb, "Odd directory size"); 1337 fat_fs_error(sb, "Odd directory size");
1338 dir->i_size = (dir->i_size + sbi->cluster_size - 1) 1338 dir->i_size = (dir->i_size + sbi->cluster_size - 1)
1339 & ~((loff_t)sbi->cluster_size - 1); 1339 & ~((loff_t)sbi->cluster_size - 1);
1340 } 1340 }
diff --git a/fs/fat/fat.h b/fs/fat/fat.h
index e4d88527b5dd..adb0e72a176d 100644
--- a/fs/fat/fat.h
+++ b/fs/fat/fat.h
@@ -17,6 +17,10 @@
17#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */ 17#define VFAT_SFN_CREATE_WIN95 0x0100 /* emulate win95 rule for create */
18#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */ 18#define VFAT_SFN_CREATE_WINNT 0x0200 /* emulate winnt rule for create */
19 19
20#define FAT_ERRORS_CONT 1 /* ignore error and continue */
21#define FAT_ERRORS_PANIC 2 /* panic on error */
22#define FAT_ERRORS_RO 3 /* remount r/o on error */
23
20struct fat_mount_options { 24struct fat_mount_options {
21 uid_t fs_uid; 25 uid_t fs_uid;
22 gid_t fs_gid; 26 gid_t fs_gid;
@@ -26,6 +30,7 @@ struct fat_mount_options {
26 char *iocharset; /* Charset used for filename input/display */ 30 char *iocharset; /* Charset used for filename input/display */
27 unsigned short shortname; /* flags for shortname display/create rule */ 31 unsigned short shortname; /* flags for shortname display/create rule */
28 unsigned char name_check; /* r = relaxed, n = normal, s = strict */ 32 unsigned char name_check; /* r = relaxed, n = normal, s = strict */
33 unsigned char errors; /* On error: continue, panic, remount-ro */
29 unsigned short allow_utime;/* permission for setting the [am]time */ 34 unsigned short allow_utime;/* permission for setting the [am]time */
30 unsigned quiet:1, /* set = fake successful chmods and chowns */ 35 unsigned quiet:1, /* set = fake successful chmods and chowns */
31 showexec:1, /* set = only set x bit for com/exe/bat */ 36 showexec:1, /* set = only set x bit for com/exe/bat */
@@ -316,7 +321,7 @@ extern int fat_fill_super(struct super_block *sb, void *data, int silent,
316extern int fat_flush_inodes(struct super_block *sb, struct inode *i1, 321extern int fat_flush_inodes(struct super_block *sb, struct inode *i1,
317 struct inode *i2); 322 struct inode *i2);
318/* fat/misc.c */ 323/* fat/misc.c */
319extern void fat_fs_panic(struct super_block *s, const char *fmt, ...) 324extern void fat_fs_error(struct super_block *s, const char *fmt, ...)
320 __attribute__ ((format (printf, 2, 3))) __cold; 325 __attribute__ ((format (printf, 2, 3))) __cold;
321extern void fat_clusters_flush(struct super_block *sb); 326extern void fat_clusters_flush(struct super_block *sb);
322extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster); 327extern int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster);
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c
index 618f5305c2e4..a81037721a6f 100644
--- a/fs/fat/fatent.c
+++ b/fs/fat/fatent.c
@@ -348,7 +348,7 @@ int fat_ent_read(struct inode *inode, struct fat_entry *fatent, int entry)
348 348
349 if (entry < FAT_START_ENT || sbi->max_cluster <= entry) { 349 if (entry < FAT_START_ENT || sbi->max_cluster <= entry) {
350 fatent_brelse(fatent); 350 fatent_brelse(fatent);
351 fat_fs_panic(sb, "invalid access to FAT (entry 0x%08x)", entry); 351 fat_fs_error(sb, "invalid access to FAT (entry 0x%08x)", entry);
352 return -EIO; 352 return -EIO;
353 } 353 }
354 354
@@ -560,7 +560,7 @@ int fat_free_clusters(struct inode *inode, int cluster)
560 err = cluster; 560 err = cluster;
561 goto error; 561 goto error;
562 } else if (cluster == FAT_ENT_FREE) { 562 } else if (cluster == FAT_ENT_FREE) {
563 fat_fs_panic(sb, "%s: deleting FAT entry beyond EOF", 563 fat_fs_error(sb, "%s: deleting FAT entry beyond EOF",
564 __func__); 564 __func__);
565 err = -EIO; 565 err = -EIO;
566 goto error; 566 goto error;
diff --git a/fs/fat/file.c b/fs/fat/file.c
index e955a56b4e5e..b28ea646ff60 100644
--- a/fs/fat/file.c
+++ b/fs/fat/file.c
@@ -18,106 +18,112 @@
18#include <linux/security.h> 18#include <linux/security.h>
19#include "fat.h" 19#include "fat.h"
20 20
21int fat_generic_ioctl(struct inode *inode, struct file *filp, 21static int fat_ioctl_get_attributes(struct inode *inode, u32 __user *user_attr)
22 unsigned int cmd, unsigned long arg)
23{ 22{
23 u32 attr;
24
25 mutex_lock(&inode->i_mutex);
26 attr = fat_make_attrs(inode);
27 mutex_unlock(&inode->i_mutex);
28
29 return put_user(attr, user_attr);
30}
31
32static int fat_ioctl_set_attributes(struct file *file, u32 __user *user_attr)
33{
34 struct inode *inode = file->f_path.dentry->d_inode;
24 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); 35 struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb);
25 u32 __user *user_attr = (u32 __user *)arg; 36 int is_dir = S_ISDIR(inode->i_mode);
37 u32 attr, oldattr;
38 struct iattr ia;
39 int err;
26 40
27 switch (cmd) { 41 err = get_user(attr, user_attr);
28 case FAT_IOCTL_GET_ATTRIBUTES: 42 if (err)
29 { 43 goto out;
30 u32 attr;
31 44
32 mutex_lock(&inode->i_mutex); 45 mutex_lock(&inode->i_mutex);
33 attr = fat_make_attrs(inode); 46 err = mnt_want_write(file->f_path.mnt);
34 mutex_unlock(&inode->i_mutex); 47 if (err)
48 goto out_unlock_inode;
35 49
36 return put_user(attr, user_attr); 50 /*
51 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
52 * prevents the user from turning us into a VFAT
53 * longname entry. Also, we obviously can't set
54 * any of the NTFS attributes in the high 24 bits.
55 */
56 attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
57 /* Merge in ATTR_VOLUME and ATTR_DIR */
58 attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
59 (is_dir ? ATTR_DIR : 0);
60 oldattr = fat_make_attrs(inode);
61
62 /* Equivalent to a chmod() */
63 ia.ia_valid = ATTR_MODE | ATTR_CTIME;
64 ia.ia_ctime = current_fs_time(inode->i_sb);
65 if (is_dir)
66 ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
67 else {
68 ia.ia_mode = fat_make_mode(sbi, attr,
69 S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
37 } 70 }
38 case FAT_IOCTL_SET_ATTRIBUTES:
39 {
40 u32 attr, oldattr;
41 int err, is_dir = S_ISDIR(inode->i_mode);
42 struct iattr ia;
43 71
44 err = get_user(attr, user_attr); 72 /* The root directory has no attributes */
45 if (err) 73 if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) {
46 return err; 74 err = -EINVAL;
75 goto out_drop_write;
76 }
47 77
48 mutex_lock(&inode->i_mutex); 78 if (sbi->options.sys_immutable &&
49 79 ((attr | oldattr) & ATTR_SYS) &&
50 err = mnt_want_write(filp->f_path.mnt); 80 !capable(CAP_LINUX_IMMUTABLE)) {
51 if (err) 81 err = -EPERM;
52 goto up_no_drop_write; 82 goto out_drop_write;
53 83 }
54 /*
55 * ATTR_VOLUME and ATTR_DIR cannot be changed; this also
56 * prevents the user from turning us into a VFAT
57 * longname entry. Also, we obviously can't set
58 * any of the NTFS attributes in the high 24 bits.
59 */
60 attr &= 0xff & ~(ATTR_VOLUME | ATTR_DIR);
61 /* Merge in ATTR_VOLUME and ATTR_DIR */
62 attr |= (MSDOS_I(inode)->i_attrs & ATTR_VOLUME) |
63 (is_dir ? ATTR_DIR : 0);
64 oldattr = fat_make_attrs(inode);
65
66 /* Equivalent to a chmod() */
67 ia.ia_valid = ATTR_MODE | ATTR_CTIME;
68 ia.ia_ctime = current_fs_time(inode->i_sb);
69 if (is_dir)
70 ia.ia_mode = fat_make_mode(sbi, attr, S_IRWXUGO);
71 else {
72 ia.ia_mode = fat_make_mode(sbi, attr,
73 S_IRUGO | S_IWUGO | (inode->i_mode & S_IXUGO));
74 }
75 84
76 /* The root directory has no attributes */ 85 /*
77 if (inode->i_ino == MSDOS_ROOT_INO && attr != ATTR_DIR) { 86 * The security check is questionable... We single
78 err = -EINVAL; 87 * out the RO attribute for checking by the security
79 goto up; 88 * module, just because it maps to a file mode.
80 } 89 */
90 err = security_inode_setattr(file->f_path.dentry, &ia);
91 if (err)
92 goto out_drop_write;
81 93
82 if (sbi->options.sys_immutable) { 94 /* This MUST be done before doing anything irreversible... */
83 if ((attr | oldattr) & ATTR_SYS) { 95 err = fat_setattr(file->f_path.dentry, &ia);
84 if (!capable(CAP_LINUX_IMMUTABLE)) { 96 if (err)
85 err = -EPERM; 97 goto out_drop_write;
86 goto up; 98
87 } 99 fsnotify_change(file->f_path.dentry, ia.ia_valid);
88 } 100 if (sbi->options.sys_immutable) {
89 } 101 if (attr & ATTR_SYS)
102 inode->i_flags |= S_IMMUTABLE;
103 else
104 inode->i_flags &= S_IMMUTABLE;
105 }
90 106
91 /* 107 fat_save_attrs(inode, attr);
92 * The security check is questionable... We single 108 mark_inode_dirty(inode);
93 * out the RO attribute for checking by the security 109out_drop_write:
94 * module, just because it maps to a file mode. 110 mnt_drop_write(file->f_path.mnt);
95 */ 111out_unlock_inode:
96 err = security_inode_setattr(filp->f_path.dentry, &ia); 112 mutex_unlock(&inode->i_mutex);
97 if (err) 113out:
98 goto up; 114 return err;
99 115}
100 /* This MUST be done before doing anything irreversible... */
101 err = fat_setattr(filp->f_path.dentry, &ia);
102 if (err)
103 goto up;
104
105 fsnotify_change(filp->f_path.dentry, ia.ia_valid);
106 if (sbi->options.sys_immutable) {
107 if (attr & ATTR_SYS)
108 inode->i_flags |= S_IMMUTABLE;
109 else
110 inode->i_flags &= S_IMMUTABLE;
111 }
112 116
113 fat_save_attrs(inode, attr); 117int fat_generic_ioctl(struct inode *inode, struct file *filp,
114 mark_inode_dirty(inode); 118 unsigned int cmd, unsigned long arg)
115up: 119{
116 mnt_drop_write(filp->f_path.mnt); 120 u32 __user *user_attr = (u32 __user *)arg;
117up_no_drop_write: 121
118 mutex_unlock(&inode->i_mutex); 122 switch (cmd) {
119 return err; 123 case FAT_IOCTL_GET_ATTRIBUTES:
120 } 124 return fat_ioctl_get_attributes(inode, user_attr);
125 case FAT_IOCTL_SET_ATTRIBUTES:
126 return fat_ioctl_set_attributes(filp, user_attr);
121 default: 127 default:
122 return -ENOTTY; /* Inappropriate ioctl for device */ 128 return -ENOTTY; /* Inappropriate ioctl for device */
123 } 129 }
@@ -225,7 +231,7 @@ static int fat_free(struct inode *inode, int skip)
225 fatent_brelse(&fatent); 231 fatent_brelse(&fatent);
226 return 0; 232 return 0;
227 } else if (ret == FAT_ENT_FREE) { 233 } else if (ret == FAT_ENT_FREE) {
228 fat_fs_panic(sb, 234 fat_fs_error(sb,
229 "%s: invalid cluster chain (i_pos %lld)", 235 "%s: invalid cluster chain (i_pos %lld)",
230 __func__, MSDOS_I(inode)->i_pos); 236 __func__, MSDOS_I(inode)->i_pos);
231 ret = -EIO; 237 ret = -EIO;
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 51a5ecf9000a..304b411cb8bc 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -76,7 +76,7 @@ static inline int __fat_get_block(struct inode *inode, sector_t iblock,
76 return 0; 76 return 0;
77 77
78 if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) { 78 if (iblock != MSDOS_I(inode)->mmu_private >> sb->s_blocksize_bits) {
79 fat_fs_panic(sb, "corrupted file size (i_pos %lld, %lld)", 79 fat_fs_error(sb, "corrupted file size (i_pos %lld, %lld)",
80 MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private); 80 MSDOS_I(inode)->i_pos, MSDOS_I(inode)->mmu_private);
81 return -EIO; 81 return -EIO;
82 } 82 }
@@ -856,6 +856,12 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt)
856 seq_puts(m, ",flush"); 856 seq_puts(m, ",flush");
857 if (opts->tz_utc) 857 if (opts->tz_utc)
858 seq_puts(m, ",tz=UTC"); 858 seq_puts(m, ",tz=UTC");
859 if (opts->errors == FAT_ERRORS_CONT)
860 seq_puts(m, ",errors=continue");
861 else if (opts->errors == FAT_ERRORS_PANIC)
862 seq_puts(m, ",errors=panic");
863 else
864 seq_puts(m, ",errors=remount-ro");
859 865
860 return 0; 866 return 0;
861} 867}
@@ -868,7 +874,8 @@ enum {
868 Opt_charset, Opt_shortname_lower, Opt_shortname_win95, 874 Opt_charset, Opt_shortname_lower, Opt_shortname_win95,
869 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, 875 Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes,
870 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, 876 Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes,
871 Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err, 877 Opt_obsolate, Opt_flush, Opt_tz_utc, Opt_rodir, Opt_err_cont,
878 Opt_err_panic, Opt_err_ro, Opt_err,
872}; 879};
873 880
874static const match_table_t fat_tokens = { 881static const match_table_t fat_tokens = {
@@ -891,6 +898,11 @@ static const match_table_t fat_tokens = {
891 {Opt_showexec, "showexec"}, 898 {Opt_showexec, "showexec"},
892 {Opt_debug, "debug"}, 899 {Opt_debug, "debug"},
893 {Opt_immutable, "sys_immutable"}, 900 {Opt_immutable, "sys_immutable"},
901 {Opt_flush, "flush"},
902 {Opt_tz_utc, "tz=UTC"},
903 {Opt_err_cont, "errors=continue"},
904 {Opt_err_panic, "errors=panic"},
905 {Opt_err_ro, "errors=remount-ro"},
894 {Opt_obsolate, "conv=binary"}, 906 {Opt_obsolate, "conv=binary"},
895 {Opt_obsolate, "conv=text"}, 907 {Opt_obsolate, "conv=text"},
896 {Opt_obsolate, "conv=auto"}, 908 {Opt_obsolate, "conv=auto"},
@@ -902,8 +914,6 @@ static const match_table_t fat_tokens = {
902 {Opt_obsolate, "cvf_format=%20s"}, 914 {Opt_obsolate, "cvf_format=%20s"},
903 {Opt_obsolate, "cvf_options=%100s"}, 915 {Opt_obsolate, "cvf_options=%100s"},
904 {Opt_obsolate, "posix"}, 916 {Opt_obsolate, "posix"},
905 {Opt_flush, "flush"},
906 {Opt_tz_utc, "tz=UTC"},
907 {Opt_err, NULL}, 917 {Opt_err, NULL},
908}; 918};
909static const match_table_t msdos_tokens = { 919static const match_table_t msdos_tokens = {
@@ -973,6 +983,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
973 opts->numtail = 1; 983 opts->numtail = 1;
974 opts->usefree = opts->nocase = 0; 984 opts->usefree = opts->nocase = 0;
975 opts->tz_utc = 0; 985 opts->tz_utc = 0;
986 opts->errors = FAT_ERRORS_RO;
976 *debug = 0; 987 *debug = 0;
977 988
978 if (!options) 989 if (!options)
@@ -1065,6 +1076,15 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug,
1065 case Opt_tz_utc: 1076 case Opt_tz_utc:
1066 opts->tz_utc = 1; 1077 opts->tz_utc = 1;
1067 break; 1078 break;
1079 case Opt_err_cont:
1080 opts->errors = FAT_ERRORS_CONT;
1081 break;
1082 case Opt_err_panic:
1083 opts->errors = FAT_ERRORS_PANIC;
1084 break;
1085 case Opt_err_ro:
1086 opts->errors = FAT_ERRORS_RO;
1087 break;
1068 1088
1069 /* msdos specific */ 1089 /* msdos specific */
1070 case Opt_dots: 1090 case Opt_dots:
diff --git a/fs/fat/misc.c b/fs/fat/misc.c
index ac39ebcc1496..a6c20473dfd7 100644
--- a/fs/fat/misc.c
+++ b/fs/fat/misc.c
@@ -12,14 +12,19 @@
12#include "fat.h" 12#include "fat.h"
13 13
14/* 14/*
15 * fat_fs_panic reports a severe file system problem and sets the file system 15 * fat_fs_error reports a file system problem that might indicate fa data
16 * read-only. The file system can be made writable again by remounting it. 16 * corruption/inconsistency. Depending on 'errors' mount option the
17 * panic() is called, or error message is printed FAT and nothing is done,
18 * or filesystem is remounted read-only (default behavior).
19 * In case the file system is remounted read-only, it can be made writable
20 * again by remounting it.
17 */ 21 */
18void fat_fs_panic(struct super_block *s, const char *fmt, ...) 22void fat_fs_error(struct super_block *s, const char *fmt, ...)
19{ 23{
24 struct fat_mount_options *opts = &MSDOS_SB(s)->options;
20 va_list args; 25 va_list args;
21 26
22 printk(KERN_ERR "FAT: Filesystem panic (dev %s)\n", s->s_id); 27 printk(KERN_ERR "FAT: Filesystem error (dev %s)\n", s->s_id);
23 28
24 printk(KERN_ERR " "); 29 printk(KERN_ERR " ");
25 va_start(args, fmt); 30 va_start(args, fmt);
@@ -27,13 +32,14 @@ void fat_fs_panic(struct super_block *s, const char *fmt, ...)
27 va_end(args); 32 va_end(args);
28 printk("\n"); 33 printk("\n");
29 34
30 if (!(s->s_flags & MS_RDONLY)) { 35 if (opts->errors == FAT_ERRORS_PANIC)
36 panic(" FAT fs panic from previous error\n");
37 else if (opts->errors == FAT_ERRORS_RO && !(s->s_flags & MS_RDONLY)) {
31 s->s_flags |= MS_RDONLY; 38 s->s_flags |= MS_RDONLY;
32 printk(KERN_ERR " File system has been set read-only\n"); 39 printk(KERN_ERR " File system has been set read-only\n");
33 } 40 }
34} 41}
35 42EXPORT_SYMBOL_GPL(fat_fs_error);
36EXPORT_SYMBOL_GPL(fat_fs_panic);
37 43
38/* Flushes the number of free clusters on FAT32 */ 44/* Flushes the number of free clusters on FAT32 */
39/* XXX: Need to write one per FSINFO block. Currently only writes 1 */ 45/* XXX: Need to write one per FSINFO block. Currently only writes 1 */
@@ -124,7 +130,7 @@ int fat_chain_add(struct inode *inode, int new_dclus, int nr_cluster)
124 mark_inode_dirty(inode); 130 mark_inode_dirty(inode);
125 } 131 }
126 if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) { 132 if (new_fclus != (inode->i_blocks >> (sbi->cluster_bits - 9))) {
127 fat_fs_panic(sb, "clusters badly computed (%d != %llu)", 133 fat_fs_error(sb, "clusters badly computed (%d != %llu)",
128 new_fclus, 134 new_fclus,
129 (llu)(inode->i_blocks >> (sbi->cluster_bits - 9))); 135 (llu)(inode->i_blocks >> (sbi->cluster_bits - 9)));
130 fat_cache_inval_inode(inode); 136 fat_cache_inval_inode(inode);
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index 20f522861355..82f88733b681 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -608,7 +608,7 @@ error_inode:
608 sinfo.bh = NULL; 608 sinfo.bh = NULL;
609 } 609 }
610 if (corrupt < 0) { 610 if (corrupt < 0) {
611 fat_fs_panic(new_dir->i_sb, 611 fat_fs_error(new_dir->i_sb,
612 "%s: Filesystem corrupted (i_pos %lld)", 612 "%s: Filesystem corrupted (i_pos %lld)",
613 __func__, sinfo.i_pos); 613 __func__, sinfo.i_pos);
614 } 614 }
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index b50ecbe97f83..8d6fdcfd41df 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1030,7 +1030,7 @@ error_inode:
1030 sinfo.bh = NULL; 1030 sinfo.bh = NULL;
1031 } 1031 }
1032 if (corrupt < 0) { 1032 if (corrupt < 0) {
1033 fat_fs_panic(new_dir->i_sb, 1033 fat_fs_error(new_dir->i_sb,
1034 "%s: Filesystem corrupted (i_pos %lld)", 1034 "%s: Filesystem corrupted (i_pos %lld)",
1035 __func__, sinfo.i_pos); 1035 __func__, sinfo.i_pos);
1036 } 1036 }
diff --git a/fs/nilfs2/bmap.c b/fs/nilfs2/bmap.c
index 064279e33bbb..36df60b6d8a4 100644
--- a/fs/nilfs2/bmap.c
+++ b/fs/nilfs2/bmap.c
@@ -31,21 +31,26 @@
31#include "dat.h" 31#include "dat.h"
32#include "alloc.h" 32#include "alloc.h"
33 33
34struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
35{
36 return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
37}
38
34int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level, 39int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
35 __u64 *ptrp) 40 __u64 *ptrp)
36{ 41{
37 __u64 ptr; 42 sector_t blocknr;
38 int ret; 43 int ret;
39 44
40 down_read(&bmap->b_sem); 45 down_read(&bmap->b_sem);
41 ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp); 46 ret = bmap->b_ops->bop_lookup(bmap, key, level, ptrp);
42 if (ret < 0) 47 if (ret < 0)
43 goto out; 48 goto out;
44 if (bmap->b_pops->bpop_translate != NULL) { 49 if (NILFS_BMAP_USE_VBN(bmap)) {
45 ret = bmap->b_pops->bpop_translate(bmap, *ptrp, &ptr); 50 ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), *ptrp,
46 if (ret < 0) 51 &blocknr);
47 goto out; 52 if (!ret)
48 *ptrp = ptr; 53 *ptrp = blocknr;
49 } 54 }
50 55
51 out: 56 out:
@@ -53,6 +58,16 @@ int nilfs_bmap_lookup_at_level(struct nilfs_bmap *bmap, __u64 key, int level,
53 return ret; 58 return ret;
54} 59}
55 60
61int nilfs_bmap_lookup_contig(struct nilfs_bmap *bmap, __u64 key, __u64 *ptrp,
62 unsigned maxblocks)
63{
64 int ret;
65
66 down_read(&bmap->b_sem);
67 ret = bmap->b_ops->bop_lookup_contig(bmap, key, ptrp, maxblocks);
68 up_read(&bmap->b_sem);
69 return ret;
70}
56 71
57/** 72/**
58 * nilfs_bmap_lookup - find a record 73 * nilfs_bmap_lookup - find a record
@@ -101,8 +116,7 @@ static int nilfs_bmap_do_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
101 if (n < 0) 116 if (n < 0)
102 return n; 117 return n;
103 ret = nilfs_btree_convert_and_insert( 118 ret = nilfs_btree_convert_and_insert(
104 bmap, key, ptr, keys, ptrs, n, 119 bmap, key, ptr, keys, ptrs, n);
105 NILFS_BMAP_LARGE_LOW, NILFS_BMAP_LARGE_HIGH);
106 if (ret == 0) 120 if (ret == 0)
107 bmap->b_u.u_flags |= NILFS_BMAP_LARGE; 121 bmap->b_u.u_flags |= NILFS_BMAP_LARGE;
108 122
@@ -158,8 +172,7 @@ static int nilfs_bmap_do_delete(struct nilfs_bmap *bmap, __u64 key)
158 if (n < 0) 172 if (n < 0)
159 return n; 173 return n;
160 ret = nilfs_direct_delete_and_convert( 174 ret = nilfs_direct_delete_and_convert(
161 bmap, key, keys, ptrs, n, 175 bmap, key, keys, ptrs, n);
162 NILFS_BMAP_SMALL_LOW, NILFS_BMAP_SMALL_HIGH);
163 if (ret == 0) 176 if (ret == 0)
164 bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE; 177 bmap->b_u.u_flags &= ~NILFS_BMAP_LARGE;
165 178
@@ -417,38 +430,6 @@ void nilfs_bmap_sub_blocks(const struct nilfs_bmap *bmap, int n)
417 mark_inode_dirty(bmap->b_inode); 430 mark_inode_dirty(bmap->b_inode);
418} 431}
419 432
420int nilfs_bmap_get_block(const struct nilfs_bmap *bmap, __u64 ptr,
421 struct buffer_head **bhp)
422{
423 return nilfs_btnode_get(&NILFS_BMAP_I(bmap)->i_btnode_cache,
424 ptr, 0, bhp, 0);
425}
426
427void nilfs_bmap_put_block(const struct nilfs_bmap *bmap,
428 struct buffer_head *bh)
429{
430 brelse(bh);
431}
432
433int nilfs_bmap_get_new_block(const struct nilfs_bmap *bmap, __u64 ptr,
434 struct buffer_head **bhp)
435{
436 int ret;
437
438 ret = nilfs_btnode_get(&NILFS_BMAP_I(bmap)->i_btnode_cache,
439 ptr, 0, bhp, 1);
440 if (ret < 0)
441 return ret;
442 set_buffer_nilfs_volatile(*bhp);
443 return 0;
444}
445
446void nilfs_bmap_delete_block(const struct nilfs_bmap *bmap,
447 struct buffer_head *bh)
448{
449 nilfs_btnode_delete(bh);
450}
451
452__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap, 433__u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *bmap,
453 const struct buffer_head *bh) 434 const struct buffer_head *bh)
454{ 435{
@@ -476,11 +457,6 @@ __u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *bmap, __u64 key)
476 return NILFS_BMAP_INVALID_PTR; 457 return NILFS_BMAP_INVALID_PTR;
477} 458}
478 459
479static struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *bmap)
480{
481 return nilfs_dat_inode(NILFS_I_NILFS(bmap->b_inode));
482}
483
484#define NILFS_BMAP_GROUP_DIV 8 460#define NILFS_BMAP_GROUP_DIV 8
485__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap) 461__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
486{ 462{
@@ -493,64 +469,51 @@ __u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *bmap)
493 (entries_per_group / NILFS_BMAP_GROUP_DIV); 469 (entries_per_group / NILFS_BMAP_GROUP_DIV);
494} 470}
495 471
496static int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap, 472int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *bmap,
497 union nilfs_bmap_ptr_req *req) 473 union nilfs_bmap_ptr_req *req)
498{ 474{
499 return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); 475 return nilfs_dat_prepare_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
500} 476}
501 477
502static void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap, 478void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *bmap,
503 union nilfs_bmap_ptr_req *req) 479 union nilfs_bmap_ptr_req *req)
504{ 480{
505 nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); 481 nilfs_dat_commit_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
506} 482}
507 483
508static void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap, 484void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *bmap,
509 union nilfs_bmap_ptr_req *req) 485 union nilfs_bmap_ptr_req *req)
510{ 486{
511 nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req); 487 nilfs_dat_abort_alloc(nilfs_bmap_get_dat(bmap), &req->bpr_req);
512} 488}
513 489
514static int nilfs_bmap_prepare_start_v(struct nilfs_bmap *bmap, 490int nilfs_bmap_start_v(struct nilfs_bmap *bmap, union nilfs_bmap_ptr_req *req,
515 union nilfs_bmap_ptr_req *req) 491 sector_t blocknr)
516{ 492{
517 return nilfs_dat_prepare_start(nilfs_bmap_get_dat(bmap), &req->bpr_req); 493 struct inode *dat = nilfs_bmap_get_dat(bmap);
518} 494 int ret;
519
520static void nilfs_bmap_commit_start_v(struct nilfs_bmap *bmap,
521 union nilfs_bmap_ptr_req *req,
522 sector_t blocknr)
523{
524 nilfs_dat_commit_start(nilfs_bmap_get_dat(bmap), &req->bpr_req,
525 blocknr);
526}
527 495
528static void nilfs_bmap_abort_start_v(struct nilfs_bmap *bmap, 496 ret = nilfs_dat_prepare_start(dat, &req->bpr_req);
529 union nilfs_bmap_ptr_req *req) 497 if (likely(!ret))
530{ 498 nilfs_dat_commit_start(dat, &req->bpr_req, blocknr);
531 nilfs_dat_abort_start(nilfs_bmap_get_dat(bmap), &req->bpr_req); 499 return ret;
532} 500}
533 501
534static int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap, 502int nilfs_bmap_prepare_end_v(struct nilfs_bmap *bmap,
535 union nilfs_bmap_ptr_req *req) 503 union nilfs_bmap_ptr_req *req)
536{ 504{
537 return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req); 505 return nilfs_dat_prepare_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
538} 506}
539 507
540static void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap, 508void nilfs_bmap_commit_end_v(struct nilfs_bmap *bmap,
541 union nilfs_bmap_ptr_req *req) 509 union nilfs_bmap_ptr_req *req)
542{
543 nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req, 0);
544}
545
546static void nilfs_bmap_commit_end_vmdt(struct nilfs_bmap *bmap,
547 union nilfs_bmap_ptr_req *req)
548{ 510{
549 nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req, 1); 511 nilfs_dat_commit_end(nilfs_bmap_get_dat(bmap), &req->bpr_req,
512 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
550} 513}
551 514
552static void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap, 515void nilfs_bmap_abort_end_v(struct nilfs_bmap *bmap,
553 union nilfs_bmap_ptr_req *req) 516 union nilfs_bmap_ptr_req *req)
554{ 517{
555 nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req); 518 nilfs_dat_abort_end(nilfs_bmap_get_dat(bmap), &req->bpr_req);
556} 519}
@@ -566,128 +529,44 @@ int nilfs_bmap_mark_dirty(const struct nilfs_bmap *bmap, __u64 vblocknr)
566 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr); 529 return nilfs_dat_mark_dirty(nilfs_bmap_get_dat(bmap), vblocknr);
567} 530}
568 531
569int nilfs_bmap_prepare_update(struct nilfs_bmap *bmap, 532int nilfs_bmap_prepare_update_v(struct nilfs_bmap *bmap,
570 union nilfs_bmap_ptr_req *oldreq, 533 union nilfs_bmap_ptr_req *oldreq,
571 union nilfs_bmap_ptr_req *newreq) 534 union nilfs_bmap_ptr_req *newreq)
572{ 535{
536 struct inode *dat = nilfs_bmap_get_dat(bmap);
573 int ret; 537 int ret;
574 538
575 ret = bmap->b_pops->bpop_prepare_end_ptr(bmap, oldreq); 539 ret = nilfs_dat_prepare_end(dat, &oldreq->bpr_req);
576 if (ret < 0) 540 if (ret < 0)
577 return ret; 541 return ret;
578 ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, newreq); 542 ret = nilfs_dat_prepare_alloc(dat, &newreq->bpr_req);
579 if (ret < 0) 543 if (ret < 0)
580 bmap->b_pops->bpop_abort_end_ptr(bmap, oldreq); 544 nilfs_dat_abort_end(dat, &oldreq->bpr_req);
581 545
582 return ret; 546 return ret;
583} 547}
584 548
585void nilfs_bmap_commit_update(struct nilfs_bmap *bmap, 549void nilfs_bmap_commit_update_v(struct nilfs_bmap *bmap,
586 union nilfs_bmap_ptr_req *oldreq, 550 union nilfs_bmap_ptr_req *oldreq,
587 union nilfs_bmap_ptr_req *newreq) 551 union nilfs_bmap_ptr_req *newreq)
588{ 552{
589 bmap->b_pops->bpop_commit_end_ptr(bmap, oldreq); 553 struct inode *dat = nilfs_bmap_get_dat(bmap);
590 bmap->b_pops->bpop_commit_alloc_ptr(bmap, newreq);
591}
592 554
593void nilfs_bmap_abort_update(struct nilfs_bmap *bmap, 555 nilfs_dat_commit_end(dat, &oldreq->bpr_req,
594 union nilfs_bmap_ptr_req *oldreq, 556 bmap->b_ptr_type == NILFS_BMAP_PTR_VS);
595 union nilfs_bmap_ptr_req *newreq) 557 nilfs_dat_commit_alloc(dat, &newreq->bpr_req);
596{
597 bmap->b_pops->bpop_abort_end_ptr(bmap, oldreq);
598 bmap->b_pops->bpop_abort_alloc_ptr(bmap, newreq);
599} 558}
600 559
601static int nilfs_bmap_translate_v(const struct nilfs_bmap *bmap, __u64 ptr, 560void nilfs_bmap_abort_update_v(struct nilfs_bmap *bmap,
602 __u64 *ptrp) 561 union nilfs_bmap_ptr_req *oldreq,
562 union nilfs_bmap_ptr_req *newreq)
603{ 563{
604 sector_t blocknr; 564 struct inode *dat = nilfs_bmap_get_dat(bmap);
605 int ret;
606
607 ret = nilfs_dat_translate(nilfs_bmap_get_dat(bmap), ptr, &blocknr);
608 if (ret < 0)
609 return ret;
610 if (ptrp != NULL)
611 *ptrp = blocknr;
612 return 0;
613}
614 565
615static int nilfs_bmap_prepare_alloc_p(struct nilfs_bmap *bmap, 566 nilfs_dat_abort_end(dat, &oldreq->bpr_req);
616 union nilfs_bmap_ptr_req *req) 567 nilfs_dat_abort_alloc(dat, &newreq->bpr_req);
617{
618 /* ignore target ptr */
619 req->bpr_ptr = bmap->b_last_allocated_ptr++;
620 return 0;
621} 568}
622 569
623static void nilfs_bmap_commit_alloc_p(struct nilfs_bmap *bmap,
624 union nilfs_bmap_ptr_req *req)
625{
626 /* do nothing */
627}
628
629static void nilfs_bmap_abort_alloc_p(struct nilfs_bmap *bmap,
630 union nilfs_bmap_ptr_req *req)
631{
632 bmap->b_last_allocated_ptr--;
633}
634
635static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_v = {
636 .bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_v,
637 .bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_v,
638 .bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_v,
639 .bpop_prepare_start_ptr = nilfs_bmap_prepare_start_v,
640 .bpop_commit_start_ptr = nilfs_bmap_commit_start_v,
641 .bpop_abort_start_ptr = nilfs_bmap_abort_start_v,
642 .bpop_prepare_end_ptr = nilfs_bmap_prepare_end_v,
643 .bpop_commit_end_ptr = nilfs_bmap_commit_end_v,
644 .bpop_abort_end_ptr = nilfs_bmap_abort_end_v,
645
646 .bpop_translate = nilfs_bmap_translate_v,
647};
648
649static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_vmdt = {
650 .bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_v,
651 .bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_v,
652 .bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_v,
653 .bpop_prepare_start_ptr = nilfs_bmap_prepare_start_v,
654 .bpop_commit_start_ptr = nilfs_bmap_commit_start_v,
655 .bpop_abort_start_ptr = nilfs_bmap_abort_start_v,
656 .bpop_prepare_end_ptr = nilfs_bmap_prepare_end_v,
657 .bpop_commit_end_ptr = nilfs_bmap_commit_end_vmdt,
658 .bpop_abort_end_ptr = nilfs_bmap_abort_end_v,
659
660 .bpop_translate = nilfs_bmap_translate_v,
661};
662
663static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_p = {
664 .bpop_prepare_alloc_ptr = nilfs_bmap_prepare_alloc_p,
665 .bpop_commit_alloc_ptr = nilfs_bmap_commit_alloc_p,
666 .bpop_abort_alloc_ptr = nilfs_bmap_abort_alloc_p,
667 .bpop_prepare_start_ptr = NULL,
668 .bpop_commit_start_ptr = NULL,
669 .bpop_abort_start_ptr = NULL,
670 .bpop_prepare_end_ptr = NULL,
671 .bpop_commit_end_ptr = NULL,
672 .bpop_abort_end_ptr = NULL,
673
674 .bpop_translate = NULL,
675};
676
677static const struct nilfs_bmap_ptr_operations nilfs_bmap_ptr_ops_gc = {
678 .bpop_prepare_alloc_ptr = NULL,
679 .bpop_commit_alloc_ptr = NULL,
680 .bpop_abort_alloc_ptr = NULL,
681 .bpop_prepare_start_ptr = NULL,
682 .bpop_commit_start_ptr = NULL,
683 .bpop_abort_start_ptr = NULL,
684 .bpop_prepare_end_ptr = NULL,
685 .bpop_commit_end_ptr = NULL,
686 .bpop_abort_end_ptr = NULL,
687
688 .bpop_translate = NULL,
689};
690
691static struct lock_class_key nilfs_bmap_dat_lock_key; 570static struct lock_class_key nilfs_bmap_dat_lock_key;
692 571
693/** 572/**
@@ -714,31 +593,26 @@ int nilfs_bmap_read(struct nilfs_bmap *bmap, struct nilfs_inode *raw_inode)
714 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; 593 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
715 switch (bmap->b_inode->i_ino) { 594 switch (bmap->b_inode->i_ino) {
716 case NILFS_DAT_INO: 595 case NILFS_DAT_INO:
717 bmap->b_pops = &nilfs_bmap_ptr_ops_p; 596 bmap->b_ptr_type = NILFS_BMAP_PTR_P;
718 bmap->b_last_allocated_key = 0; /* XXX: use macro */ 597 bmap->b_last_allocated_key = 0;
719 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT; 598 bmap->b_last_allocated_ptr = NILFS_BMAP_NEW_PTR_INIT;
720 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key); 599 lockdep_set_class(&bmap->b_sem, &nilfs_bmap_dat_lock_key);
721 break; 600 break;
722 case NILFS_CPFILE_INO: 601 case NILFS_CPFILE_INO:
723 case NILFS_SUFILE_INO: 602 case NILFS_SUFILE_INO:
724 bmap->b_pops = &nilfs_bmap_ptr_ops_vmdt; 603 bmap->b_ptr_type = NILFS_BMAP_PTR_VS;
725 bmap->b_last_allocated_key = 0; /* XXX: use macro */ 604 bmap->b_last_allocated_key = 0;
726 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 605 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
727 break; 606 break;
728 default: 607 default:
729 bmap->b_pops = &nilfs_bmap_ptr_ops_v; 608 bmap->b_ptr_type = NILFS_BMAP_PTR_VM;
730 bmap->b_last_allocated_key = 0; /* XXX: use macro */ 609 bmap->b_last_allocated_key = 0;
731 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 610 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
732 break; 611 break;
733 } 612 }
734 613
735 return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ? 614 return (bmap->b_u.u_flags & NILFS_BMAP_LARGE) ?
736 nilfs_btree_init(bmap, 615 nilfs_btree_init(bmap) : nilfs_direct_init(bmap);
737 NILFS_BMAP_LARGE_LOW,
738 NILFS_BMAP_LARGE_HIGH) :
739 nilfs_direct_init(bmap,
740 NILFS_BMAP_SMALL_LOW,
741 NILFS_BMAP_SMALL_HIGH);
742} 616}
743 617
744/** 618/**
@@ -764,7 +638,7 @@ void nilfs_bmap_init_gc(struct nilfs_bmap *bmap)
764 memset(&bmap->b_u, 0, NILFS_BMAP_SIZE); 638 memset(&bmap->b_u, 0, NILFS_BMAP_SIZE);
765 init_rwsem(&bmap->b_sem); 639 init_rwsem(&bmap->b_sem);
766 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode; 640 bmap->b_inode = &NILFS_BMAP_I(bmap)->vfs_inode;
767 bmap->b_pops = &nilfs_bmap_ptr_ops_gc; 641 bmap->b_ptr_type = NILFS_BMAP_PTR_U;
768 bmap->b_last_allocated_key = 0; 642 bmap->b_last_allocated_key = 0;
769 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR; 643 bmap->b_last_allocated_ptr = NILFS_BMAP_INVALID_PTR;
770 bmap->b_state = 0; 644 bmap->b_state = 0;
diff --git a/fs/nilfs2/bmap.h b/fs/nilfs2/bmap.h
index 4f2708abb1ba..b2890cdcef12 100644
--- a/fs/nilfs2/bmap.h
+++ b/fs/nilfs2/bmap.h
@@ -64,6 +64,8 @@ struct nilfs_bmap_stats {
64 */ 64 */
65struct nilfs_bmap_operations { 65struct nilfs_bmap_operations {
66 int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *); 66 int (*bop_lookup)(const struct nilfs_bmap *, __u64, int, __u64 *);
67 int (*bop_lookup_contig)(const struct nilfs_bmap *, __u64, __u64 *,
68 unsigned);
67 int (*bop_insert)(struct nilfs_bmap *, __u64, __u64); 69 int (*bop_insert)(struct nilfs_bmap *, __u64, __u64);
68 int (*bop_delete)(struct nilfs_bmap *, __u64); 70 int (*bop_delete)(struct nilfs_bmap *, __u64);
69 void (*bop_clear)(struct nilfs_bmap *); 71 void (*bop_clear)(struct nilfs_bmap *);
@@ -86,34 +88,6 @@ struct nilfs_bmap_operations {
86}; 88};
87 89
88 90
89/**
90 * struct nilfs_bmap_ptr_operations - bmap ptr operation table
91 */
92struct nilfs_bmap_ptr_operations {
93 int (*bpop_prepare_alloc_ptr)(struct nilfs_bmap *,
94 union nilfs_bmap_ptr_req *);
95 void (*bpop_commit_alloc_ptr)(struct nilfs_bmap *,
96 union nilfs_bmap_ptr_req *);
97 void (*bpop_abort_alloc_ptr)(struct nilfs_bmap *,
98 union nilfs_bmap_ptr_req *);
99 int (*bpop_prepare_start_ptr)(struct nilfs_bmap *,
100 union nilfs_bmap_ptr_req *);
101 void (*bpop_commit_start_ptr)(struct nilfs_bmap *,
102 union nilfs_bmap_ptr_req *,
103 sector_t);
104 void (*bpop_abort_start_ptr)(struct nilfs_bmap *,
105 union nilfs_bmap_ptr_req *);
106 int (*bpop_prepare_end_ptr)(struct nilfs_bmap *,
107 union nilfs_bmap_ptr_req *);
108 void (*bpop_commit_end_ptr)(struct nilfs_bmap *,
109 union nilfs_bmap_ptr_req *);
110 void (*bpop_abort_end_ptr)(struct nilfs_bmap *,
111 union nilfs_bmap_ptr_req *);
112
113 int (*bpop_translate)(const struct nilfs_bmap *, __u64, __u64 *);
114};
115
116
117#define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(__le64)) 91#define NILFS_BMAP_SIZE (NILFS_INODE_BMAP_SIZE * sizeof(__le64))
118#define NILFS_BMAP_KEY_BIT (sizeof(unsigned long) * 8 /* CHAR_BIT */) 92#define NILFS_BMAP_KEY_BIT (sizeof(unsigned long) * 8 /* CHAR_BIT */)
119#define NILFS_BMAP_NEW_PTR_INIT \ 93#define NILFS_BMAP_NEW_PTR_INIT \
@@ -131,11 +105,9 @@ static inline int nilfs_bmap_is_new_ptr(unsigned long ptr)
131 * @b_sem: semaphore 105 * @b_sem: semaphore
132 * @b_inode: owner of bmap 106 * @b_inode: owner of bmap
133 * @b_ops: bmap operation table 107 * @b_ops: bmap operation table
134 * @b_pops: bmap ptr operation table
135 * @b_low: low watermark of conversion
136 * @b_high: high watermark of conversion
137 * @b_last_allocated_key: last allocated key for data block 108 * @b_last_allocated_key: last allocated key for data block
138 * @b_last_allocated_ptr: last allocated ptr for data block 109 * @b_last_allocated_ptr: last allocated ptr for data block
110 * @b_ptr_type: pointer type
139 * @b_state: state 111 * @b_state: state
140 */ 112 */
141struct nilfs_bmap { 113struct nilfs_bmap {
@@ -146,14 +118,22 @@ struct nilfs_bmap {
146 struct rw_semaphore b_sem; 118 struct rw_semaphore b_sem;
147 struct inode *b_inode; 119 struct inode *b_inode;
148 const struct nilfs_bmap_operations *b_ops; 120 const struct nilfs_bmap_operations *b_ops;
149 const struct nilfs_bmap_ptr_operations *b_pops;
150 __u64 b_low;
151 __u64 b_high;
152 __u64 b_last_allocated_key; 121 __u64 b_last_allocated_key;
153 __u64 b_last_allocated_ptr; 122 __u64 b_last_allocated_ptr;
123 int b_ptr_type;
154 int b_state; 124 int b_state;
155}; 125};
156 126
127/* pointer type */
128#define NILFS_BMAP_PTR_P 0 /* physical block number (i.e. LBN) */
129#define NILFS_BMAP_PTR_VS 1 /* virtual block number (single
130 version) */
131#define NILFS_BMAP_PTR_VM 2 /* virtual block number (has multiple
132 versions) */
133#define NILFS_BMAP_PTR_U (-1) /* never perform pointer operations */
134
135#define NILFS_BMAP_USE_VBN(bmap) ((bmap)->b_ptr_type > 0)
136
157/* state */ 137/* state */
158#define NILFS_BMAP_DIRTY 0x00000001 138#define NILFS_BMAP_DIRTY 0x00000001
159 139
@@ -162,6 +142,7 @@ int nilfs_bmap_test_and_clear_dirty(struct nilfs_bmap *);
162int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *); 142int nilfs_bmap_read(struct nilfs_bmap *, struct nilfs_inode *);
163void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *); 143void nilfs_bmap_write(struct nilfs_bmap *, struct nilfs_inode *);
164int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *); 144int nilfs_bmap_lookup(struct nilfs_bmap *, unsigned long, unsigned long *);
145int nilfs_bmap_lookup_contig(struct nilfs_bmap *, __u64, __u64 *, unsigned);
165int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long); 146int nilfs_bmap_insert(struct nilfs_bmap *, unsigned long, unsigned long);
166int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long); 147int nilfs_bmap_delete(struct nilfs_bmap *, unsigned long);
167int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *); 148int nilfs_bmap_last_key(struct nilfs_bmap *, unsigned long *);
@@ -182,7 +163,67 @@ void nilfs_bmap_commit_gcdat(struct nilfs_bmap *, struct nilfs_bmap *);
182/* 163/*
183 * Internal use only 164 * Internal use only
184 */ 165 */
166struct inode *nilfs_bmap_get_dat(const struct nilfs_bmap *);
167int nilfs_bmap_prepare_alloc_v(struct nilfs_bmap *,
168 union nilfs_bmap_ptr_req *);
169void nilfs_bmap_commit_alloc_v(struct nilfs_bmap *,
170 union nilfs_bmap_ptr_req *);
171void nilfs_bmap_abort_alloc_v(struct nilfs_bmap *,
172 union nilfs_bmap_ptr_req *);
185 173
174static inline int nilfs_bmap_prepare_alloc_ptr(struct nilfs_bmap *bmap,
175 union nilfs_bmap_ptr_req *req)
176{
177 if (NILFS_BMAP_USE_VBN(bmap))
178 return nilfs_bmap_prepare_alloc_v(bmap, req);
179 /* ignore target ptr */
180 req->bpr_ptr = bmap->b_last_allocated_ptr++;
181 return 0;
182}
183
184static inline void nilfs_bmap_commit_alloc_ptr(struct nilfs_bmap *bmap,
185 union nilfs_bmap_ptr_req *req)
186{
187 if (NILFS_BMAP_USE_VBN(bmap))
188 nilfs_bmap_commit_alloc_v(bmap, req);
189}
190
191static inline void nilfs_bmap_abort_alloc_ptr(struct nilfs_bmap *bmap,
192 union nilfs_bmap_ptr_req *req)
193{
194 if (NILFS_BMAP_USE_VBN(bmap))
195 nilfs_bmap_abort_alloc_v(bmap, req);
196 else
197 bmap->b_last_allocated_ptr--;
198}
199
200int nilfs_bmap_prepare_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
201void nilfs_bmap_commit_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
202void nilfs_bmap_abort_end_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *);
203
204static inline int nilfs_bmap_prepare_end_ptr(struct nilfs_bmap *bmap,
205 union nilfs_bmap_ptr_req *req)
206{
207 return NILFS_BMAP_USE_VBN(bmap) ?
208 nilfs_bmap_prepare_end_v(bmap, req) : 0;
209}
210
211static inline void nilfs_bmap_commit_end_ptr(struct nilfs_bmap *bmap,
212 union nilfs_bmap_ptr_req *req)
213{
214 if (NILFS_BMAP_USE_VBN(bmap))
215 nilfs_bmap_commit_end_v(bmap, req);
216}
217
218static inline void nilfs_bmap_abort_end_ptr(struct nilfs_bmap *bmap,
219 union nilfs_bmap_ptr_req *req)
220{
221 if (NILFS_BMAP_USE_VBN(bmap))
222 nilfs_bmap_abort_end_v(bmap, req);
223}
224
225int nilfs_bmap_start_v(struct nilfs_bmap *, union nilfs_bmap_ptr_req *,
226 sector_t);
186int nilfs_bmap_move_v(const struct nilfs_bmap *, __u64, sector_t); 227int nilfs_bmap_move_v(const struct nilfs_bmap *, __u64, sector_t);
187int nilfs_bmap_mark_dirty(const struct nilfs_bmap *, __u64); 228int nilfs_bmap_mark_dirty(const struct nilfs_bmap *, __u64);
188 229
@@ -193,28 +234,20 @@ __u64 nilfs_bmap_data_get_key(const struct nilfs_bmap *,
193__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64); 234__u64 nilfs_bmap_find_target_seq(const struct nilfs_bmap *, __u64);
194__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *); 235__u64 nilfs_bmap_find_target_in_group(const struct nilfs_bmap *);
195 236
196int nilfs_bmap_prepare_update(struct nilfs_bmap *, 237int nilfs_bmap_prepare_update_v(struct nilfs_bmap *,
197 union nilfs_bmap_ptr_req *, 238 union nilfs_bmap_ptr_req *,
198 union nilfs_bmap_ptr_req *); 239 union nilfs_bmap_ptr_req *);
199void nilfs_bmap_commit_update(struct nilfs_bmap *, 240void nilfs_bmap_commit_update_v(struct nilfs_bmap *,
200 union nilfs_bmap_ptr_req *, 241 union nilfs_bmap_ptr_req *,
201 union nilfs_bmap_ptr_req *); 242 union nilfs_bmap_ptr_req *);
202void nilfs_bmap_abort_update(struct nilfs_bmap *, 243void nilfs_bmap_abort_update_v(struct nilfs_bmap *,
203 union nilfs_bmap_ptr_req *, 244 union nilfs_bmap_ptr_req *,
204 union nilfs_bmap_ptr_req *); 245 union nilfs_bmap_ptr_req *);
205 246
206void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int); 247void nilfs_bmap_add_blocks(const struct nilfs_bmap *, int);
207void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int); 248void nilfs_bmap_sub_blocks(const struct nilfs_bmap *, int);
208 249
209 250
210int nilfs_bmap_get_block(const struct nilfs_bmap *, __u64,
211 struct buffer_head **);
212void nilfs_bmap_put_block(const struct nilfs_bmap *, struct buffer_head *);
213int nilfs_bmap_get_new_block(const struct nilfs_bmap *, __u64,
214 struct buffer_head **);
215void nilfs_bmap_delete_block(const struct nilfs_bmap *, struct buffer_head *);
216
217
218/* Assume that bmap semaphore is locked. */ 251/* Assume that bmap semaphore is locked. */
219static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap) 252static inline int nilfs_bmap_dirty(const struct nilfs_bmap *bmap)
220{ 253{
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index 4cc07b2c30e0..7e0b61be212e 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -46,15 +46,18 @@ void nilfs_btnode_cache_init_once(struct address_space *btnc)
46 INIT_LIST_HEAD(&btnc->i_mmap_nonlinear); 46 INIT_LIST_HEAD(&btnc->i_mmap_nonlinear);
47} 47}
48 48
49static struct address_space_operations def_btnode_aops; 49static struct address_space_operations def_btnode_aops = {
50 .sync_page = block_sync_page,
51};
50 52
51void nilfs_btnode_cache_init(struct address_space *btnc) 53void nilfs_btnode_cache_init(struct address_space *btnc,
54 struct backing_dev_info *bdi)
52{ 55{
53 btnc->host = NULL; /* can safely set to host inode ? */ 56 btnc->host = NULL; /* can safely set to host inode ? */
54 btnc->flags = 0; 57 btnc->flags = 0;
55 mapping_set_gfp_mask(btnc, GFP_NOFS); 58 mapping_set_gfp_mask(btnc, GFP_NOFS);
56 btnc->assoc_mapping = NULL; 59 btnc->assoc_mapping = NULL;
57 btnc->backing_dev_info = &default_backing_dev_info; 60 btnc->backing_dev_info = bdi;
58 btnc->a_ops = &def_btnode_aops; 61 btnc->a_ops = &def_btnode_aops;
59} 62}
60 63
diff --git a/fs/nilfs2/btnode.h b/fs/nilfs2/btnode.h
index 35faa86444a7..3e2275172ed6 100644
--- a/fs/nilfs2/btnode.h
+++ b/fs/nilfs2/btnode.h
@@ -38,7 +38,7 @@ struct nilfs_btnode_chkey_ctxt {
38}; 38};
39 39
40void nilfs_btnode_cache_init_once(struct address_space *); 40void nilfs_btnode_cache_init_once(struct address_space *);
41void nilfs_btnode_cache_init(struct address_space *); 41void nilfs_btnode_cache_init(struct address_space *, struct backing_dev_info *);
42void nilfs_btnode_cache_clear(struct address_space *); 42void nilfs_btnode_cache_clear(struct address_space *);
43int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t, 43int nilfs_btnode_submit_block(struct address_space *, __u64, sector_t,
44 struct buffer_head **, int); 44 struct buffer_head **, int);
diff --git a/fs/nilfs2/btree.c b/fs/nilfs2/btree.c
index 6b37a2767293..aa412724b64e 100644
--- a/fs/nilfs2/btree.c
+++ b/fs/nilfs2/btree.c
@@ -29,6 +29,7 @@
29#include "btnode.h" 29#include "btnode.h"
30#include "btree.h" 30#include "btree.h"
31#include "alloc.h" 31#include "alloc.h"
32#include "dat.h"
32 33
33/** 34/**
34 * struct nilfs_btree_path - A path on which B-tree operations are executed 35 * struct nilfs_btree_path - A path on which B-tree operations are executed
@@ -109,8 +110,7 @@ static void nilfs_btree_clear_path(const struct nilfs_btree *btree,
109 level < NILFS_BTREE_LEVEL_MAX; 110 level < NILFS_BTREE_LEVEL_MAX;
110 level++) { 111 level++) {
111 if (path[level].bp_bh != NULL) { 112 if (path[level].bp_bh != NULL) {
112 nilfs_bmap_put_block(&btree->bt_bmap, 113 brelse(path[level].bp_bh);
113 path[level].bp_bh);
114 path[level].bp_bh = NULL; 114 path[level].bp_bh = NULL;
115 } 115 }
116 /* sib_bh is released or deleted by prepare or commit 116 /* sib_bh is released or deleted by prepare or commit
@@ -123,10 +123,29 @@ static void nilfs_btree_clear_path(const struct nilfs_btree *btree,
123 } 123 }
124} 124}
125 125
126
127/* 126/*
128 * B-tree node operations 127 * B-tree node operations
129 */ 128 */
129static int nilfs_btree_get_block(const struct nilfs_btree *btree, __u64 ptr,
130 struct buffer_head **bhp)
131{
132 struct address_space *btnc =
133 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
134 return nilfs_btnode_get(btnc, ptr, 0, bhp, 0);
135}
136
137static int nilfs_btree_get_new_block(const struct nilfs_btree *btree,
138 __u64 ptr, struct buffer_head **bhp)
139{
140 struct address_space *btnc =
141 &NILFS_BMAP_I((struct nilfs_bmap *)btree)->i_btnode_cache;
142 int ret;
143
144 ret = nilfs_btnode_get(btnc, ptr, 0, bhp, 1);
145 if (!ret)
146 set_buffer_nilfs_volatile(*bhp);
147 return ret;
148}
130 149
131static inline int 150static inline int
132nilfs_btree_node_get_flags(const struct nilfs_btree *btree, 151nilfs_btree_node_get_flags(const struct nilfs_btree *btree,
@@ -488,8 +507,7 @@ static int nilfs_btree_do_lookup(const struct nilfs_btree *btree,
488 path[level].bp_index = index; 507 path[level].bp_index = index;
489 508
490 for (level--; level >= minlevel; level--) { 509 for (level--; level >= minlevel; level--) {
491 ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr, 510 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
492 &path[level].bp_bh);
493 if (ret < 0) 511 if (ret < 0)
494 return ret; 512 return ret;
495 node = nilfs_btree_get_nonroot_node(btree, path, level); 513 node = nilfs_btree_get_nonroot_node(btree, path, level);
@@ -535,8 +553,7 @@ static int nilfs_btree_do_lookup_last(const struct nilfs_btree *btree,
535 path[level].bp_index = index; 553 path[level].bp_index = index;
536 554
537 for (level--; level > 0; level--) { 555 for (level--; level > 0; level--) {
538 ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr, 556 ret = nilfs_btree_get_block(btree, ptr, &path[level].bp_bh);
539 &path[level].bp_bh);
540 if (ret < 0) 557 if (ret < 0)
541 return ret; 558 return ret;
542 node = nilfs_btree_get_nonroot_node(btree, path, level); 559 node = nilfs_btree_get_nonroot_node(btree, path, level);
@@ -579,6 +596,87 @@ static int nilfs_btree_lookup(const struct nilfs_bmap *bmap,
579 return ret; 596 return ret;
580} 597}
581 598
599static int nilfs_btree_lookup_contig(const struct nilfs_bmap *bmap,
600 __u64 key, __u64 *ptrp, unsigned maxblocks)
601{
602 struct nilfs_btree *btree = (struct nilfs_btree *)bmap;
603 struct nilfs_btree_path *path;
604 struct nilfs_btree_node *node;
605 struct inode *dat = NULL;
606 __u64 ptr, ptr2;
607 sector_t blocknr;
608 int level = NILFS_BTREE_LEVEL_NODE_MIN;
609 int ret, cnt, index, maxlevel;
610
611 path = nilfs_btree_alloc_path(btree);
612 if (path == NULL)
613 return -ENOMEM;
614 nilfs_btree_init_path(btree, path);
615 ret = nilfs_btree_do_lookup(btree, path, key, &ptr, level);
616 if (ret < 0)
617 goto out;
618
619 if (NILFS_BMAP_USE_VBN(bmap)) {
620 dat = nilfs_bmap_get_dat(bmap);
621 ret = nilfs_dat_translate(dat, ptr, &blocknr);
622 if (ret < 0)
623 goto out;
624 ptr = blocknr;
625 }
626 cnt = 1;
627 if (cnt == maxblocks)
628 goto end;
629
630 maxlevel = nilfs_btree_height(btree) - 1;
631 node = nilfs_btree_get_node(btree, path, level);
632 index = path[level].bp_index + 1;
633 for (;;) {
634 while (index < nilfs_btree_node_get_nchildren(btree, node)) {
635 if (nilfs_btree_node_get_key(btree, node, index) !=
636 key + cnt)
637 goto end;
638 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
639 if (dat) {
640 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
641 if (ret < 0)
642 goto out;
643 ptr2 = blocknr;
644 }
645 if (ptr2 != ptr + cnt || ++cnt == maxblocks)
646 goto end;
647 index++;
648 continue;
649 }
650 if (level == maxlevel)
651 break;
652
653 /* look-up right sibling node */
654 node = nilfs_btree_get_node(btree, path, level + 1);
655 index = path[level + 1].bp_index + 1;
656 if (index >= nilfs_btree_node_get_nchildren(btree, node) ||
657 nilfs_btree_node_get_key(btree, node, index) != key + cnt)
658 break;
659 ptr2 = nilfs_btree_node_get_ptr(btree, node, index);
660 path[level + 1].bp_index = index;
661
662 brelse(path[level].bp_bh);
663 path[level].bp_bh = NULL;
664 ret = nilfs_btree_get_block(btree, ptr2, &path[level].bp_bh);
665 if (ret < 0)
666 goto out;
667 node = nilfs_btree_get_nonroot_node(btree, path, level);
668 index = 0;
669 path[level].bp_index = index;
670 }
671 end:
672 *ptrp = ptr;
673 ret = cnt;
674 out:
675 nilfs_btree_clear_path(btree, path);
676 nilfs_btree_free_path(btree, path);
677 return ret;
678}
679
582static void nilfs_btree_promote_key(struct nilfs_btree *btree, 680static void nilfs_btree_promote_key(struct nilfs_btree *btree,
583 struct nilfs_btree_path *path, 681 struct nilfs_btree_path *path,
584 int level, __u64 key) 682 int level, __u64 key)
@@ -669,13 +767,13 @@ static void nilfs_btree_carry_left(struct nilfs_btree *btree,
669 nilfs_btree_node_get_key(btree, node, 0)); 767 nilfs_btree_node_get_key(btree, node, 0));
670 768
671 if (move) { 769 if (move) {
672 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh); 770 brelse(path[level].bp_bh);
673 path[level].bp_bh = path[level].bp_sib_bh; 771 path[level].bp_bh = path[level].bp_sib_bh;
674 path[level].bp_sib_bh = NULL; 772 path[level].bp_sib_bh = NULL;
675 path[level].bp_index += lnchildren; 773 path[level].bp_index += lnchildren;
676 path[level + 1].bp_index--; 774 path[level + 1].bp_index--;
677 } else { 775 } else {
678 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 776 brelse(path[level].bp_sib_bh);
679 path[level].bp_sib_bh = NULL; 777 path[level].bp_sib_bh = NULL;
680 path[level].bp_index -= n; 778 path[level].bp_index -= n;
681 } 779 }
@@ -722,14 +820,14 @@ static void nilfs_btree_carry_right(struct nilfs_btree *btree,
722 path[level + 1].bp_index--; 820 path[level + 1].bp_index--;
723 821
724 if (move) { 822 if (move) {
725 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh); 823 brelse(path[level].bp_bh);
726 path[level].bp_bh = path[level].bp_sib_bh; 824 path[level].bp_bh = path[level].bp_sib_bh;
727 path[level].bp_sib_bh = NULL; 825 path[level].bp_sib_bh = NULL;
728 path[level].bp_index -= 826 path[level].bp_index -=
729 nilfs_btree_node_get_nchildren(btree, node); 827 nilfs_btree_node_get_nchildren(btree, node);
730 path[level + 1].bp_index++; 828 path[level + 1].bp_index++;
731 } else { 829 } else {
732 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 830 brelse(path[level].bp_sib_bh);
733 path[level].bp_sib_bh = NULL; 831 path[level].bp_sib_bh = NULL;
734 } 832 }
735 833
@@ -781,7 +879,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
781 *keyp = nilfs_btree_node_get_key(btree, right, 0); 879 *keyp = nilfs_btree_node_get_key(btree, right, 0);
782 *ptrp = path[level].bp_newreq.bpr_ptr; 880 *ptrp = path[level].bp_newreq.bpr_ptr;
783 881
784 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_bh); 882 brelse(path[level].bp_bh);
785 path[level].bp_bh = path[level].bp_sib_bh; 883 path[level].bp_bh = path[level].bp_sib_bh;
786 path[level].bp_sib_bh = NULL; 884 path[level].bp_sib_bh = NULL;
787 } else { 885 } else {
@@ -790,7 +888,7 @@ static void nilfs_btree_split(struct nilfs_btree *btree,
790 *keyp = nilfs_btree_node_get_key(btree, right, 0); 888 *keyp = nilfs_btree_node_get_key(btree, right, 0);
791 *ptrp = path[level].bp_newreq.bpr_ptr; 889 *ptrp = path[level].bp_newreq.bpr_ptr;
792 890
793 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 891 brelse(path[level].bp_sib_bh);
794 path[level].bp_sib_bh = NULL; 892 path[level].bp_sib_bh = NULL;
795 } 893 }
796 894
@@ -897,12 +995,12 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
897 level = NILFS_BTREE_LEVEL_DATA; 995 level = NILFS_BTREE_LEVEL_DATA;
898 996
899 /* allocate a new ptr for data block */ 997 /* allocate a new ptr for data block */
900 if (btree->bt_ops->btop_find_target != NULL) 998 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
901 path[level].bp_newreq.bpr_ptr = 999 path[level].bp_newreq.bpr_ptr =
902 btree->bt_ops->btop_find_target(btree, path, key); 1000 nilfs_btree_find_target_v(btree, path, key);
903 1001
904 ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr( 1002 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
905 &btree->bt_bmap, &path[level].bp_newreq); 1003 &path[level].bp_newreq);
906 if (ret < 0) 1004 if (ret < 0)
907 goto err_out_data; 1005 goto err_out_data;
908 1006
@@ -924,8 +1022,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
924 if (pindex > 0) { 1022 if (pindex > 0) {
925 sibptr = nilfs_btree_node_get_ptr(btree, parent, 1023 sibptr = nilfs_btree_node_get_ptr(btree, parent,
926 pindex - 1); 1024 pindex - 1);
927 ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr, 1025 ret = nilfs_btree_get_block(btree, sibptr, &bh);
928 &bh);
929 if (ret < 0) 1026 if (ret < 0)
930 goto err_out_child_node; 1027 goto err_out_child_node;
931 sib = (struct nilfs_btree_node *)bh->b_data; 1028 sib = (struct nilfs_btree_node *)bh->b_data;
@@ -936,7 +1033,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
936 stats->bs_nblocks++; 1033 stats->bs_nblocks++;
937 goto out; 1034 goto out;
938 } else 1035 } else
939 nilfs_bmap_put_block(&btree->bt_bmap, bh); 1036 brelse(bh);
940 } 1037 }
941 1038
942 /* right sibling */ 1039 /* right sibling */
@@ -944,8 +1041,7 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
944 nilfs_btree_node_get_nchildren(btree, parent) - 1) { 1041 nilfs_btree_node_get_nchildren(btree, parent) - 1) {
945 sibptr = nilfs_btree_node_get_ptr(btree, parent, 1042 sibptr = nilfs_btree_node_get_ptr(btree, parent,
946 pindex + 1); 1043 pindex + 1);
947 ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr, 1044 ret = nilfs_btree_get_block(btree, sibptr, &bh);
948 &bh);
949 if (ret < 0) 1045 if (ret < 0)
950 goto err_out_child_node; 1046 goto err_out_child_node;
951 sib = (struct nilfs_btree_node *)bh->b_data; 1047 sib = (struct nilfs_btree_node *)bh->b_data;
@@ -956,19 +1052,19 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
956 stats->bs_nblocks++; 1052 stats->bs_nblocks++;
957 goto out; 1053 goto out;
958 } else 1054 } else
959 nilfs_bmap_put_block(&btree->bt_bmap, bh); 1055 brelse(bh);
960 } 1056 }
961 1057
962 /* split */ 1058 /* split */
963 path[level].bp_newreq.bpr_ptr = 1059 path[level].bp_newreq.bpr_ptr =
964 path[level - 1].bp_newreq.bpr_ptr + 1; 1060 path[level - 1].bp_newreq.bpr_ptr + 1;
965 ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr( 1061 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
966 &btree->bt_bmap, &path[level].bp_newreq); 1062 &path[level].bp_newreq);
967 if (ret < 0) 1063 if (ret < 0)
968 goto err_out_child_node; 1064 goto err_out_child_node;
969 ret = nilfs_bmap_get_new_block(&btree->bt_bmap, 1065 ret = nilfs_btree_get_new_block(btree,
970 path[level].bp_newreq.bpr_ptr, 1066 path[level].bp_newreq.bpr_ptr,
971 &bh); 1067 &bh);
972 if (ret < 0) 1068 if (ret < 0)
973 goto err_out_curr_node; 1069 goto err_out_curr_node;
974 1070
@@ -994,12 +1090,12 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
994 1090
995 /* grow */ 1091 /* grow */
996 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1; 1092 path[level].bp_newreq.bpr_ptr = path[level - 1].bp_newreq.bpr_ptr + 1;
997 ret = btree->bt_bmap.b_pops->bpop_prepare_alloc_ptr( 1093 ret = nilfs_bmap_prepare_alloc_ptr(&btree->bt_bmap,
998 &btree->bt_bmap, &path[level].bp_newreq); 1094 &path[level].bp_newreq);
999 if (ret < 0) 1095 if (ret < 0)
1000 goto err_out_child_node; 1096 goto err_out_child_node;
1001 ret = nilfs_bmap_get_new_block(&btree->bt_bmap, 1097 ret = nilfs_btree_get_new_block(btree, path[level].bp_newreq.bpr_ptr,
1002 path[level].bp_newreq.bpr_ptr, &bh); 1098 &bh);
1003 if (ret < 0) 1099 if (ret < 0)
1004 goto err_out_curr_node; 1100 goto err_out_curr_node;
1005 1101
@@ -1023,18 +1119,16 @@ static int nilfs_btree_prepare_insert(struct nilfs_btree *btree,
1023 1119
1024 /* error */ 1120 /* error */
1025 err_out_curr_node: 1121 err_out_curr_node:
1026 btree->bt_bmap.b_pops->bpop_abort_alloc_ptr(&btree->bt_bmap, 1122 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
1027 &path[level].bp_newreq);
1028 err_out_child_node: 1123 err_out_child_node:
1029 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) { 1124 for (level--; level > NILFS_BTREE_LEVEL_DATA; level--) {
1030 nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_sib_bh); 1125 nilfs_btnode_delete(path[level].bp_sib_bh);
1031 btree->bt_bmap.b_pops->bpop_abort_alloc_ptr( 1126 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap,
1032 &btree->bt_bmap, &path[level].bp_newreq); 1127 &path[level].bp_newreq);
1033 1128
1034 } 1129 }
1035 1130
1036 btree->bt_bmap.b_pops->bpop_abort_alloc_ptr(&btree->bt_bmap, 1131 nilfs_bmap_abort_alloc_ptr(&btree->bt_bmap, &path[level].bp_newreq);
1037 &path[level].bp_newreq);
1038 err_out_data: 1132 err_out_data:
1039 *levelp = level; 1133 *levelp = level;
1040 stats->bs_nblocks = 0; 1134 stats->bs_nblocks = 0;
@@ -1049,14 +1143,12 @@ static void nilfs_btree_commit_insert(struct nilfs_btree *btree,
1049 1143
1050 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr)); 1144 set_buffer_nilfs_volatile((struct buffer_head *)((unsigned long)ptr));
1051 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr; 1145 ptr = path[NILFS_BTREE_LEVEL_DATA].bp_newreq.bpr_ptr;
1052 if (btree->bt_ops->btop_set_target != NULL) 1146 if (NILFS_BMAP_USE_VBN(&btree->bt_bmap))
1053 btree->bt_ops->btop_set_target(btree, key, ptr); 1147 nilfs_btree_set_target_v(btree, key, ptr);
1054 1148
1055 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { 1149 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
1056 if (btree->bt_bmap.b_pops->bpop_commit_alloc_ptr != NULL) { 1150 nilfs_bmap_commit_alloc_ptr(&btree->bt_bmap,
1057 btree->bt_bmap.b_pops->bpop_commit_alloc_ptr( 1151 &path[level - 1].bp_newreq);
1058 &btree->bt_bmap, &path[level - 1].bp_newreq);
1059 }
1060 path[level].bp_op(btree, path, level, &key, &ptr); 1152 path[level].bp_op(btree, path, level, &key, &ptr);
1061 } 1153 }
1062 1154
@@ -1153,7 +1245,7 @@ static void nilfs_btree_borrow_left(struct nilfs_btree *btree,
1153 nilfs_btree_promote_key(btree, path, level + 1, 1245 nilfs_btree_promote_key(btree, path, level + 1,
1154 nilfs_btree_node_get_key(btree, node, 0)); 1246 nilfs_btree_node_get_key(btree, node, 0));
1155 1247
1156 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 1248 brelse(path[level].bp_sib_bh);
1157 path[level].bp_sib_bh = NULL; 1249 path[level].bp_sib_bh = NULL;
1158 path[level].bp_index += n; 1250 path[level].bp_index += n;
1159} 1251}
@@ -1192,7 +1284,7 @@ static void nilfs_btree_borrow_right(struct nilfs_btree *btree,
1192 nilfs_btree_node_get_key(btree, right, 0)); 1284 nilfs_btree_node_get_key(btree, right, 0));
1193 path[level + 1].bp_index--; 1285 path[level + 1].bp_index--;
1194 1286
1195 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 1287 brelse(path[level].bp_sib_bh);
1196 path[level].bp_sib_bh = NULL; 1288 path[level].bp_sib_bh = NULL;
1197} 1289}
1198 1290
@@ -1221,7 +1313,7 @@ static void nilfs_btree_concat_left(struct nilfs_btree *btree,
1221 unlock_buffer(path[level].bp_bh); 1313 unlock_buffer(path[level].bp_bh);
1222 unlock_buffer(path[level].bp_sib_bh); 1314 unlock_buffer(path[level].bp_sib_bh);
1223 1315
1224 nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_bh); 1316 nilfs_btnode_delete(path[level].bp_bh);
1225 path[level].bp_bh = path[level].bp_sib_bh; 1317 path[level].bp_bh = path[level].bp_sib_bh;
1226 path[level].bp_sib_bh = NULL; 1318 path[level].bp_sib_bh = NULL;
1227 path[level].bp_index += nilfs_btree_node_get_nchildren(btree, left); 1319 path[level].bp_index += nilfs_btree_node_get_nchildren(btree, left);
@@ -1252,7 +1344,7 @@ static void nilfs_btree_concat_right(struct nilfs_btree *btree,
1252 unlock_buffer(path[level].bp_bh); 1344 unlock_buffer(path[level].bp_bh);
1253 unlock_buffer(path[level].bp_sib_bh); 1345 unlock_buffer(path[level].bp_sib_bh);
1254 1346
1255 nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_sib_bh); 1347 nilfs_btnode_delete(path[level].bp_sib_bh);
1256 path[level].bp_sib_bh = NULL; 1348 path[level].bp_sib_bh = NULL;
1257 path[level + 1].bp_index++; 1349 path[level + 1].bp_index++;
1258} 1350}
@@ -1276,7 +1368,7 @@ static void nilfs_btree_shrink(struct nilfs_btree *btree,
1276 nilfs_btree_node_move_left(btree, root, child, n); 1368 nilfs_btree_node_move_left(btree, root, child, n);
1277 unlock_buffer(path[level].bp_bh); 1369 unlock_buffer(path[level].bp_bh);
1278 1370
1279 nilfs_bmap_delete_block(&btree->bt_bmap, path[level].bp_bh); 1371 nilfs_btnode_delete(path[level].bp_bh);
1280 path[level].bp_bh = NULL; 1372 path[level].bp_bh = NULL;
1281} 1373}
1282 1374
@@ -1300,12 +1392,10 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1300 path[level].bp_oldreq.bpr_ptr = 1392 path[level].bp_oldreq.bpr_ptr =
1301 nilfs_btree_node_get_ptr(btree, node, 1393 nilfs_btree_node_get_ptr(btree, node,
1302 path[level].bp_index); 1394 path[level].bp_index);
1303 if (btree->bt_bmap.b_pops->bpop_prepare_end_ptr != NULL) { 1395 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
1304 ret = btree->bt_bmap.b_pops->bpop_prepare_end_ptr( 1396 &path[level].bp_oldreq);
1305 &btree->bt_bmap, &path[level].bp_oldreq); 1397 if (ret < 0)
1306 if (ret < 0) 1398 goto err_out_child_node;
1307 goto err_out_child_node;
1308 }
1309 1399
1310 if (nilfs_btree_node_get_nchildren(btree, node) > 1400 if (nilfs_btree_node_get_nchildren(btree, node) >
1311 nilfs_btree_node_nchildren_min(btree, node)) { 1401 nilfs_btree_node_nchildren_min(btree, node)) {
@@ -1321,8 +1411,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1321 /* left sibling */ 1411 /* left sibling */
1322 sibptr = nilfs_btree_node_get_ptr(btree, parent, 1412 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1323 pindex - 1); 1413 pindex - 1);
1324 ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr, 1414 ret = nilfs_btree_get_block(btree, sibptr, &bh);
1325 &bh);
1326 if (ret < 0) 1415 if (ret < 0)
1327 goto err_out_curr_node; 1416 goto err_out_curr_node;
1328 sib = (struct nilfs_btree_node *)bh->b_data; 1417 sib = (struct nilfs_btree_node *)bh->b_data;
@@ -1343,8 +1432,7 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1343 /* right sibling */ 1432 /* right sibling */
1344 sibptr = nilfs_btree_node_get_ptr(btree, parent, 1433 sibptr = nilfs_btree_node_get_ptr(btree, parent,
1345 pindex + 1); 1434 pindex + 1);
1346 ret = nilfs_bmap_get_block(&btree->bt_bmap, sibptr, 1435 ret = nilfs_btree_get_block(btree, sibptr, &bh);
1347 &bh);
1348 if (ret < 0) 1436 if (ret < 0)
1349 goto err_out_curr_node; 1437 goto err_out_curr_node;
1350 sib = (struct nilfs_btree_node *)bh->b_data; 1438 sib = (struct nilfs_btree_node *)bh->b_data;
@@ -1381,12 +1469,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1381 node = nilfs_btree_get_root(btree); 1469 node = nilfs_btree_get_root(btree);
1382 path[level].bp_oldreq.bpr_ptr = 1470 path[level].bp_oldreq.bpr_ptr =
1383 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index); 1471 nilfs_btree_node_get_ptr(btree, node, path[level].bp_index);
1384 if (btree->bt_bmap.b_pops->bpop_prepare_end_ptr != NULL) { 1472
1385 ret = btree->bt_bmap.b_pops->bpop_prepare_end_ptr( 1473 ret = nilfs_bmap_prepare_end_ptr(&btree->bt_bmap,
1386 &btree->bt_bmap, &path[level].bp_oldreq); 1474 &path[level].bp_oldreq);
1387 if (ret < 0) 1475 if (ret < 0)
1388 goto err_out_child_node; 1476 goto err_out_child_node;
1389 } 1477
1390 /* child of the root node is deleted */ 1478 /* child of the root node is deleted */
1391 path[level].bp_op = nilfs_btree_do_delete; 1479 path[level].bp_op = nilfs_btree_do_delete;
1392 stats->bs_nblocks++; 1480 stats->bs_nblocks++;
@@ -1398,15 +1486,12 @@ static int nilfs_btree_prepare_delete(struct nilfs_btree *btree,
1398 1486
1399 /* error */ 1487 /* error */
1400 err_out_curr_node: 1488 err_out_curr_node:
1401 if (btree->bt_bmap.b_pops->bpop_abort_end_ptr != NULL) 1489 nilfs_bmap_abort_end_ptr(&btree->bt_bmap, &path[level].bp_oldreq);
1402 btree->bt_bmap.b_pops->bpop_abort_end_ptr(
1403 &btree->bt_bmap, &path[level].bp_oldreq);
1404 err_out_child_node: 1490 err_out_child_node:
1405 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) { 1491 for (level--; level >= NILFS_BTREE_LEVEL_NODE_MIN; level--) {
1406 nilfs_bmap_put_block(&btree->bt_bmap, path[level].bp_sib_bh); 1492 brelse(path[level].bp_sib_bh);
1407 if (btree->bt_bmap.b_pops->bpop_abort_end_ptr != NULL) 1493 nilfs_bmap_abort_end_ptr(&btree->bt_bmap,
1408 btree->bt_bmap.b_pops->bpop_abort_end_ptr( 1494 &path[level].bp_oldreq);
1409 &btree->bt_bmap, &path[level].bp_oldreq);
1410 } 1495 }
1411 *levelp = level; 1496 *levelp = level;
1412 stats->bs_nblocks = 0; 1497 stats->bs_nblocks = 0;
@@ -1420,9 +1505,8 @@ static void nilfs_btree_commit_delete(struct nilfs_btree *btree,
1420 int level; 1505 int level;
1421 1506
1422 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) { 1507 for (level = NILFS_BTREE_LEVEL_NODE_MIN; level <= maxlevel; level++) {
1423 if (btree->bt_bmap.b_pops->bpop_commit_end_ptr != NULL) 1508 nilfs_bmap_commit_end_ptr(&btree->bt_bmap,
1424 btree->bt_bmap.b_pops->bpop_commit_end_ptr( 1509 &path[level].bp_oldreq);
1425 &btree->bt_bmap, &path[level].bp_oldreq);
1426 path[level].bp_op(btree, path, level, NULL, NULL); 1510 path[level].bp_op(btree, path, level, NULL, NULL);
1427 } 1511 }
1428 1512
@@ -1501,7 +1585,7 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1501 if (nchildren > 1) 1585 if (nchildren > 1)
1502 return 0; 1586 return 0;
1503 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); 1587 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
1504 ret = nilfs_bmap_get_block(bmap, ptr, &bh); 1588 ret = nilfs_btree_get_block(btree, ptr, &bh);
1505 if (ret < 0) 1589 if (ret < 0)
1506 return ret; 1590 return ret;
1507 node = (struct nilfs_btree_node *)bh->b_data; 1591 node = (struct nilfs_btree_node *)bh->b_data;
@@ -1515,9 +1599,9 @@ static int nilfs_btree_check_delete(struct nilfs_bmap *bmap, __u64 key)
1515 nextmaxkey = (nchildren > 1) ? 1599 nextmaxkey = (nchildren > 1) ?
1516 nilfs_btree_node_get_key(btree, node, nchildren - 2) : 0; 1600 nilfs_btree_node_get_key(btree, node, nchildren - 2) : 0;
1517 if (bh != NULL) 1601 if (bh != NULL)
1518 nilfs_bmap_put_block(bmap, bh); 1602 brelse(bh);
1519 1603
1520 return (maxkey == key) && (nextmaxkey < bmap->b_low); 1604 return (maxkey == key) && (nextmaxkey < NILFS_BMAP_LARGE_LOW);
1521} 1605}
1522 1606
1523static int nilfs_btree_gather_data(struct nilfs_bmap *bmap, 1607static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
@@ -1542,7 +1626,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1542 nchildren = nilfs_btree_node_get_nchildren(btree, root); 1626 nchildren = nilfs_btree_node_get_nchildren(btree, root);
1543 WARN_ON(nchildren > 1); 1627 WARN_ON(nchildren > 1);
1544 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1); 1628 ptr = nilfs_btree_node_get_ptr(btree, root, nchildren - 1);
1545 ret = nilfs_bmap_get_block(bmap, ptr, &bh); 1629 ret = nilfs_btree_get_block(btree, ptr, &bh);
1546 if (ret < 0) 1630 if (ret < 0)
1547 return ret; 1631 return ret;
1548 node = (struct nilfs_btree_node *)bh->b_data; 1632 node = (struct nilfs_btree_node *)bh->b_data;
@@ -1563,7 +1647,7 @@ static int nilfs_btree_gather_data(struct nilfs_bmap *bmap,
1563 } 1647 }
1564 1648
1565 if (bh != NULL) 1649 if (bh != NULL)
1566 nilfs_bmap_put_block(bmap, bh); 1650 brelse(bh);
1567 1651
1568 return nitems; 1652 return nitems;
1569} 1653}
@@ -1584,10 +1668,10 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1584 1668
1585 /* for data */ 1669 /* for data */
1586 /* cannot find near ptr */ 1670 /* cannot find near ptr */
1587 if (btree->bt_ops->btop_find_target != NULL) 1671 if (NILFS_BMAP_USE_VBN(bmap))
1588 dreq->bpr_ptr 1672 dreq->bpr_ptr = nilfs_btree_find_target_v(btree, NULL, key);
1589 = btree->bt_ops->btop_find_target(btree, NULL, key); 1673
1590 ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, dreq); 1674 ret = nilfs_bmap_prepare_alloc_ptr(bmap, dreq);
1591 if (ret < 0) 1675 if (ret < 0)
1592 return ret; 1676 return ret;
1593 1677
@@ -1595,11 +1679,11 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1595 stats->bs_nblocks++; 1679 stats->bs_nblocks++;
1596 if (nreq != NULL) { 1680 if (nreq != NULL) {
1597 nreq->bpr_ptr = dreq->bpr_ptr + 1; 1681 nreq->bpr_ptr = dreq->bpr_ptr + 1;
1598 ret = bmap->b_pops->bpop_prepare_alloc_ptr(bmap, nreq); 1682 ret = nilfs_bmap_prepare_alloc_ptr(bmap, nreq);
1599 if (ret < 0) 1683 if (ret < 0)
1600 goto err_out_dreq; 1684 goto err_out_dreq;
1601 1685
1602 ret = nilfs_bmap_get_new_block(bmap, nreq->bpr_ptr, &bh); 1686 ret = nilfs_btree_get_new_block(btree, nreq->bpr_ptr, &bh);
1603 if (ret < 0) 1687 if (ret < 0)
1604 goto err_out_nreq; 1688 goto err_out_nreq;
1605 1689
@@ -1612,9 +1696,9 @@ nilfs_btree_prepare_convert_and_insert(struct nilfs_bmap *bmap, __u64 key,
1612 1696
1613 /* error */ 1697 /* error */
1614 err_out_nreq: 1698 err_out_nreq:
1615 bmap->b_pops->bpop_abort_alloc_ptr(bmap, nreq); 1699 nilfs_bmap_abort_alloc_ptr(bmap, nreq);
1616 err_out_dreq: 1700 err_out_dreq:
1617 bmap->b_pops->bpop_abort_alloc_ptr(bmap, dreq); 1701 nilfs_bmap_abort_alloc_ptr(bmap, dreq);
1618 stats->bs_nblocks = 0; 1702 stats->bs_nblocks = 0;
1619 return ret; 1703 return ret;
1620 1704
@@ -1624,7 +1708,7 @@ static void
1624nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap, 1708nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1625 __u64 key, __u64 ptr, 1709 __u64 key, __u64 ptr,
1626 const __u64 *keys, const __u64 *ptrs, 1710 const __u64 *keys, const __u64 *ptrs,
1627 int n, __u64 low, __u64 high, 1711 int n,
1628 union nilfs_bmap_ptr_req *dreq, 1712 union nilfs_bmap_ptr_req *dreq,
1629 union nilfs_bmap_ptr_req *nreq, 1713 union nilfs_bmap_ptr_req *nreq,
1630 struct buffer_head *bh) 1714 struct buffer_head *bh)
@@ -1642,12 +1726,10 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1642 1726
1643 /* convert and insert */ 1727 /* convert and insert */
1644 btree = (struct nilfs_btree *)bmap; 1728 btree = (struct nilfs_btree *)bmap;
1645 nilfs_btree_init(bmap, low, high); 1729 nilfs_btree_init(bmap);
1646 if (nreq != NULL) { 1730 if (nreq != NULL) {
1647 if (bmap->b_pops->bpop_commit_alloc_ptr != NULL) { 1731 nilfs_bmap_commit_alloc_ptr(bmap, dreq);
1648 bmap->b_pops->bpop_commit_alloc_ptr(bmap, dreq); 1732 nilfs_bmap_commit_alloc_ptr(bmap, nreq);
1649 bmap->b_pops->bpop_commit_alloc_ptr(bmap, nreq);
1650 }
1651 1733
1652 /* create child node at level 1 */ 1734 /* create child node at level 1 */
1653 lock_buffer(bh); 1735 lock_buffer(bh);
@@ -1661,7 +1743,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1661 nilfs_bmap_set_dirty(bmap); 1743 nilfs_bmap_set_dirty(bmap);
1662 1744
1663 unlock_buffer(bh); 1745 unlock_buffer(bh);
1664 nilfs_bmap_put_block(bmap, bh); 1746 brelse(bh);
1665 1747
1666 /* create root node at level 2 */ 1748 /* create root node at level 2 */
1667 node = nilfs_btree_get_root(btree); 1749 node = nilfs_btree_get_root(btree);
@@ -1669,8 +1751,7 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1669 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT, 1751 nilfs_btree_node_init(btree, node, NILFS_BTREE_NODE_ROOT,
1670 2, 1, &keys[0], &tmpptr); 1752 2, 1, &keys[0], &tmpptr);
1671 } else { 1753 } else {
1672 if (bmap->b_pops->bpop_commit_alloc_ptr != NULL) 1754 nilfs_bmap_commit_alloc_ptr(bmap, dreq);
1673 bmap->b_pops->bpop_commit_alloc_ptr(bmap, dreq);
1674 1755
1675 /* create root node at level 1 */ 1756 /* create root node at level 1 */
1676 node = nilfs_btree_get_root(btree); 1757 node = nilfs_btree_get_root(btree);
@@ -1682,8 +1763,8 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1682 nilfs_bmap_set_dirty(bmap); 1763 nilfs_bmap_set_dirty(bmap);
1683 } 1764 }
1684 1765
1685 if (btree->bt_ops->btop_set_target != NULL) 1766 if (NILFS_BMAP_USE_VBN(bmap))
1686 btree->bt_ops->btop_set_target(btree, key, dreq->bpr_ptr); 1767 nilfs_btree_set_target_v(btree, key, dreq->bpr_ptr);
1687} 1768}
1688 1769
1689/** 1770/**
@@ -1694,13 +1775,10 @@ nilfs_btree_commit_convert_and_insert(struct nilfs_bmap *bmap,
1694 * @keys: 1775 * @keys:
1695 * @ptrs: 1776 * @ptrs:
1696 * @n: 1777 * @n:
1697 * @low:
1698 * @high:
1699 */ 1778 */
1700int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap, 1779int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1701 __u64 key, __u64 ptr, 1780 __u64 key, __u64 ptr,
1702 const __u64 *keys, const __u64 *ptrs, 1781 const __u64 *keys, const __u64 *ptrs, int n)
1703 int n, __u64 low, __u64 high)
1704{ 1782{
1705 struct buffer_head *bh; 1783 struct buffer_head *bh;
1706 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni; 1784 union nilfs_bmap_ptr_req dreq, nreq, *di, *ni;
@@ -1725,7 +1803,7 @@ int nilfs_btree_convert_and_insert(struct nilfs_bmap *bmap,
1725 if (ret < 0) 1803 if (ret < 0)
1726 return ret; 1804 return ret;
1727 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n, 1805 nilfs_btree_commit_convert_and_insert(bmap, key, ptr, keys, ptrs, n,
1728 low, high, di, ni, bh); 1806 di, ni, bh);
1729 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks); 1807 nilfs_bmap_add_blocks(bmap, stats.bs_nblocks);
1730 return 0; 1808 return 0;
1731} 1809}
@@ -1754,9 +1832,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1754 nilfs_btree_node_get_ptr(btree, parent, 1832 nilfs_btree_node_get_ptr(btree, parent,
1755 path[level + 1].bp_index); 1833 path[level + 1].bp_index);
1756 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1; 1834 path[level].bp_newreq.bpr_ptr = path[level].bp_oldreq.bpr_ptr + 1;
1757 ret = nilfs_bmap_prepare_update(&btree->bt_bmap, 1835 ret = nilfs_bmap_prepare_update_v(&btree->bt_bmap,
1758 &path[level].bp_oldreq, 1836 &path[level].bp_oldreq,
1759 &path[level].bp_newreq); 1837 &path[level].bp_newreq);
1760 if (ret < 0) 1838 if (ret < 0)
1761 return ret; 1839 return ret;
1762 1840
@@ -1768,9 +1846,9 @@ static int nilfs_btree_prepare_update_v(struct nilfs_btree *btree,
1768 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, 1846 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
1769 &path[level].bp_ctxt); 1847 &path[level].bp_ctxt);
1770 if (ret < 0) { 1848 if (ret < 0) {
1771 nilfs_bmap_abort_update(&btree->bt_bmap, 1849 nilfs_bmap_abort_update_v(&btree->bt_bmap,
1772 &path[level].bp_oldreq, 1850 &path[level].bp_oldreq,
1773 &path[level].bp_newreq); 1851 &path[level].bp_newreq);
1774 return ret; 1852 return ret;
1775 } 1853 }
1776 } 1854 }
@@ -1784,9 +1862,9 @@ static void nilfs_btree_commit_update_v(struct nilfs_btree *btree,
1784{ 1862{
1785 struct nilfs_btree_node *parent; 1863 struct nilfs_btree_node *parent;
1786 1864
1787 nilfs_bmap_commit_update(&btree->bt_bmap, 1865 nilfs_bmap_commit_update_v(&btree->bt_bmap,
1788 &path[level].bp_oldreq, 1866 &path[level].bp_oldreq,
1789 &path[level].bp_newreq); 1867 &path[level].bp_newreq);
1790 1868
1791 if (buffer_nilfs_node(path[level].bp_bh)) { 1869 if (buffer_nilfs_node(path[level].bp_bh)) {
1792 nilfs_btnode_commit_change_key( 1870 nilfs_btnode_commit_change_key(
@@ -1805,9 +1883,9 @@ static void nilfs_btree_abort_update_v(struct nilfs_btree *btree,
1805 struct nilfs_btree_path *path, 1883 struct nilfs_btree_path *path,
1806 int level) 1884 int level)
1807{ 1885{
1808 nilfs_bmap_abort_update(&btree->bt_bmap, 1886 nilfs_bmap_abort_update_v(&btree->bt_bmap,
1809 &path[level].bp_oldreq, 1887 &path[level].bp_oldreq,
1810 &path[level].bp_newreq); 1888 &path[level].bp_newreq);
1811 if (buffer_nilfs_node(path[level].bp_bh)) 1889 if (buffer_nilfs_node(path[level].bp_bh))
1812 nilfs_btnode_abort_change_key( 1890 nilfs_btnode_abort_change_key(
1813 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache, 1891 &NILFS_BMAP_I(&btree->bt_bmap)->i_btnode_cache,
@@ -1930,7 +2008,9 @@ static int nilfs_btree_propagate(const struct nilfs_bmap *bmap,
1930 goto out; 2008 goto out;
1931 } 2009 }
1932 2010
1933 ret = btree->bt_ops->btop_propagate(btree, path, level, bh); 2011 ret = NILFS_BMAP_USE_VBN(bmap) ?
2012 nilfs_btree_propagate_v(btree, path, level, bh) :
2013 nilfs_btree_propagate_p(btree, path, level, bh);
1934 2014
1935 out: 2015 out:
1936 nilfs_btree_clear_path(btree, path); 2016 nilfs_btree_clear_path(btree, path);
@@ -2066,12 +2146,9 @@ static int nilfs_btree_assign_v(struct nilfs_btree *btree,
2066 ptr = nilfs_btree_node_get_ptr(btree, parent, 2146 ptr = nilfs_btree_node_get_ptr(btree, parent,
2067 path[level + 1].bp_index); 2147 path[level + 1].bp_index);
2068 req.bpr_ptr = ptr; 2148 req.bpr_ptr = ptr;
2069 ret = btree->bt_bmap.b_pops->bpop_prepare_start_ptr(&btree->bt_bmap, 2149 ret = nilfs_bmap_start_v(&btree->bt_bmap, &req, blocknr);
2070 &req); 2150 if (unlikely(ret < 0))
2071 if (ret < 0)
2072 return ret; 2151 return ret;
2073 btree->bt_bmap.b_pops->bpop_commit_start_ptr(&btree->bt_bmap,
2074 &req, blocknr);
2075 2152
2076 key = nilfs_btree_node_get_key(btree, parent, 2153 key = nilfs_btree_node_get_key(btree, parent,
2077 path[level + 1].bp_index); 2154 path[level + 1].bp_index);
@@ -2114,8 +2191,9 @@ static int nilfs_btree_assign(struct nilfs_bmap *bmap,
2114 goto out; 2191 goto out;
2115 } 2192 }
2116 2193
2117 ret = btree->bt_ops->btop_assign(btree, path, level, bh, 2194 ret = NILFS_BMAP_USE_VBN(bmap) ?
2118 blocknr, binfo); 2195 nilfs_btree_assign_v(btree, path, level, bh, blocknr, binfo) :
2196 nilfs_btree_assign_p(btree, path, level, bh, blocknr, binfo);
2119 2197
2120 out: 2198 out:
2121 nilfs_btree_clear_path(btree, path); 2199 nilfs_btree_clear_path(btree, path);
@@ -2171,7 +2249,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2171 WARN_ON(ret == -ENOENT); 2249 WARN_ON(ret == -ENOENT);
2172 goto out; 2250 goto out;
2173 } 2251 }
2174 ret = nilfs_bmap_get_block(&btree->bt_bmap, ptr, &bh); 2252 ret = nilfs_btree_get_block(btree, ptr, &bh);
2175 if (ret < 0) { 2253 if (ret < 0) {
2176 WARN_ON(ret == -ENOENT); 2254 WARN_ON(ret == -ENOENT);
2177 goto out; 2255 goto out;
@@ -2179,7 +2257,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2179 2257
2180 if (!buffer_dirty(bh)) 2258 if (!buffer_dirty(bh))
2181 nilfs_btnode_mark_dirty(bh); 2259 nilfs_btnode_mark_dirty(bh);
2182 nilfs_bmap_put_block(&btree->bt_bmap, bh); 2260 brelse(bh);
2183 if (!nilfs_bmap_dirty(&btree->bt_bmap)) 2261 if (!nilfs_bmap_dirty(&btree->bt_bmap))
2184 nilfs_bmap_set_dirty(&btree->bt_bmap); 2262 nilfs_bmap_set_dirty(&btree->bt_bmap);
2185 2263
@@ -2191,6 +2269,7 @@ static int nilfs_btree_mark(struct nilfs_bmap *bmap, __u64 key, int level)
2191 2269
2192static const struct nilfs_bmap_operations nilfs_btree_ops = { 2270static const struct nilfs_bmap_operations nilfs_btree_ops = {
2193 .bop_lookup = nilfs_btree_lookup, 2271 .bop_lookup = nilfs_btree_lookup,
2272 .bop_lookup_contig = nilfs_btree_lookup_contig,
2194 .bop_insert = nilfs_btree_insert, 2273 .bop_insert = nilfs_btree_insert,
2195 .bop_delete = nilfs_btree_delete, 2274 .bop_delete = nilfs_btree_delete,
2196 .bop_clear = NULL, 2275 .bop_clear = NULL,
@@ -2210,6 +2289,7 @@ static const struct nilfs_bmap_operations nilfs_btree_ops = {
2210 2289
2211static const struct nilfs_bmap_operations nilfs_btree_ops_gc = { 2290static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2212 .bop_lookup = NULL, 2291 .bop_lookup = NULL,
2292 .bop_lookup_contig = NULL,
2213 .bop_insert = NULL, 2293 .bop_insert = NULL,
2214 .bop_delete = NULL, 2294 .bop_delete = NULL,
2215 .bop_clear = NULL, 2295 .bop_clear = NULL,
@@ -2227,43 +2307,13 @@ static const struct nilfs_bmap_operations nilfs_btree_ops_gc = {
2227 .bop_gather_data = NULL, 2307 .bop_gather_data = NULL,
2228}; 2308};
2229 2309
2230static const struct nilfs_btree_operations nilfs_btree_ops_v = { 2310int nilfs_btree_init(struct nilfs_bmap *bmap)
2231 .btop_find_target = nilfs_btree_find_target_v,
2232 .btop_set_target = nilfs_btree_set_target_v,
2233 .btop_propagate = nilfs_btree_propagate_v,
2234 .btop_assign = nilfs_btree_assign_v,
2235};
2236
2237static const struct nilfs_btree_operations nilfs_btree_ops_p = {
2238 .btop_find_target = NULL,
2239 .btop_set_target = NULL,
2240 .btop_propagate = nilfs_btree_propagate_p,
2241 .btop_assign = nilfs_btree_assign_p,
2242};
2243
2244int nilfs_btree_init(struct nilfs_bmap *bmap, __u64 low, __u64 high)
2245{ 2311{
2246 struct nilfs_btree *btree;
2247
2248 btree = (struct nilfs_btree *)bmap;
2249 bmap->b_ops = &nilfs_btree_ops; 2312 bmap->b_ops = &nilfs_btree_ops;
2250 bmap->b_low = low;
2251 bmap->b_high = high;
2252 switch (bmap->b_inode->i_ino) {
2253 case NILFS_DAT_INO:
2254 btree->bt_ops = &nilfs_btree_ops_p;
2255 break;
2256 default:
2257 btree->bt_ops = &nilfs_btree_ops_v;
2258 break;
2259 }
2260
2261 return 0; 2313 return 0;
2262} 2314}
2263 2315
2264void nilfs_btree_init_gc(struct nilfs_bmap *bmap) 2316void nilfs_btree_init_gc(struct nilfs_bmap *bmap)
2265{ 2317{
2266 bmap->b_low = NILFS_BMAP_LARGE_LOW;
2267 bmap->b_high = NILFS_BMAP_LARGE_HIGH;
2268 bmap->b_ops = &nilfs_btree_ops_gc; 2318 bmap->b_ops = &nilfs_btree_ops_gc;
2269} 2319}
diff --git a/fs/nilfs2/btree.h b/fs/nilfs2/btree.h
index 4766deb52fb1..0e72bbbc6b64 100644
--- a/fs/nilfs2/btree.h
+++ b/fs/nilfs2/btree.h
@@ -34,28 +34,6 @@ struct nilfs_btree;
34struct nilfs_btree_path; 34struct nilfs_btree_path;
35 35
36/** 36/**
37 * struct nilfs_btree_operations - B-tree operation table
38 */
39struct nilfs_btree_operations {
40 __u64 (*btop_find_target)(const struct nilfs_btree *,
41 const struct nilfs_btree_path *, __u64);
42 void (*btop_set_target)(struct nilfs_btree *, __u64, __u64);
43
44 struct the_nilfs *(*btop_get_nilfs)(struct nilfs_btree *);
45
46 int (*btop_propagate)(struct nilfs_btree *,
47 struct nilfs_btree_path *,
48 int,
49 struct buffer_head *);
50 int (*btop_assign)(struct nilfs_btree *,
51 struct nilfs_btree_path *,
52 int,
53 struct buffer_head **,
54 sector_t,
55 union nilfs_binfo *);
56};
57
58/**
59 * struct nilfs_btree_node - B-tree node 37 * struct nilfs_btree_node - B-tree node
60 * @bn_flags: flags 38 * @bn_flags: flags
61 * @bn_level: level 39 * @bn_level: level
@@ -80,13 +58,9 @@ struct nilfs_btree_node {
80/** 58/**
81 * struct nilfs_btree - B-tree structure 59 * struct nilfs_btree - B-tree structure
82 * @bt_bmap: bmap base structure 60 * @bt_bmap: bmap base structure
83 * @bt_ops: B-tree operation table
84 */ 61 */
85struct nilfs_btree { 62struct nilfs_btree {
86 struct nilfs_bmap bt_bmap; 63 struct nilfs_bmap bt_bmap;
87
88 /* B-tree-specific members */
89 const struct nilfs_btree_operations *bt_ops;
90}; 64};
91 65
92 66
@@ -108,10 +82,9 @@ struct nilfs_btree {
108 82
109int nilfs_btree_path_cache_init(void); 83int nilfs_btree_path_cache_init(void);
110void nilfs_btree_path_cache_destroy(void); 84void nilfs_btree_path_cache_destroy(void);
111int nilfs_btree_init(struct nilfs_bmap *, __u64, __u64); 85int nilfs_btree_init(struct nilfs_bmap *);
112int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64, 86int nilfs_btree_convert_and_insert(struct nilfs_bmap *, __u64, __u64,
113 const __u64 *, const __u64 *, 87 const __u64 *, const __u64 *, int);
114 int, __u64, __u64);
115void nilfs_btree_init_gc(struct nilfs_bmap *); 88void nilfs_btree_init_gc(struct nilfs_bmap *);
116 89
117#endif /* _NILFS_BTREE_H */ 90#endif /* _NILFS_BTREE_H */
diff --git a/fs/nilfs2/cpfile.c b/fs/nilfs2/cpfile.c
index cadd36b14d07..7d49813f66d6 100644
--- a/fs/nilfs2/cpfile.c
+++ b/fs/nilfs2/cpfile.c
@@ -295,10 +295,6 @@ int nilfs_cpfile_delete_checkpoints(struct inode *cpfile,
295 return -EINVAL; 295 return -EINVAL;
296 } 296 }
297 297
298 /* cannot delete the latest checkpoint */
299 if (start == nilfs_mdt_cno(cpfile) - 1)
300 return -EPERM;
301
302 down_write(&NILFS_MDT(cpfile)->mi_sem); 298 down_write(&NILFS_MDT(cpfile)->mi_sem);
303 299
304 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh); 300 ret = nilfs_cpfile_get_header_block(cpfile, &header_bh);
@@ -384,9 +380,10 @@ static void nilfs_cpfile_checkpoint_to_cpinfo(struct inode *cpfile,
384} 380}
385 381
386static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop, 382static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
387 struct nilfs_cpinfo *ci, size_t nci) 383 void *buf, unsigned cisz, size_t nci)
388{ 384{
389 struct nilfs_checkpoint *cp; 385 struct nilfs_checkpoint *cp;
386 struct nilfs_cpinfo *ci = buf;
390 struct buffer_head *bh; 387 struct buffer_head *bh;
391 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size; 388 size_t cpsz = NILFS_MDT(cpfile)->mi_entry_size;
392 __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop; 389 __u64 cur_cno = nilfs_mdt_cno(cpfile), cno = *cnop;
@@ -410,17 +407,22 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
410 kaddr = kmap_atomic(bh->b_page, KM_USER0); 407 kaddr = kmap_atomic(bh->b_page, KM_USER0);
411 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr); 408 cp = nilfs_cpfile_block_get_checkpoint(cpfile, cno, bh, kaddr);
412 for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) { 409 for (i = 0; i < ncps && n < nci; i++, cp = (void *)cp + cpsz) {
413 if (!nilfs_checkpoint_invalid(cp)) 410 if (!nilfs_checkpoint_invalid(cp)) {
414 nilfs_cpfile_checkpoint_to_cpinfo( 411 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp,
415 cpfile, cp, &ci[n++]); 412 ci);
413 ci = (void *)ci + cisz;
414 n++;
415 }
416 } 416 }
417 kunmap_atomic(kaddr, KM_USER0); 417 kunmap_atomic(kaddr, KM_USER0);
418 brelse(bh); 418 brelse(bh);
419 } 419 }
420 420
421 ret = n; 421 ret = n;
422 if (n > 0) 422 if (n > 0) {
423 *cnop = ci[n - 1].ci_cno + 1; 423 ci = (void *)ci - cisz;
424 *cnop = ci->ci_cno + 1;
425 }
424 426
425 out: 427 out:
426 up_read(&NILFS_MDT(cpfile)->mi_sem); 428 up_read(&NILFS_MDT(cpfile)->mi_sem);
@@ -428,11 +430,12 @@ static ssize_t nilfs_cpfile_do_get_cpinfo(struct inode *cpfile, __u64 *cnop,
428} 430}
429 431
430static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop, 432static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
431 struct nilfs_cpinfo *ci, size_t nci) 433 void *buf, unsigned cisz, size_t nci)
432{ 434{
433 struct buffer_head *bh; 435 struct buffer_head *bh;
434 struct nilfs_cpfile_header *header; 436 struct nilfs_cpfile_header *header;
435 struct nilfs_checkpoint *cp; 437 struct nilfs_checkpoint *cp;
438 struct nilfs_cpinfo *ci = buf;
436 __u64 curr = *cnop, next; 439 __u64 curr = *cnop, next;
437 unsigned long curr_blkoff, next_blkoff; 440 unsigned long curr_blkoff, next_blkoff;
438 void *kaddr; 441 void *kaddr;
@@ -472,7 +475,9 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
472 if (unlikely(nilfs_checkpoint_invalid(cp) || 475 if (unlikely(nilfs_checkpoint_invalid(cp) ||
473 !nilfs_checkpoint_snapshot(cp))) 476 !nilfs_checkpoint_snapshot(cp)))
474 break; 477 break;
475 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, &ci[n++]); 478 nilfs_cpfile_checkpoint_to_cpinfo(cpfile, cp, ci);
479 ci = (void *)ci + cisz;
480 n++;
476 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next); 481 next = le64_to_cpu(cp->cp_snapshot_list.ssl_next);
477 if (next == 0) 482 if (next == 0)
478 break; /* reach end of the snapshot list */ 483 break; /* reach end of the snapshot list */
@@ -511,13 +516,13 @@ static ssize_t nilfs_cpfile_do_get_ssinfo(struct inode *cpfile, __u64 *cnop,
511 */ 516 */
512 517
513ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode, 518ssize_t nilfs_cpfile_get_cpinfo(struct inode *cpfile, __u64 *cnop, int mode,
514 struct nilfs_cpinfo *ci, size_t nci) 519 void *buf, unsigned cisz, size_t nci)
515{ 520{
516 switch (mode) { 521 switch (mode) {
517 case NILFS_CHECKPOINT: 522 case NILFS_CHECKPOINT:
518 return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, ci, nci); 523 return nilfs_cpfile_do_get_cpinfo(cpfile, cnop, buf, cisz, nci);
519 case NILFS_SNAPSHOT: 524 case NILFS_SNAPSHOT:
520 return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, ci, nci); 525 return nilfs_cpfile_do_get_ssinfo(cpfile, cnop, buf, cisz, nci);
521 default: 526 default:
522 return -EINVAL; 527 return -EINVAL;
523 } 528 }
@@ -533,20 +538,14 @@ int nilfs_cpfile_delete_checkpoint(struct inode *cpfile, __u64 cno)
533 struct nilfs_cpinfo ci; 538 struct nilfs_cpinfo ci;
534 __u64 tcno = cno; 539 __u64 tcno = cno;
535 ssize_t nci; 540 ssize_t nci;
536 int ret;
537 541
538 nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, 1); 542 nci = nilfs_cpfile_do_get_cpinfo(cpfile, &tcno, &ci, sizeof(ci), 1);
539 if (nci < 0) 543 if (nci < 0)
540 return nci; 544 return nci;
541 else if (nci == 0 || ci.ci_cno != cno) 545 else if (nci == 0 || ci.ci_cno != cno)
542 return -ENOENT; 546 return -ENOENT;
543 547 else if (nilfs_cpinfo_snapshot(&ci))
544 /* cannot delete the latest checkpoint nor snapshots */ 548 return -EBUSY;
545 ret = nilfs_cpinfo_snapshot(&ci);
546 if (ret < 0)
547 return ret;
548 else if (ret > 0 || cno == nilfs_mdt_cno(cpfile) - 1)
549 return -EPERM;
550 549
551 return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1); 550 return nilfs_cpfile_delete_checkpoints(cpfile, cno, cno + 1);
552} 551}
diff --git a/fs/nilfs2/cpfile.h b/fs/nilfs2/cpfile.h
index 1a8a1008c342..788a45950197 100644
--- a/fs/nilfs2/cpfile.h
+++ b/fs/nilfs2/cpfile.h
@@ -39,7 +39,7 @@ int nilfs_cpfile_delete_checkpoint(struct inode *, __u64);
39int nilfs_cpfile_change_cpmode(struct inode *, __u64, int); 39int nilfs_cpfile_change_cpmode(struct inode *, __u64, int);
40int nilfs_cpfile_is_snapshot(struct inode *, __u64); 40int nilfs_cpfile_is_snapshot(struct inode *, __u64);
41int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *); 41int nilfs_cpfile_get_stat(struct inode *, struct nilfs_cpstat *);
42ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, 42ssize_t nilfs_cpfile_get_cpinfo(struct inode *, __u64 *, int, void *, unsigned,
43 struct nilfs_cpinfo *, size_t); 43 size_t);
44 44
45#endif /* _NILFS_CPFILE_H */ 45#endif /* _NILFS_CPFILE_H */
diff --git a/fs/nilfs2/dat.c b/fs/nilfs2/dat.c
index bb8a5818e7f1..0b2710e2d565 100644
--- a/fs/nilfs2/dat.c
+++ b/fs/nilfs2/dat.c
@@ -92,21 +92,6 @@ void nilfs_dat_abort_alloc(struct inode *dat, struct nilfs_palloc_req *req)
92 nilfs_palloc_abort_alloc_entry(dat, req); 92 nilfs_palloc_abort_alloc_entry(dat, req);
93} 93}
94 94
95int nilfs_dat_prepare_free(struct inode *dat, struct nilfs_palloc_req *req)
96{
97 int ret;
98
99 ret = nilfs_palloc_prepare_free_entry(dat, req);
100 if (ret < 0)
101 return ret;
102 ret = nilfs_dat_prepare_entry(dat, req, 0);
103 if (ret < 0) {
104 nilfs_palloc_abort_free_entry(dat, req);
105 return ret;
106 }
107 return 0;
108}
109
110void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req) 95void nilfs_dat_commit_free(struct inode *dat, struct nilfs_palloc_req *req)
111{ 96{
112 struct nilfs_dat_entry *entry; 97 struct nilfs_dat_entry *entry;
@@ -391,36 +376,37 @@ int nilfs_dat_translate(struct inode *dat, __u64 vblocknr, sector_t *blocknrp)
391 return ret; 376 return ret;
392} 377}
393 378
394ssize_t nilfs_dat_get_vinfo(struct inode *dat, struct nilfs_vinfo *vinfo, 379ssize_t nilfs_dat_get_vinfo(struct inode *dat, void *buf, unsigned visz,
395 size_t nvi) 380 size_t nvi)
396{ 381{
397 struct buffer_head *entry_bh; 382 struct buffer_head *entry_bh;
398 struct nilfs_dat_entry *entry; 383 struct nilfs_dat_entry *entry;
384 struct nilfs_vinfo *vinfo = buf;
399 __u64 first, last; 385 __u64 first, last;
400 void *kaddr; 386 void *kaddr;
401 unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block; 387 unsigned long entries_per_block = NILFS_MDT(dat)->mi_entries_per_block;
402 int i, j, n, ret; 388 int i, j, n, ret;
403 389
404 for (i = 0; i < nvi; i += n) { 390 for (i = 0; i < nvi; i += n) {
405 ret = nilfs_palloc_get_entry_block(dat, vinfo[i].vi_vblocknr, 391 ret = nilfs_palloc_get_entry_block(dat, vinfo->vi_vblocknr,
406 0, &entry_bh); 392 0, &entry_bh);
407 if (ret < 0) 393 if (ret < 0)
408 return ret; 394 return ret;
409 kaddr = kmap_atomic(entry_bh->b_page, KM_USER0); 395 kaddr = kmap_atomic(entry_bh->b_page, KM_USER0);
410 /* last virtual block number in this block */ 396 /* last virtual block number in this block */
411 first = vinfo[i].vi_vblocknr; 397 first = vinfo->vi_vblocknr;
412 do_div(first, entries_per_block); 398 do_div(first, entries_per_block);
413 first *= entries_per_block; 399 first *= entries_per_block;
414 last = first + entries_per_block - 1; 400 last = first + entries_per_block - 1;
415 for (j = i, n = 0; 401 for (j = i, n = 0;
416 j < nvi && vinfo[j].vi_vblocknr >= first && 402 j < nvi && vinfo->vi_vblocknr >= first &&
417 vinfo[j].vi_vblocknr <= last; 403 vinfo->vi_vblocknr <= last;
418 j++, n++) { 404 j++, n++, vinfo = (void *)vinfo + visz) {
419 entry = nilfs_palloc_block_get_entry( 405 entry = nilfs_palloc_block_get_entry(
420 dat, vinfo[j].vi_vblocknr, entry_bh, kaddr); 406 dat, vinfo->vi_vblocknr, entry_bh, kaddr);
421 vinfo[j].vi_start = le64_to_cpu(entry->de_start); 407 vinfo->vi_start = le64_to_cpu(entry->de_start);
422 vinfo[j].vi_end = le64_to_cpu(entry->de_end); 408 vinfo->vi_end = le64_to_cpu(entry->de_end);
423 vinfo[j].vi_blocknr = le64_to_cpu(entry->de_blocknr); 409 vinfo->vi_blocknr = le64_to_cpu(entry->de_blocknr);
424 } 410 }
425 kunmap_atomic(kaddr, KM_USER0); 411 kunmap_atomic(kaddr, KM_USER0);
426 brelse(entry_bh); 412 brelse(entry_bh);
diff --git a/fs/nilfs2/dat.h b/fs/nilfs2/dat.h
index d9560654a4b7..d328b81eead4 100644
--- a/fs/nilfs2/dat.h
+++ b/fs/nilfs2/dat.h
@@ -47,6 +47,6 @@ void nilfs_dat_abort_end(struct inode *, struct nilfs_palloc_req *);
47int nilfs_dat_mark_dirty(struct inode *, __u64); 47int nilfs_dat_mark_dirty(struct inode *, __u64);
48int nilfs_dat_freev(struct inode *, __u64 *, size_t); 48int nilfs_dat_freev(struct inode *, __u64 *, size_t);
49int nilfs_dat_move(struct inode *, __u64, sector_t); 49int nilfs_dat_move(struct inode *, __u64, sector_t);
50ssize_t nilfs_dat_get_vinfo(struct inode *, struct nilfs_vinfo *, size_t); 50ssize_t nilfs_dat_get_vinfo(struct inode *, void *, unsigned, size_t);
51 51
52#endif /* _NILFS_DAT_H */ 52#endif /* _NILFS_DAT_H */
diff --git a/fs/nilfs2/direct.c b/fs/nilfs2/direct.c
index c6379e482781..342d9765df8d 100644
--- a/fs/nilfs2/direct.c
+++ b/fs/nilfs2/direct.c
@@ -25,6 +25,7 @@
25#include "page.h" 25#include "page.h"
26#include "direct.h" 26#include "direct.h"
27#include "alloc.h" 27#include "alloc.h"
28#include "dat.h"
28 29
29static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct) 30static inline __le64 *nilfs_direct_dptrs(const struct nilfs_direct *direct)
30{ 31{
@@ -62,6 +63,47 @@ static int nilfs_direct_lookup(const struct nilfs_bmap *bmap,
62 return 0; 63 return 0;
63} 64}
64 65
66static int nilfs_direct_lookup_contig(const struct nilfs_bmap *bmap,
67 __u64 key, __u64 *ptrp,
68 unsigned maxblocks)
69{
70 struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
71 struct inode *dat = NULL;
72 __u64 ptr, ptr2;
73 sector_t blocknr;
74 int ret, cnt;
75
76 if (key > NILFS_DIRECT_KEY_MAX ||
77 (ptr = nilfs_direct_get_ptr(direct, key)) ==
78 NILFS_BMAP_INVALID_PTR)
79 return -ENOENT;
80
81 if (NILFS_BMAP_USE_VBN(bmap)) {
82 dat = nilfs_bmap_get_dat(bmap);
83 ret = nilfs_dat_translate(dat, ptr, &blocknr);
84 if (ret < 0)
85 return ret;
86 ptr = blocknr;
87 }
88
89 maxblocks = min_t(unsigned, maxblocks, NILFS_DIRECT_KEY_MAX - key + 1);
90 for (cnt = 1; cnt < maxblocks &&
91 (ptr2 = nilfs_direct_get_ptr(direct, key + cnt)) !=
92 NILFS_BMAP_INVALID_PTR;
93 cnt++) {
94 if (dat) {
95 ret = nilfs_dat_translate(dat, ptr2, &blocknr);
96 if (ret < 0)
97 return ret;
98 ptr2 = blocknr;
99 }
100 if (ptr2 != ptr + cnt)
101 break;
102 }
103 *ptrp = ptr;
104 return cnt;
105}
106
65static __u64 107static __u64
66nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key) 108nilfs_direct_find_target_v(const struct nilfs_direct *direct, __u64 key)
67{ 109{
@@ -90,10 +132,9 @@ static int nilfs_direct_prepare_insert(struct nilfs_direct *direct,
90{ 132{
91 int ret; 133 int ret;
92 134
93 if (direct->d_ops->dop_find_target != NULL) 135 if (NILFS_BMAP_USE_VBN(&direct->d_bmap))
94 req->bpr_ptr = direct->d_ops->dop_find_target(direct, key); 136 req->bpr_ptr = nilfs_direct_find_target_v(direct, key);
95 ret = direct->d_bmap.b_pops->bpop_prepare_alloc_ptr(&direct->d_bmap, 137 ret = nilfs_bmap_prepare_alloc_ptr(&direct->d_bmap, req);
96 req);
97 if (ret < 0) 138 if (ret < 0)
98 return ret; 139 return ret;
99 140
@@ -111,16 +152,14 @@ static void nilfs_direct_commit_insert(struct nilfs_direct *direct,
111 bh = (struct buffer_head *)((unsigned long)ptr); 152 bh = (struct buffer_head *)((unsigned long)ptr);
112 set_buffer_nilfs_volatile(bh); 153 set_buffer_nilfs_volatile(bh);
113 154
114 if (direct->d_bmap.b_pops->bpop_commit_alloc_ptr != NULL) 155 nilfs_bmap_commit_alloc_ptr(&direct->d_bmap, req);
115 direct->d_bmap.b_pops->bpop_commit_alloc_ptr(
116 &direct->d_bmap, req);
117 nilfs_direct_set_ptr(direct, key, req->bpr_ptr); 156 nilfs_direct_set_ptr(direct, key, req->bpr_ptr);
118 157
119 if (!nilfs_bmap_dirty(&direct->d_bmap)) 158 if (!nilfs_bmap_dirty(&direct->d_bmap))
120 nilfs_bmap_set_dirty(&direct->d_bmap); 159 nilfs_bmap_set_dirty(&direct->d_bmap);
121 160
122 if (direct->d_ops->dop_set_target != NULL) 161 if (NILFS_BMAP_USE_VBN(&direct->d_bmap))
123 direct->d_ops->dop_set_target(direct, key, req->bpr_ptr); 162 nilfs_direct_set_target_v(direct, key, req->bpr_ptr);
124} 163}
125 164
126static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr) 165static int nilfs_direct_insert(struct nilfs_bmap *bmap, __u64 key, __u64 ptr)
@@ -152,25 +191,18 @@ static int nilfs_direct_prepare_delete(struct nilfs_direct *direct,
152{ 191{
153 int ret; 192 int ret;
154 193
155 if (direct->d_bmap.b_pops->bpop_prepare_end_ptr != NULL) { 194 req->bpr_ptr = nilfs_direct_get_ptr(direct, key);
156 req->bpr_ptr = nilfs_direct_get_ptr(direct, key); 195 ret = nilfs_bmap_prepare_end_ptr(&direct->d_bmap, req);
157 ret = direct->d_bmap.b_pops->bpop_prepare_end_ptr( 196 if (!ret)
158 &direct->d_bmap, req); 197 stats->bs_nblocks = 1;
159 if (ret < 0) 198 return ret;
160 return ret;
161 }
162
163 stats->bs_nblocks = 1;
164 return 0;
165} 199}
166 200
167static void nilfs_direct_commit_delete(struct nilfs_direct *direct, 201static void nilfs_direct_commit_delete(struct nilfs_direct *direct,
168 union nilfs_bmap_ptr_req *req, 202 union nilfs_bmap_ptr_req *req,
169 __u64 key) 203 __u64 key)
170{ 204{
171 if (direct->d_bmap.b_pops->bpop_commit_end_ptr != NULL) 205 nilfs_bmap_commit_end_ptr(&direct->d_bmap, req);
172 direct->d_bmap.b_pops->bpop_commit_end_ptr(
173 &direct->d_bmap, req);
174 nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR); 206 nilfs_direct_set_ptr(direct, key, NILFS_BMAP_INVALID_PTR);
175} 207}
176 208
@@ -244,8 +276,7 @@ static int nilfs_direct_gather_data(struct nilfs_bmap *bmap,
244} 276}
245 277
246int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap, 278int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
247 __u64 key, __u64 *keys, __u64 *ptrs, 279 __u64 key, __u64 *keys, __u64 *ptrs, int n)
248 int n, __u64 low, __u64 high)
249{ 280{
250 struct nilfs_direct *direct; 281 struct nilfs_direct *direct;
251 __le64 *dptrs; 282 __le64 *dptrs;
@@ -275,8 +306,7 @@ int nilfs_direct_delete_and_convert(struct nilfs_bmap *bmap,
275 dptrs[i] = NILFS_BMAP_INVALID_PTR; 306 dptrs[i] = NILFS_BMAP_INVALID_PTR;
276 } 307 }
277 308
278 nilfs_direct_init(bmap, low, high); 309 nilfs_direct_init(bmap);
279
280 return 0; 310 return 0;
281} 311}
282 312
@@ -293,11 +323,11 @@ static int nilfs_direct_propagate_v(struct nilfs_direct *direct,
293 if (!buffer_nilfs_volatile(bh)) { 323 if (!buffer_nilfs_volatile(bh)) {
294 oldreq.bpr_ptr = ptr; 324 oldreq.bpr_ptr = ptr;
295 newreq.bpr_ptr = ptr; 325 newreq.bpr_ptr = ptr;
296 ret = nilfs_bmap_prepare_update(&direct->d_bmap, &oldreq, 326 ret = nilfs_bmap_prepare_update_v(&direct->d_bmap, &oldreq,
297 &newreq); 327 &newreq);
298 if (ret < 0) 328 if (ret < 0)
299 return ret; 329 return ret;
300 nilfs_bmap_commit_update(&direct->d_bmap, &oldreq, &newreq); 330 nilfs_bmap_commit_update_v(&direct->d_bmap, &oldreq, &newreq);
301 set_buffer_nilfs_volatile(bh); 331 set_buffer_nilfs_volatile(bh);
302 nilfs_direct_set_ptr(direct, key, newreq.bpr_ptr); 332 nilfs_direct_set_ptr(direct, key, newreq.bpr_ptr);
303 } else 333 } else
@@ -309,12 +339,10 @@ static int nilfs_direct_propagate_v(struct nilfs_direct *direct,
309static int nilfs_direct_propagate(const struct nilfs_bmap *bmap, 339static int nilfs_direct_propagate(const struct nilfs_bmap *bmap,
310 struct buffer_head *bh) 340 struct buffer_head *bh)
311{ 341{
312 struct nilfs_direct *direct; 342 struct nilfs_direct *direct = (struct nilfs_direct *)bmap;
313 343
314 direct = (struct nilfs_direct *)bmap; 344 return NILFS_BMAP_USE_VBN(bmap) ?
315 return (direct->d_ops->dop_propagate != NULL) ? 345 nilfs_direct_propagate_v(direct, bh) : 0;
316 direct->d_ops->dop_propagate(direct, bh) :
317 0;
318} 346}
319 347
320static int nilfs_direct_assign_v(struct nilfs_direct *direct, 348static int nilfs_direct_assign_v(struct nilfs_direct *direct,
@@ -327,12 +355,9 @@ static int nilfs_direct_assign_v(struct nilfs_direct *direct,
327 int ret; 355 int ret;
328 356
329 req.bpr_ptr = ptr; 357 req.bpr_ptr = ptr;
330 ret = direct->d_bmap.b_pops->bpop_prepare_start_ptr( 358 ret = nilfs_bmap_start_v(&direct->d_bmap, &req, blocknr);
331 &direct->d_bmap, &req); 359 if (unlikely(ret < 0))
332 if (ret < 0)
333 return ret; 360 return ret;
334 direct->d_bmap.b_pops->bpop_commit_start_ptr(&direct->d_bmap,
335 &req, blocknr);
336 361
337 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr); 362 binfo->bi_v.bi_vblocknr = nilfs_bmap_ptr_to_dptr(ptr);
338 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key); 363 binfo->bi_v.bi_blkoff = nilfs_bmap_key_to_dkey(key);
@@ -377,12 +402,14 @@ static int nilfs_direct_assign(struct nilfs_bmap *bmap,
377 return -EINVAL; 402 return -EINVAL;
378 } 403 }
379 404
380 return direct->d_ops->dop_assign(direct, key, ptr, bh, 405 return NILFS_BMAP_USE_VBN(bmap) ?
381 blocknr, binfo); 406 nilfs_direct_assign_v(direct, key, ptr, bh, blocknr, binfo) :
407 nilfs_direct_assign_p(direct, key, ptr, bh, blocknr, binfo);
382} 408}
383 409
384static const struct nilfs_bmap_operations nilfs_direct_ops = { 410static const struct nilfs_bmap_operations nilfs_direct_ops = {
385 .bop_lookup = nilfs_direct_lookup, 411 .bop_lookup = nilfs_direct_lookup,
412 .bop_lookup_contig = nilfs_direct_lookup_contig,
386 .bop_insert = nilfs_direct_insert, 413 .bop_insert = nilfs_direct_insert,
387 .bop_delete = nilfs_direct_delete, 414 .bop_delete = nilfs_direct_delete,
388 .bop_clear = NULL, 415 .bop_clear = NULL,
@@ -401,36 +428,8 @@ static const struct nilfs_bmap_operations nilfs_direct_ops = {
401}; 428};
402 429
403 430
404static const struct nilfs_direct_operations nilfs_direct_ops_v = { 431int nilfs_direct_init(struct nilfs_bmap *bmap)
405 .dop_find_target = nilfs_direct_find_target_v,
406 .dop_set_target = nilfs_direct_set_target_v,
407 .dop_propagate = nilfs_direct_propagate_v,
408 .dop_assign = nilfs_direct_assign_v,
409};
410
411static const struct nilfs_direct_operations nilfs_direct_ops_p = {
412 .dop_find_target = NULL,
413 .dop_set_target = NULL,
414 .dop_propagate = NULL,
415 .dop_assign = nilfs_direct_assign_p,
416};
417
418int nilfs_direct_init(struct nilfs_bmap *bmap, __u64 low, __u64 high)
419{ 432{
420 struct nilfs_direct *direct;
421
422 direct = (struct nilfs_direct *)bmap;
423 bmap->b_ops = &nilfs_direct_ops; 433 bmap->b_ops = &nilfs_direct_ops;
424 bmap->b_low = low;
425 bmap->b_high = high;
426 switch (bmap->b_inode->i_ino) {
427 case NILFS_DAT_INO:
428 direct->d_ops = &nilfs_direct_ops_p;
429 break;
430 default:
431 direct->d_ops = &nilfs_direct_ops_v;
432 break;
433 }
434
435 return 0; 434 return 0;
436} 435}
diff --git a/fs/nilfs2/direct.h b/fs/nilfs2/direct.h
index 45d2c5cda812..a5ffd66e25d0 100644
--- a/fs/nilfs2/direct.h
+++ b/fs/nilfs2/direct.h
@@ -31,18 +31,6 @@
31struct nilfs_direct; 31struct nilfs_direct;
32 32
33/** 33/**
34 * struct nilfs_direct_operations - direct mapping operation table
35 */
36struct nilfs_direct_operations {
37 __u64 (*dop_find_target)(const struct nilfs_direct *, __u64);
38 void (*dop_set_target)(struct nilfs_direct *, __u64, __u64);
39 int (*dop_propagate)(struct nilfs_direct *, struct buffer_head *);
40 int (*dop_assign)(struct nilfs_direct *, __u64, __u64,
41 struct buffer_head **, sector_t,
42 union nilfs_binfo *);
43};
44
45/**
46 * struct nilfs_direct_node - direct node 34 * struct nilfs_direct_node - direct node
47 * @dn_flags: flags 35 * @dn_flags: flags
48 * @dn_pad: padding 36 * @dn_pad: padding
@@ -55,13 +43,9 @@ struct nilfs_direct_node {
55/** 43/**
56 * struct nilfs_direct - direct mapping 44 * struct nilfs_direct - direct mapping
57 * @d_bmap: bmap structure 45 * @d_bmap: bmap structure
58 * @d_ops: direct mapping operation table
59 */ 46 */
60struct nilfs_direct { 47struct nilfs_direct {
61 struct nilfs_bmap d_bmap; 48 struct nilfs_bmap d_bmap;
62
63 /* direct-mapping-specific members */
64 const struct nilfs_direct_operations *d_ops;
65}; 49};
66 50
67 51
@@ -70,9 +54,9 @@ struct nilfs_direct {
70#define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1) 54#define NILFS_DIRECT_KEY_MAX (NILFS_DIRECT_NBLOCKS - 1)
71 55
72 56
73int nilfs_direct_init(struct nilfs_bmap *, __u64, __u64); 57int nilfs_direct_init(struct nilfs_bmap *);
74int nilfs_direct_delete_and_convert(struct nilfs_bmap *, __u64, __u64 *, 58int nilfs_direct_delete_and_convert(struct nilfs_bmap *, __u64, __u64 *,
75 __u64 *, int, __u64, __u64); 59 __u64 *, int);
76 60
77 61
78#endif /* _NILFS_DIRECT_H */ 62#endif /* _NILFS_DIRECT_H */
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index 19d2102b6a69..1b3c2bb20da9 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -52,8 +52,9 @@
52#include "dat.h" 52#include "dat.h"
53#include "ifile.h" 53#include "ifile.h"
54 54
55static struct address_space_operations def_gcinode_aops = {}; 55static struct address_space_operations def_gcinode_aops = {
56/* XXX need def_gcinode_iops/fops? */ 56 .sync_page = block_sync_page,
57};
57 58
58/* 59/*
59 * nilfs_gccache_submit_read_data() - add data buffer and submit read request 60 * nilfs_gccache_submit_read_data() - add data buffer and submit read request
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index 49ab4a49bb4f..2696d6b513b7 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -43,22 +43,23 @@
43 * 43 *
44 * This function does not issue actual read request of the specified data 44 * This function does not issue actual read request of the specified data
45 * block. It is done by VFS. 45 * block. It is done by VFS.
46 * Bulk read for direct-io is not supported yet. (should be supported)
47 */ 46 */
48int nilfs_get_block(struct inode *inode, sector_t blkoff, 47int nilfs_get_block(struct inode *inode, sector_t blkoff,
49 struct buffer_head *bh_result, int create) 48 struct buffer_head *bh_result, int create)
50{ 49{
51 struct nilfs_inode_info *ii = NILFS_I(inode); 50 struct nilfs_inode_info *ii = NILFS_I(inode);
52 unsigned long blknum = 0; 51 __u64 blknum = 0;
53 int err = 0, ret; 52 int err = 0, ret;
54 struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode)); 53 struct inode *dat = nilfs_dat_inode(NILFS_I_NILFS(inode));
54 unsigned maxblocks = bh_result->b_size >> inode->i_blkbits;
55 55
56 /* This exclusion control is a workaround; should be revised */ 56 down_read(&NILFS_MDT(dat)->mi_sem);
57 down_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ 57 ret = nilfs_bmap_lookup_contig(ii->i_bmap, blkoff, &blknum, maxblocks);
58 ret = nilfs_bmap_lookup(ii->i_bmap, (unsigned long)blkoff, &blknum); 58 up_read(&NILFS_MDT(dat)->mi_sem);
59 up_read(&NILFS_MDT(dat)->mi_sem); /* XXX */ 59 if (ret >= 0) { /* found */
60 if (ret == 0) { /* found */
61 map_bh(bh_result, inode->i_sb, blknum); 60 map_bh(bh_result, inode->i_sb, blknum);
61 if (ret > 0)
62 bh_result->b_size = (ret << inode->i_blkbits);
62 goto out; 63 goto out;
63 } 64 }
64 /* data block was not found */ 65 /* data block was not found */
@@ -240,7 +241,7 @@ nilfs_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov,
240struct address_space_operations nilfs_aops = { 241struct address_space_operations nilfs_aops = {
241 .writepage = nilfs_writepage, 242 .writepage = nilfs_writepage,
242 .readpage = nilfs_readpage, 243 .readpage = nilfs_readpage,
243 /* .sync_page = nilfs_sync_page, */ 244 .sync_page = block_sync_page,
244 .writepages = nilfs_writepages, 245 .writepages = nilfs_writepages,
245 .set_page_dirty = nilfs_set_page_dirty, 246 .set_page_dirty = nilfs_set_page_dirty,
246 .readpages = nilfs_readpages, 247 .readpages = nilfs_readpages,
@@ -249,6 +250,7 @@ struct address_space_operations nilfs_aops = {
249 /* .releasepage = nilfs_releasepage, */ 250 /* .releasepage = nilfs_releasepage, */
250 .invalidatepage = block_invalidatepage, 251 .invalidatepage = block_invalidatepage,
251 .direct_IO = nilfs_direct_IO, 252 .direct_IO = nilfs_direct_IO,
253 .is_partially_uptodate = block_is_partially_uptodate,
252}; 254};
253 255
254struct inode *nilfs_new_inode(struct inode *dir, int mode) 256struct inode *nilfs_new_inode(struct inode *dir, int mode)
diff --git a/fs/nilfs2/ioctl.c b/fs/nilfs2/ioctl.c
index d6759b92006f..6ea5f872e2de 100644
--- a/fs/nilfs2/ioctl.c
+++ b/fs/nilfs2/ioctl.c
@@ -152,7 +152,7 @@ nilfs_ioctl_do_get_cpinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
152 152
153 down_read(&nilfs->ns_segctor_sem); 153 down_read(&nilfs->ns_segctor_sem);
154 ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf, 154 ret = nilfs_cpfile_get_cpinfo(nilfs->ns_cpfile, posp, flags, buf,
155 nmembs); 155 size, nmembs);
156 up_read(&nilfs->ns_segctor_sem); 156 up_read(&nilfs->ns_segctor_sem);
157 return ret; 157 return ret;
158} 158}
@@ -182,7 +182,8 @@ nilfs_ioctl_do_get_suinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
182 int ret; 182 int ret;
183 183
184 down_read(&nilfs->ns_segctor_sem); 184 down_read(&nilfs->ns_segctor_sem);
185 ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, nmembs); 185 ret = nilfs_sufile_get_suinfo(nilfs->ns_sufile, *posp, buf, size,
186 nmembs);
186 up_read(&nilfs->ns_segctor_sem); 187 up_read(&nilfs->ns_segctor_sem);
187 return ret; 188 return ret;
188} 189}
@@ -212,7 +213,7 @@ nilfs_ioctl_do_get_vinfo(struct the_nilfs *nilfs, __u64 *posp, int flags,
212 int ret; 213 int ret;
213 214
214 down_read(&nilfs->ns_segctor_sem); 215 down_read(&nilfs->ns_segctor_sem);
215 ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, nmembs); 216 ret = nilfs_dat_get_vinfo(nilfs_dat_inode(nilfs), buf, size, nmembs);
216 up_read(&nilfs->ns_segctor_sem); 217 up_read(&nilfs->ns_segctor_sem);
217 return ret; 218 return ret;
218} 219}
@@ -435,24 +436,6 @@ static int nilfs_ioctl_mark_blocks_dirty(struct the_nilfs *nilfs,
435 return nmembs; 436 return nmembs;
436} 437}
437 438
438static int nilfs_ioctl_free_segments(struct the_nilfs *nilfs,
439 struct nilfs_argv *argv, void *buf)
440{
441 size_t nmembs = argv->v_nmembs;
442 struct nilfs_sb_info *sbi = nilfs->ns_writer;
443 int ret;
444
445 if (unlikely(!sbi)) {
446 /* never happens because called for a writable mount */
447 WARN_ON(1);
448 return -EROFS;
449 }
450 ret = nilfs_segctor_add_segments_to_be_freed(
451 NILFS_SC(sbi), buf, nmembs);
452
453 return (ret < 0) ? ret : nmembs;
454}
455
456int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs, 439int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
457 struct nilfs_argv *argv, void **kbufs) 440 struct nilfs_argv *argv, void **kbufs)
458{ 441{
@@ -491,14 +474,6 @@ int nilfs_ioctl_prepare_clean_segments(struct the_nilfs *nilfs,
491 msg = "cannot mark copying blocks dirty"; 474 msg = "cannot mark copying blocks dirty";
492 goto failed; 475 goto failed;
493 } 476 }
494 ret = nilfs_ioctl_free_segments(nilfs, &argv[4], kbufs[4]);
495 if (ret < 0) {
496 /*
497 * can safely abort because this operation is atomic.
498 */
499 msg = "cannot set segments to be freed";
500 goto failed;
501 }
502 return 0; 477 return 0;
503 478
504 failed: 479 failed:
@@ -615,7 +590,7 @@ static int nilfs_ioctl_get_info(struct inode *inode, struct file *filp,
615 if (copy_from_user(&argv, argp, sizeof(argv))) 590 if (copy_from_user(&argv, argp, sizeof(argv)))
616 return -EFAULT; 591 return -EFAULT;
617 592
618 if (argv.v_size != membsz) 593 if (argv.v_size < membsz)
619 return -EINVAL; 594 return -EINVAL;
620 595
621 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc); 596 ret = nilfs_ioctl_wrap_copy(nilfs, &argv, _IOC_DIR(cmd), dofunc);
diff --git a/fs/nilfs2/mdt.c b/fs/nilfs2/mdt.c
index bb78745a0e30..3d3ddb3f5177 100644
--- a/fs/nilfs2/mdt.c
+++ b/fs/nilfs2/mdt.c
@@ -430,6 +430,7 @@ nilfs_mdt_write_page(struct page *page, struct writeback_control *wbc)
430 430
431static struct address_space_operations def_mdt_aops = { 431static struct address_space_operations def_mdt_aops = {
432 .writepage = nilfs_mdt_write_page, 432 .writepage = nilfs_mdt_write_page,
433 .sync_page = block_sync_page,
433}; 434};
434 435
435static struct inode_operations def_mdt_iops; 436static struct inode_operations def_mdt_iops;
@@ -449,7 +450,7 @@ struct inode *
449nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb, 450nilfs_mdt_new_common(struct the_nilfs *nilfs, struct super_block *sb,
450 ino_t ino, gfp_t gfp_mask) 451 ino_t ino, gfp_t gfp_mask)
451{ 452{
452 struct inode *inode = nilfs_alloc_inode(sb); 453 struct inode *inode = nilfs_alloc_inode_common(nilfs);
453 454
454 if (!inode) 455 if (!inode)
455 return NULL; 456 return NULL;
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index da6fc0bba2e5..edf6a59d9f2a 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -263,6 +263,7 @@ extern void nilfs_dirty_inode(struct inode *);
263extern struct dentry *nilfs_get_parent(struct dentry *); 263extern struct dentry *nilfs_get_parent(struct dentry *);
264 264
265/* super.c */ 265/* super.c */
266extern struct inode *nilfs_alloc_inode_common(struct the_nilfs *);
266extern struct inode *nilfs_alloc_inode(struct super_block *); 267extern struct inode *nilfs_alloc_inode(struct super_block *);
267extern void nilfs_destroy_inode(struct inode *); 268extern void nilfs_destroy_inode(struct inode *);
268extern void nilfs_error(struct super_block *, const char *, const char *, ...) 269extern void nilfs_error(struct super_block *, const char *, const char *, ...)
diff --git a/fs/nilfs2/recovery.c b/fs/nilfs2/recovery.c
index 57afa9d24061..d80cc71be749 100644
--- a/fs/nilfs2/recovery.c
+++ b/fs/nilfs2/recovery.c
@@ -28,7 +28,6 @@
28#include "segment.h" 28#include "segment.h"
29#include "sufile.h" 29#include "sufile.h"
30#include "page.h" 30#include "page.h"
31#include "seglist.h"
32#include "segbuf.h" 31#include "segbuf.h"
33 32
34/* 33/*
@@ -395,6 +394,24 @@ static void dispose_recovery_list(struct list_head *head)
395 } 394 }
396} 395}
397 396
397struct nilfs_segment_entry {
398 struct list_head list;
399 __u64 segnum;
400};
401
402static int nilfs_segment_list_add(struct list_head *head, __u64 segnum)
403{
404 struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
405
406 if (unlikely(!ent))
407 return -ENOMEM;
408
409 ent->segnum = segnum;
410 INIT_LIST_HEAD(&ent->list);
411 list_add_tail(&ent->list, head);
412 return 0;
413}
414
398void nilfs_dispose_segment_list(struct list_head *head) 415void nilfs_dispose_segment_list(struct list_head *head)
399{ 416{
400 while (!list_empty(head)) { 417 while (!list_empty(head)) {
@@ -402,7 +419,7 @@ void nilfs_dispose_segment_list(struct list_head *head)
402 = list_entry(head->next, 419 = list_entry(head->next,
403 struct nilfs_segment_entry, list); 420 struct nilfs_segment_entry, list);
404 list_del(&ent->list); 421 list_del(&ent->list);
405 nilfs_free_segment_entry(ent); 422 kfree(ent);
406 } 423 }
407} 424}
408 425
@@ -431,12 +448,10 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
431 if (unlikely(err)) 448 if (unlikely(err))
432 goto failed; 449 goto failed;
433 450
434 err = -ENOMEM;
435 for (i = 1; i < 4; i++) { 451 for (i = 1; i < 4; i++) {
436 ent = nilfs_alloc_segment_entry(segnum[i]); 452 err = nilfs_segment_list_add(head, segnum[i]);
437 if (unlikely(!ent)) 453 if (unlikely(err))
438 goto failed; 454 goto failed;
439 list_add_tail(&ent->list, head);
440 } 455 }
441 456
442 /* 457 /*
@@ -450,7 +465,7 @@ static int nilfs_prepare_segment_for_recovery(struct the_nilfs *nilfs,
450 goto failed; 465 goto failed;
451 } 466 }
452 list_del(&ent->list); 467 list_del(&ent->list);
453 nilfs_free_segment_entry(ent); 468 kfree(ent);
454 } 469 }
455 470
456 /* Allocate new segments for recovery */ 471 /* Allocate new segments for recovery */
@@ -791,7 +806,6 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
791 u64 seg_seq; 806 u64 seg_seq;
792 __u64 segnum, nextnum = 0; 807 __u64 segnum, nextnum = 0;
793 __u64 cno; 808 __u64 cno;
794 struct nilfs_segment_entry *ent;
795 LIST_HEAD(segments); 809 LIST_HEAD(segments);
796 int empty_seg = 0, scan_newer = 0; 810 int empty_seg = 0, scan_newer = 0;
797 int ret; 811 int ret;
@@ -892,12 +906,9 @@ int nilfs_search_super_root(struct the_nilfs *nilfs, struct nilfs_sb_info *sbi,
892 if (empty_seg++) 906 if (empty_seg++)
893 goto super_root_found; /* found a valid super root */ 907 goto super_root_found; /* found a valid super root */
894 908
895 ent = nilfs_alloc_segment_entry(segnum); 909 ret = nilfs_segment_list_add(&segments, segnum);
896 if (unlikely(!ent)) { 910 if (unlikely(ret))
897 ret = -ENOMEM;
898 goto failed; 911 goto failed;
899 }
900 list_add_tail(&ent->list, &segments);
901 912
902 seg_seq++; 913 seg_seq++;
903 segnum = nextnum; 914 segnum = nextnum;
diff --git a/fs/nilfs2/segbuf.c b/fs/nilfs2/segbuf.c
index 1e68821b4a9b..9e3fe17bb96b 100644
--- a/fs/nilfs2/segbuf.c
+++ b/fs/nilfs2/segbuf.c
@@ -26,7 +26,6 @@
26#include <linux/crc32.h> 26#include <linux/crc32.h>
27#include "page.h" 27#include "page.h"
28#include "segbuf.h" 28#include "segbuf.h"
29#include "seglist.h"
30 29
31 30
32static struct kmem_cache *nilfs_segbuf_cachep; 31static struct kmem_cache *nilfs_segbuf_cachep;
@@ -394,7 +393,7 @@ int nilfs_segbuf_write(struct nilfs_segment_buffer *segbuf,
394 * Last BIO is always sent through the following 393 * Last BIO is always sent through the following
395 * submission. 394 * submission.
396 */ 395 */
397 rw |= (1 << BIO_RW_SYNCIO); 396 rw |= (1 << BIO_RW_SYNCIO) | (1 << BIO_RW_UNPLUG);
398 res = nilfs_submit_seg_bio(wi, rw); 397 res = nilfs_submit_seg_bio(wi, rw);
399 if (unlikely(res)) 398 if (unlikely(res))
400 goto failed_bio; 399 goto failed_bio;
diff --git a/fs/nilfs2/seglist.h b/fs/nilfs2/seglist.h
deleted file mode 100644
index d39df9144e99..000000000000
--- a/fs/nilfs2/seglist.h
+++ /dev/null
@@ -1,85 +0,0 @@
1/*
2 * seglist.h - expediential structure and routines to handle list of segments
3 * (would be removed in a future release)
4 *
5 * Copyright (C) 2005-2008 Nippon Telegraph and Telephone Corporation.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 *
21 * Written by Ryusuke Konishi <ryusuke@osrg.net>
22 *
23 */
24#ifndef _NILFS_SEGLIST_H
25#define _NILFS_SEGLIST_H
26
27#include <linux/fs.h>
28#include <linux/buffer_head.h>
29#include <linux/nilfs2_fs.h>
30#include "sufile.h"
31
32struct nilfs_segment_entry {
33 __u64 segnum;
34
35#define NILFS_SLH_FREED 0x0001 /* The segment was freed provisonally.
36 It must be cancelled if
37 construction aborted */
38
39 unsigned flags;
40 struct list_head list;
41 struct buffer_head *bh_su;
42 struct nilfs_segment_usage *raw_su;
43};
44
45
46void nilfs_dispose_segment_list(struct list_head *);
47
48static inline struct nilfs_segment_entry *
49nilfs_alloc_segment_entry(__u64 segnum)
50{
51 struct nilfs_segment_entry *ent = kmalloc(sizeof(*ent), GFP_NOFS);
52
53 if (likely(ent)) {
54 ent->segnum = segnum;
55 ent->flags = 0;
56 ent->bh_su = NULL;
57 ent->raw_su = NULL;
58 INIT_LIST_HEAD(&ent->list);
59 }
60 return ent;
61}
62
63static inline int nilfs_open_segment_entry(struct nilfs_segment_entry *ent,
64 struct inode *sufile)
65{
66 return nilfs_sufile_get_segment_usage(sufile, ent->segnum,
67 &ent->raw_su, &ent->bh_su);
68}
69
70static inline void nilfs_close_segment_entry(struct nilfs_segment_entry *ent,
71 struct inode *sufile)
72{
73 if (!ent->bh_su)
74 return;
75 nilfs_sufile_put_segment_usage(sufile, ent->segnum, ent->bh_su);
76 ent->bh_su = NULL;
77 ent->raw_su = NULL;
78}
79
80static inline void nilfs_free_segment_entry(struct nilfs_segment_entry *ent)
81{
82 kfree(ent);
83}
84
85#endif /* _NILFS_SEGLIST_H */
diff --git a/fs/nilfs2/segment.c b/fs/nilfs2/segment.c
index 22c7f65c2403..aa977549919e 100644
--- a/fs/nilfs2/segment.c
+++ b/fs/nilfs2/segment.c
@@ -39,7 +39,6 @@
39#include "sufile.h" 39#include "sufile.h"
40#include "cpfile.h" 40#include "cpfile.h"
41#include "ifile.h" 41#include "ifile.h"
42#include "seglist.h"
43#include "segbuf.h" 42#include "segbuf.h"
44 43
45 44
@@ -79,7 +78,8 @@ enum {
79/* State flags of collection */ 78/* State flags of collection */
80#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */ 79#define NILFS_CF_NODE 0x0001 /* Collecting node blocks */
81#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */ 80#define NILFS_CF_IFILE_STARTED 0x0002 /* IFILE stage has started */
82#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED) 81#define NILFS_CF_SUFREED 0x0004 /* segment usages has been freed */
82#define NILFS_CF_HISTORY_MASK (NILFS_CF_IFILE_STARTED | NILFS_CF_SUFREED)
83 83
84/* Operations depending on the construction mode and file type */ 84/* Operations depending on the construction mode and file type */
85struct nilfs_sc_operations { 85struct nilfs_sc_operations {
@@ -810,7 +810,7 @@ static int nilfs_segctor_clean(struct nilfs_sc_info *sci)
810{ 810{
811 return list_empty(&sci->sc_dirty_files) && 811 return list_empty(&sci->sc_dirty_files) &&
812 !test_bit(NILFS_SC_DIRTY, &sci->sc_flags) && 812 !test_bit(NILFS_SC_DIRTY, &sci->sc_flags) &&
813 list_empty(&sci->sc_cleaning_segments) && 813 sci->sc_nfreesegs == 0 &&
814 (!nilfs_doing_gc() || list_empty(&sci->sc_gc_inodes)); 814 (!nilfs_doing_gc() || list_empty(&sci->sc_gc_inodes));
815} 815}
816 816
@@ -1005,44 +1005,6 @@ static void nilfs_drop_collected_inodes(struct list_head *head)
1005 } 1005 }
1006} 1006}
1007 1007
1008static void nilfs_segctor_cancel_free_segments(struct nilfs_sc_info *sci,
1009 struct inode *sufile)
1010
1011{
1012 struct list_head *head = &sci->sc_cleaning_segments;
1013 struct nilfs_segment_entry *ent;
1014 int err;
1015
1016 list_for_each_entry(ent, head, list) {
1017 if (!(ent->flags & NILFS_SLH_FREED))
1018 break;
1019 err = nilfs_sufile_cancel_free(sufile, ent->segnum);
1020 WARN_ON(err); /* do not happen */
1021 ent->flags &= ~NILFS_SLH_FREED;
1022 }
1023}
1024
1025static int nilfs_segctor_prepare_free_segments(struct nilfs_sc_info *sci,
1026 struct inode *sufile)
1027{
1028 struct list_head *head = &sci->sc_cleaning_segments;
1029 struct nilfs_segment_entry *ent;
1030 int err;
1031
1032 list_for_each_entry(ent, head, list) {
1033 err = nilfs_sufile_free(sufile, ent->segnum);
1034 if (unlikely(err))
1035 return err;
1036 ent->flags |= NILFS_SLH_FREED;
1037 }
1038 return 0;
1039}
1040
1041static void nilfs_segctor_commit_free_segments(struct nilfs_sc_info *sci)
1042{
1043 nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
1044}
1045
1046static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci, 1008static int nilfs_segctor_apply_buffers(struct nilfs_sc_info *sci,
1047 struct inode *inode, 1009 struct inode *inode,
1048 struct list_head *listp, 1010 struct list_head *listp,
@@ -1161,6 +1123,7 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1161 struct the_nilfs *nilfs = sbi->s_nilfs; 1123 struct the_nilfs *nilfs = sbi->s_nilfs;
1162 struct list_head *head; 1124 struct list_head *head;
1163 struct nilfs_inode_info *ii; 1125 struct nilfs_inode_info *ii;
1126 size_t ndone;
1164 int err = 0; 1127 int err = 0;
1165 1128
1166 switch (sci->sc_stage.scnt) { 1129 switch (sci->sc_stage.scnt) {
@@ -1250,10 +1213,16 @@ static int nilfs_segctor_collect_blocks(struct nilfs_sc_info *sci, int mode)
1250 break; 1213 break;
1251 sci->sc_stage.scnt++; /* Fall through */ 1214 sci->sc_stage.scnt++; /* Fall through */
1252 case NILFS_ST_SUFILE: 1215 case NILFS_ST_SUFILE:
1253 err = nilfs_segctor_prepare_free_segments(sci, 1216 err = nilfs_sufile_freev(nilfs->ns_sufile, sci->sc_freesegs,
1254 nilfs->ns_sufile); 1217 sci->sc_nfreesegs, &ndone);
1255 if (unlikely(err)) 1218 if (unlikely(err)) {
1219 nilfs_sufile_cancel_freev(nilfs->ns_sufile,
1220 sci->sc_freesegs, ndone,
1221 NULL);
1256 break; 1222 break;
1223 }
1224 sci->sc_stage.flags |= NILFS_CF_SUFREED;
1225
1257 err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile, 1226 err = nilfs_segctor_scan_file(sci, nilfs->ns_sufile,
1258 &nilfs_sc_file_ops); 1227 &nilfs_sc_file_ops);
1259 if (unlikely(err)) 1228 if (unlikely(err))
@@ -1486,7 +1455,15 @@ static void nilfs_segctor_end_construction(struct nilfs_sc_info *sci,
1486{ 1455{
1487 if (unlikely(err)) { 1456 if (unlikely(err)) {
1488 nilfs_segctor_free_incomplete_segments(sci, nilfs); 1457 nilfs_segctor_free_incomplete_segments(sci, nilfs);
1489 nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile); 1458 if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
1459 int ret;
1460
1461 ret = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
1462 sci->sc_freesegs,
1463 sci->sc_nfreesegs,
1464 NULL);
1465 WARN_ON(ret); /* do not happen */
1466 }
1490 } 1467 }
1491 nilfs_segctor_clear_segment_buffers(sci); 1468 nilfs_segctor_clear_segment_buffers(sci);
1492} 1469}
@@ -1585,7 +1562,13 @@ static int nilfs_segctor_collect(struct nilfs_sc_info *sci,
1585 if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE) 1562 if (mode != SC_LSEG_SR || sci->sc_stage.scnt < NILFS_ST_CPFILE)
1586 break; 1563 break;
1587 1564
1588 nilfs_segctor_cancel_free_segments(sci, nilfs->ns_sufile); 1565 if (sci->sc_stage.flags & NILFS_CF_SUFREED) {
1566 err = nilfs_sufile_cancel_freev(nilfs->ns_sufile,
1567 sci->sc_freesegs,
1568 sci->sc_nfreesegs,
1569 NULL);
1570 WARN_ON(err); /* do not happen */
1571 }
1589 nilfs_segctor_clear_segment_buffers(sci); 1572 nilfs_segctor_clear_segment_buffers(sci);
1590 1573
1591 err = nilfs_segctor_extend_segments(sci, nilfs, nadd); 1574 err = nilfs_segctor_extend_segments(sci, nilfs, nadd);
@@ -2224,10 +2207,8 @@ static int nilfs_segctor_do_construct(struct nilfs_sc_info *sci, int mode)
2224 nilfs_segctor_complete_write(sci); 2207 nilfs_segctor_complete_write(sci);
2225 2208
2226 /* Commit segments */ 2209 /* Commit segments */
2227 if (has_sr) { 2210 if (has_sr)
2228 nilfs_segctor_commit_free_segments(sci);
2229 nilfs_segctor_clear_metadata_dirty(sci); 2211 nilfs_segctor_clear_metadata_dirty(sci);
2230 }
2231 2212
2232 nilfs_segctor_end_construction(sci, nilfs, 0); 2213 nilfs_segctor_end_construction(sci, nilfs, 0);
2233 2214
@@ -2301,48 +2282,6 @@ void nilfs_flush_segment(struct super_block *sb, ino_t ino)
2301 /* assign bit 0 to data files */ 2282 /* assign bit 0 to data files */
2302} 2283}
2303 2284
2304int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *sci,
2305 __u64 *segnum, size_t nsegs)
2306{
2307 struct nilfs_segment_entry *ent;
2308 struct the_nilfs *nilfs = sci->sc_sbi->s_nilfs;
2309 struct inode *sufile = nilfs->ns_sufile;
2310 LIST_HEAD(list);
2311 __u64 *pnum;
2312 size_t i;
2313 int err;
2314
2315 for (pnum = segnum, i = 0; i < nsegs; pnum++, i++) {
2316 ent = nilfs_alloc_segment_entry(*pnum);
2317 if (unlikely(!ent)) {
2318 err = -ENOMEM;
2319 goto failed;
2320 }
2321 list_add_tail(&ent->list, &list);
2322
2323 err = nilfs_open_segment_entry(ent, sufile);
2324 if (unlikely(err))
2325 goto failed;
2326
2327 if (unlikely(!nilfs_segment_usage_dirty(ent->raw_su)))
2328 printk(KERN_WARNING "NILFS: unused segment is "
2329 "requested to be cleaned (segnum=%llu)\n",
2330 (unsigned long long)ent->segnum);
2331 nilfs_close_segment_entry(ent, sufile);
2332 }
2333 list_splice(&list, sci->sc_cleaning_segments.prev);
2334 return 0;
2335
2336 failed:
2337 nilfs_dispose_segment_list(&list);
2338 return err;
2339}
2340
2341void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *sci)
2342{
2343 nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
2344}
2345
2346struct nilfs_segctor_wait_request { 2285struct nilfs_segctor_wait_request {
2347 wait_queue_t wq; 2286 wait_queue_t wq;
2348 __u32 seq; 2287 __u32 seq;
@@ -2607,10 +2546,13 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
2607 err = nilfs_init_gcdat_inode(nilfs); 2546 err = nilfs_init_gcdat_inode(nilfs);
2608 if (unlikely(err)) 2547 if (unlikely(err))
2609 goto out_unlock; 2548 goto out_unlock;
2549
2610 err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs); 2550 err = nilfs_ioctl_prepare_clean_segments(nilfs, argv, kbufs);
2611 if (unlikely(err)) 2551 if (unlikely(err))
2612 goto out_unlock; 2552 goto out_unlock;
2613 2553
2554 sci->sc_freesegs = kbufs[4];
2555 sci->sc_nfreesegs = argv[4].v_nmembs;
2614 list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev); 2556 list_splice_init(&nilfs->ns_gc_inodes, sci->sc_gc_inodes.prev);
2615 2557
2616 for (;;) { 2558 for (;;) {
@@ -2629,6 +2571,8 @@ int nilfs_clean_segments(struct super_block *sb, struct nilfs_argv *argv,
2629 } 2571 }
2630 2572
2631 out_unlock: 2573 out_unlock:
2574 sci->sc_freesegs = NULL;
2575 sci->sc_nfreesegs = 0;
2632 nilfs_clear_gcdat_inode(nilfs); 2576 nilfs_clear_gcdat_inode(nilfs);
2633 nilfs_transaction_unlock(sbi); 2577 nilfs_transaction_unlock(sbi);
2634 return err; 2578 return err;
@@ -2835,7 +2779,6 @@ static struct nilfs_sc_info *nilfs_segctor_new(struct nilfs_sb_info *sbi)
2835 INIT_LIST_HEAD(&sci->sc_dirty_files); 2779 INIT_LIST_HEAD(&sci->sc_dirty_files);
2836 INIT_LIST_HEAD(&sci->sc_segbufs); 2780 INIT_LIST_HEAD(&sci->sc_segbufs);
2837 INIT_LIST_HEAD(&sci->sc_gc_inodes); 2781 INIT_LIST_HEAD(&sci->sc_gc_inodes);
2838 INIT_LIST_HEAD(&sci->sc_cleaning_segments);
2839 INIT_LIST_HEAD(&sci->sc_copied_buffers); 2782 INIT_LIST_HEAD(&sci->sc_copied_buffers);
2840 2783
2841 sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT; 2784 sci->sc_interval = HZ * NILFS_SC_DEFAULT_TIMEOUT;
@@ -2901,9 +2844,6 @@ static void nilfs_segctor_destroy(struct nilfs_sc_info *sci)
2901 nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1); 2844 nilfs_dispose_list(sbi, &sci->sc_dirty_files, 1);
2902 } 2845 }
2903 2846
2904 if (!list_empty(&sci->sc_cleaning_segments))
2905 nilfs_dispose_segment_list(&sci->sc_cleaning_segments);
2906
2907 WARN_ON(!list_empty(&sci->sc_segbufs)); 2847 WARN_ON(!list_empty(&sci->sc_segbufs));
2908 2848
2909 down_write(&sbi->s_nilfs->ns_segctor_sem); 2849 down_write(&sbi->s_nilfs->ns_segctor_sem);
diff --git a/fs/nilfs2/segment.h b/fs/nilfs2/segment.h
index 476bdd5df5be..0d2a475a741b 100644
--- a/fs/nilfs2/segment.h
+++ b/fs/nilfs2/segment.h
@@ -90,8 +90,9 @@ struct nilfs_segsum_pointer {
90 * @sc_nblk_inc: Block count of current generation 90 * @sc_nblk_inc: Block count of current generation
91 * @sc_dirty_files: List of files to be written 91 * @sc_dirty_files: List of files to be written
92 * @sc_gc_inodes: List of GC inodes having blocks to be written 92 * @sc_gc_inodes: List of GC inodes having blocks to be written
93 * @sc_cleaning_segments: List of segments to be freed through construction
94 * @sc_copied_buffers: List of copied buffers (buffer heads) to freeze data 93 * @sc_copied_buffers: List of copied buffers (buffer heads) to freeze data
94 * @sc_freesegs: array of segment numbers to be freed
95 * @sc_nfreesegs: number of segments on @sc_freesegs
95 * @sc_dsync_inode: inode whose data pages are written for a sync operation 96 * @sc_dsync_inode: inode whose data pages are written for a sync operation
96 * @sc_dsync_start: start byte offset of data pages 97 * @sc_dsync_start: start byte offset of data pages
97 * @sc_dsync_end: end byte offset of data pages (inclusive) 98 * @sc_dsync_end: end byte offset of data pages (inclusive)
@@ -131,9 +132,11 @@ struct nilfs_sc_info {
131 132
132 struct list_head sc_dirty_files; 133 struct list_head sc_dirty_files;
133 struct list_head sc_gc_inodes; 134 struct list_head sc_gc_inodes;
134 struct list_head sc_cleaning_segments;
135 struct list_head sc_copied_buffers; 135 struct list_head sc_copied_buffers;
136 136
137 __u64 *sc_freesegs;
138 size_t sc_nfreesegs;
139
137 struct nilfs_inode_info *sc_dsync_inode; 140 struct nilfs_inode_info *sc_dsync_inode;
138 loff_t sc_dsync_start; 141 loff_t sc_dsync_start;
139 loff_t sc_dsync_end; 142 loff_t sc_dsync_end;
@@ -225,10 +228,6 @@ extern void nilfs_flush_segment(struct super_block *, ino_t);
225extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *, 228extern int nilfs_clean_segments(struct super_block *, struct nilfs_argv *,
226 void **); 229 void **);
227 230
228extern int nilfs_segctor_add_segments_to_be_freed(struct nilfs_sc_info *,
229 __u64 *, size_t);
230extern void nilfs_segctor_clear_segments_to_be_freed(struct nilfs_sc_info *);
231
232extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *); 231extern int nilfs_attach_segment_constructor(struct nilfs_sb_info *);
233extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *); 232extern void nilfs_detach_segment_constructor(struct nilfs_sb_info *);
234 233
@@ -240,5 +239,6 @@ extern int nilfs_search_super_root(struct the_nilfs *, struct nilfs_sb_info *,
240extern int nilfs_recover_logical_segments(struct the_nilfs *, 239extern int nilfs_recover_logical_segments(struct the_nilfs *,
241 struct nilfs_sb_info *, 240 struct nilfs_sb_info *,
242 struct nilfs_recovery_info *); 241 struct nilfs_recovery_info *);
242extern void nilfs_dispose_segment_list(struct list_head *);
243 243
244#endif /* _NILFS_SEGMENT_H */ 244#endif /* _NILFS_SEGMENT_H */
diff --git a/fs/nilfs2/sufile.c b/fs/nilfs2/sufile.c
index 98e68677f045..37994d4a59cc 100644
--- a/fs/nilfs2/sufile.c
+++ b/fs/nilfs2/sufile.c
@@ -18,6 +18,7 @@
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 * 19 *
20 * Written by Koji Sato <koji@osrg.net>. 20 * Written by Koji Sato <koji@osrg.net>.
21 * Rivised by Ryusuke Konishi <ryusuke@osrg.net>.
21 */ 22 */
22 23
23#include <linux/kernel.h> 24#include <linux/kernel.h>
@@ -108,6 +109,102 @@ static void nilfs_sufile_mod_counter(struct buffer_head *header_bh,
108 nilfs_mdt_mark_buffer_dirty(header_bh); 109 nilfs_mdt_mark_buffer_dirty(header_bh);
109} 110}
110 111
112/**
113 * nilfs_sufile_updatev - modify multiple segment usages at a time
114 * @sufile: inode of segment usage file
115 * @segnumv: array of segment numbers
116 * @nsegs: size of @segnumv array
117 * @create: creation flag
118 * @ndone: place to store number of modified segments on @segnumv
119 * @dofunc: primitive operation for the update
120 *
121 * Description: nilfs_sufile_updatev() repeatedly calls @dofunc
122 * against the given array of segments. The @dofunc is called with
123 * buffers of a header block and the sufile block in which the target
124 * segment usage entry is contained. If @ndone is given, the number
125 * of successfully modified segments from the head is stored in the
126 * place @ndone points to.
127 *
128 * Return Value: On success, zero is returned. On error, one of the
129 * following negative error codes is returned.
130 *
131 * %-EIO - I/O error.
132 *
133 * %-ENOMEM - Insufficient amount of memory available.
134 *
135 * %-ENOENT - Given segment usage is in hole block (may be returned if
136 * @create is zero)
137 *
138 * %-EINVAL - Invalid segment usage number
139 */
140int nilfs_sufile_updatev(struct inode *sufile, __u64 *segnumv, size_t nsegs,
141 int create, size_t *ndone,
142 void (*dofunc)(struct inode *, __u64,
143 struct buffer_head *,
144 struct buffer_head *))
145{
146 struct buffer_head *header_bh, *bh;
147 unsigned long blkoff, prev_blkoff;
148 __u64 *seg;
149 size_t nerr = 0, n = 0;
150 int ret = 0;
151
152 if (unlikely(nsegs == 0))
153 goto out;
154
155 down_write(&NILFS_MDT(sufile)->mi_sem);
156 for (seg = segnumv; seg < segnumv + nsegs; seg++) {
157 if (unlikely(*seg >= nilfs_sufile_get_nsegments(sufile))) {
158 printk(KERN_WARNING
159 "%s: invalid segment number: %llu\n", __func__,
160 (unsigned long long)*seg);
161 nerr++;
162 }
163 }
164 if (nerr > 0) {
165 ret = -EINVAL;
166 goto out_sem;
167 }
168
169 ret = nilfs_sufile_get_header_block(sufile, &header_bh);
170 if (ret < 0)
171 goto out_sem;
172
173 seg = segnumv;
174 blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
175 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
176 if (ret < 0)
177 goto out_header;
178
179 for (;;) {
180 dofunc(sufile, *seg, header_bh, bh);
181
182 if (++seg >= segnumv + nsegs)
183 break;
184 prev_blkoff = blkoff;
185 blkoff = nilfs_sufile_get_blkoff(sufile, *seg);
186 if (blkoff == prev_blkoff)
187 continue;
188
189 /* get different block */
190 brelse(bh);
191 ret = nilfs_mdt_get_block(sufile, blkoff, create, NULL, &bh);
192 if (unlikely(ret < 0))
193 goto out_header;
194 }
195 brelse(bh);
196
197 out_header:
198 n = seg - segnumv;
199 brelse(header_bh);
200 out_sem:
201 up_write(&NILFS_MDT(sufile)->mi_sem);
202 out:
203 if (ndone)
204 *ndone = n;
205 return ret;
206}
207
111int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create, 208int nilfs_sufile_update(struct inode *sufile, __u64 segnum, int create,
112 void (*dofunc)(struct inode *, __u64, 209 void (*dofunc)(struct inode *, __u64,
113 struct buffer_head *, 210 struct buffer_head *,
@@ -490,7 +587,8 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
490 * nilfs_sufile_get_suinfo - 587 * nilfs_sufile_get_suinfo -
491 * @sufile: inode of segment usage file 588 * @sufile: inode of segment usage file
492 * @segnum: segment number to start looking 589 * @segnum: segment number to start looking
493 * @si: array of suinfo 590 * @buf: array of suinfo
591 * @sisz: byte size of suinfo
494 * @nsi: size of suinfo array 592 * @nsi: size of suinfo array
495 * 593 *
496 * Description: 594 * Description:
@@ -502,11 +600,12 @@ void nilfs_sufile_do_set_error(struct inode *sufile, __u64 segnum,
502 * 600 *
503 * %-ENOMEM - Insufficient amount of memory available. 601 * %-ENOMEM - Insufficient amount of memory available.
504 */ 602 */
505ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, 603ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum, void *buf,
506 struct nilfs_suinfo *si, size_t nsi) 604 unsigned sisz, size_t nsi)
507{ 605{
508 struct buffer_head *su_bh; 606 struct buffer_head *su_bh;
509 struct nilfs_segment_usage *su; 607 struct nilfs_segment_usage *su;
608 struct nilfs_suinfo *si = buf;
510 size_t susz = NILFS_MDT(sufile)->mi_entry_size; 609 size_t susz = NILFS_MDT(sufile)->mi_entry_size;
511 struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs; 610 struct the_nilfs *nilfs = NILFS_MDT(sufile)->mi_nilfs;
512 void *kaddr; 611 void *kaddr;
@@ -531,20 +630,22 @@ ssize_t nilfs_sufile_get_suinfo(struct inode *sufile, __u64 segnum,
531 if (ret != -ENOENT) 630 if (ret != -ENOENT)
532 goto out; 631 goto out;
533 /* hole */ 632 /* hole */
534 memset(&si[i], 0, sizeof(struct nilfs_suinfo) * n); 633 memset(si, 0, sisz * n);
634 si = (void *)si + sisz * n;
535 continue; 635 continue;
536 } 636 }
537 637
538 kaddr = kmap_atomic(su_bh->b_page, KM_USER0); 638 kaddr = kmap_atomic(su_bh->b_page, KM_USER0);
539 su = nilfs_sufile_block_get_segment_usage( 639 su = nilfs_sufile_block_get_segment_usage(
540 sufile, segnum, su_bh, kaddr); 640 sufile, segnum, su_bh, kaddr);
541 for (j = 0; j < n; j++, su = (void *)su + susz) { 641 for (j = 0; j < n;
542 si[i + j].sui_lastmod = le64_to_cpu(su->su_lastmod); 642 j++, su = (void *)su + susz, si = (void *)si + sisz) {
543 si[i + j].sui_nblocks = le32_to_cpu(su->su_nblocks); 643 si->sui_lastmod = le64_to_cpu(su->su_lastmod);
544 si[i + j].sui_flags = le32_to_cpu(su->su_flags) & 644 si->sui_nblocks = le32_to_cpu(su->su_nblocks);
645 si->sui_flags = le32_to_cpu(su->su_flags) &
545 ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE); 646 ~(1UL << NILFS_SEGMENT_USAGE_ACTIVE);
546 if (nilfs_segment_is_active(nilfs, segnum + j)) 647 if (nilfs_segment_is_active(nilfs, segnum + j))
547 si[i + j].sui_flags |= 648 si->sui_flags |=
548 (1UL << NILFS_SEGMENT_USAGE_ACTIVE); 649 (1UL << NILFS_SEGMENT_USAGE_ACTIVE);
549 } 650 }
550 kunmap_atomic(kaddr, KM_USER0); 651 kunmap_atomic(kaddr, KM_USER0);
diff --git a/fs/nilfs2/sufile.h b/fs/nilfs2/sufile.h
index a2e2efd4ade1..a2c4d76c3366 100644
--- a/fs/nilfs2/sufile.h
+++ b/fs/nilfs2/sufile.h
@@ -43,43 +43,27 @@ void nilfs_sufile_put_segment_usage(struct inode *, __u64,
43 struct buffer_head *); 43 struct buffer_head *);
44int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *); 44int nilfs_sufile_get_stat(struct inode *, struct nilfs_sustat *);
45int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *); 45int nilfs_sufile_get_ncleansegs(struct inode *, unsigned long *);
46ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, struct nilfs_suinfo *, 46ssize_t nilfs_sufile_get_suinfo(struct inode *, __u64, void *, unsigned,
47 size_t); 47 size_t);
48 48
49int nilfs_sufile_updatev(struct inode *, __u64 *, size_t, int, size_t *,
50 void (*dofunc)(struct inode *, __u64,
51 struct buffer_head *,
52 struct buffer_head *));
49int nilfs_sufile_update(struct inode *, __u64, int, 53int nilfs_sufile_update(struct inode *, __u64, int,
50 void (*dofunc)(struct inode *, __u64, 54 void (*dofunc)(struct inode *, __u64,
51 struct buffer_head *, 55 struct buffer_head *,
52 struct buffer_head *)); 56 struct buffer_head *));
53void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
54 struct buffer_head *);
55void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *, 57void nilfs_sufile_do_scrap(struct inode *, __u64, struct buffer_head *,
56 struct buffer_head *); 58 struct buffer_head *);
57void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *, 59void nilfs_sufile_do_free(struct inode *, __u64, struct buffer_head *,
58 struct buffer_head *); 60 struct buffer_head *);
61void nilfs_sufile_do_cancel_free(struct inode *, __u64, struct buffer_head *,
62 struct buffer_head *);
59void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *, 63void nilfs_sufile_do_set_error(struct inode *, __u64, struct buffer_head *,
60 struct buffer_head *); 64 struct buffer_head *);
61 65
62/** 66/**
63 * nilfs_sufile_cancel_free -
64 * @sufile: inode of segment usage file
65 * @segnum: segment number
66 *
67 * Description:
68 *
69 * Return Value: On success, 0 is returned. On error, one of the following
70 * negative error codes is returned.
71 *
72 * %-EIO - I/O error.
73 *
74 * %-ENOMEM - Insufficient amount of memory available.
75 */
76static inline int nilfs_sufile_cancel_free(struct inode *sufile, __u64 segnum)
77{
78 return nilfs_sufile_update(sufile, segnum, 0,
79 nilfs_sufile_do_cancel_free);
80}
81
82/**
83 * nilfs_sufile_scrap - make a segment garbage 67 * nilfs_sufile_scrap - make a segment garbage
84 * @sufile: inode of segment usage file 68 * @sufile: inode of segment usage file
85 * @segnum: segment number to be freed 69 * @segnum: segment number to be freed
@@ -100,6 +84,38 @@ static inline int nilfs_sufile_free(struct inode *sufile, __u64 segnum)
100} 84}
101 85
102/** 86/**
87 * nilfs_sufile_freev - free segments
88 * @sufile: inode of segment usage file
89 * @segnumv: array of segment numbers
90 * @nsegs: size of @segnumv array
91 * @ndone: place to store the number of freed segments
92 */
93static inline int nilfs_sufile_freev(struct inode *sufile, __u64 *segnumv,
94 size_t nsegs, size_t *ndone)
95{
96 return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
97 nilfs_sufile_do_free);
98}
99
100/**
101 * nilfs_sufile_cancel_freev - reallocate freeing segments
102 * @sufile: inode of segment usage file
103 * @segnumv: array of segment numbers
104 * @nsegs: size of @segnumv array
105 * @ndone: place to store the number of cancelled segments
106 *
107 * Return Value: On success, 0 is returned. On error, a negative error codes
108 * is returned.
109 */
110static inline int nilfs_sufile_cancel_freev(struct inode *sufile,
111 __u64 *segnumv, size_t nsegs,
112 size_t *ndone)
113{
114 return nilfs_sufile_updatev(sufile, segnumv, nsegs, 0, ndone,
115 nilfs_sufile_do_cancel_free);
116}
117
118/**
103 * nilfs_sufile_set_error - mark a segment as erroneous 119 * nilfs_sufile_set_error - mark a segment as erroneous
104 * @sufile: inode of segment usage file 120 * @sufile: inode of segment usage file
105 * @segnum: segment number 121 * @segnum: segment number
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index 1777a3467bd2..ab785f85aa50 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -133,7 +133,7 @@ void nilfs_warning(struct super_block *sb, const char *function,
133 133
134static struct kmem_cache *nilfs_inode_cachep; 134static struct kmem_cache *nilfs_inode_cachep;
135 135
136struct inode *nilfs_alloc_inode(struct super_block *sb) 136struct inode *nilfs_alloc_inode_common(struct the_nilfs *nilfs)
137{ 137{
138 struct nilfs_inode_info *ii; 138 struct nilfs_inode_info *ii;
139 139
@@ -143,10 +143,15 @@ struct inode *nilfs_alloc_inode(struct super_block *sb)
143 ii->i_bh = NULL; 143 ii->i_bh = NULL;
144 ii->i_state = 0; 144 ii->i_state = 0;
145 ii->vfs_inode.i_version = 1; 145 ii->vfs_inode.i_version = 1;
146 nilfs_btnode_cache_init(&ii->i_btnode_cache); 146 nilfs_btnode_cache_init(&ii->i_btnode_cache, nilfs->ns_bdi);
147 return &ii->vfs_inode; 147 return &ii->vfs_inode;
148} 148}
149 149
150struct inode *nilfs_alloc_inode(struct super_block *sb)
151{
152 return nilfs_alloc_inode_common(NILFS_SB(sb)->s_nilfs);
153}
154
150void nilfs_destroy_inode(struct inode *inode) 155void nilfs_destroy_inode(struct inode *inode)
151{ 156{
152 kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode)); 157 kmem_cache_free(nilfs_inode_cachep, NILFS_I(inode));
diff --git a/fs/nilfs2/the_nilfs.c b/fs/nilfs2/the_nilfs.c
index e4e5c78bcc93..8b8889825716 100644
--- a/fs/nilfs2/the_nilfs.c
+++ b/fs/nilfs2/the_nilfs.c
@@ -32,7 +32,6 @@
32#include "cpfile.h" 32#include "cpfile.h"
33#include "sufile.h" 33#include "sufile.h"
34#include "dat.h" 34#include "dat.h"
35#include "seglist.h"
36#include "segbuf.h" 35#include "segbuf.h"
37 36
38 37
diff --git a/fs/ocfs2/alloc.c b/fs/ocfs2/alloc.c
index 678a067d9251..9edcde4974aa 100644
--- a/fs/ocfs2/alloc.c
+++ b/fs/ocfs2/alloc.c
@@ -475,6 +475,12 @@ struct ocfs2_path {
475#define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el) 475#define path_leaf_el(_path) ((_path)->p_node[(_path)->p_tree_depth].el)
476#define path_num_items(_path) ((_path)->p_tree_depth + 1) 476#define path_num_items(_path) ((_path)->p_tree_depth + 1)
477 477
478static int ocfs2_find_path(struct inode *inode, struct ocfs2_path *path,
479 u32 cpos);
480static void ocfs2_adjust_rightmost_records(struct inode *inode,
481 handle_t *handle,
482 struct ocfs2_path *path,
483 struct ocfs2_extent_rec *insert_rec);
478/* 484/*
479 * Reset the actual path elements so that we can re-use the structure 485 * Reset the actual path elements so that we can re-use the structure
480 * to build another path. Generally, this involves freeing the buffer 486 * to build another path. Generally, this involves freeing the buffer
@@ -1013,6 +1019,54 @@ static inline u32 ocfs2_sum_rightmost_rec(struct ocfs2_extent_list *el)
1013} 1019}
1014 1020
1015/* 1021/*
1022 * Change range of the branches in the right most path according to the leaf
1023 * extent block's rightmost record.
1024 */
1025static int ocfs2_adjust_rightmost_branch(handle_t *handle,
1026 struct inode *inode,
1027 struct ocfs2_extent_tree *et)
1028{
1029 int status;
1030 struct ocfs2_path *path = NULL;
1031 struct ocfs2_extent_list *el;
1032 struct ocfs2_extent_rec *rec;
1033
1034 path = ocfs2_new_path_from_et(et);
1035 if (!path) {
1036 status = -ENOMEM;
1037 return status;
1038 }
1039
1040 status = ocfs2_find_path(inode, path, UINT_MAX);
1041 if (status < 0) {
1042 mlog_errno(status);
1043 goto out;
1044 }
1045
1046 status = ocfs2_extend_trans(handle, path_num_items(path) +
1047 handle->h_buffer_credits);
1048 if (status < 0) {
1049 mlog_errno(status);
1050 goto out;
1051 }
1052
1053 status = ocfs2_journal_access_path(inode, handle, path);
1054 if (status < 0) {
1055 mlog_errno(status);
1056 goto out;
1057 }
1058
1059 el = path_leaf_el(path);
1060 rec = &el->l_recs[le32_to_cpu(el->l_next_free_rec) - 1];
1061
1062 ocfs2_adjust_rightmost_records(inode, handle, path, rec);
1063
1064out:
1065 ocfs2_free_path(path);
1066 return status;
1067}
1068
1069/*
1016 * Add an entire tree branch to our inode. eb_bh is the extent block 1070 * Add an entire tree branch to our inode. eb_bh is the extent block
1017 * to start at, if we don't want to start the branch at the dinode 1071 * to start at, if we don't want to start the branch at the dinode
1018 * structure. 1072 * structure.
@@ -1038,7 +1092,7 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
1038 struct ocfs2_extent_block *eb; 1092 struct ocfs2_extent_block *eb;
1039 struct ocfs2_extent_list *eb_el; 1093 struct ocfs2_extent_list *eb_el;
1040 struct ocfs2_extent_list *el; 1094 struct ocfs2_extent_list *el;
1041 u32 new_cpos; 1095 u32 new_cpos, root_end;
1042 1096
1043 mlog_entry_void(); 1097 mlog_entry_void();
1044 1098
@@ -1055,6 +1109,27 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
1055 1109
1056 new_blocks = le16_to_cpu(el->l_tree_depth); 1110 new_blocks = le16_to_cpu(el->l_tree_depth);
1057 1111
1112 eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
1113 new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
1114 root_end = ocfs2_sum_rightmost_rec(et->et_root_el);
1115
1116 /*
1117 * If there is a gap before the root end and the real end
1118 * of the righmost leaf block, we need to remove the gap
1119 * between new_cpos and root_end first so that the tree
1120 * is consistent after we add a new branch(it will start
1121 * from new_cpos).
1122 */
1123 if (root_end > new_cpos) {
1124 mlog(0, "adjust the cluster end from %u to %u\n",
1125 root_end, new_cpos);
1126 status = ocfs2_adjust_rightmost_branch(handle, inode, et);
1127 if (status) {
1128 mlog_errno(status);
1129 goto bail;
1130 }
1131 }
1132
1058 /* allocate the number of new eb blocks we need */ 1133 /* allocate the number of new eb blocks we need */
1059 new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *), 1134 new_eb_bhs = kcalloc(new_blocks, sizeof(struct buffer_head *),
1060 GFP_KERNEL); 1135 GFP_KERNEL);
@@ -1071,9 +1146,6 @@ static int ocfs2_add_branch(struct ocfs2_super *osb,
1071 goto bail; 1146 goto bail;
1072 } 1147 }
1073 1148
1074 eb = (struct ocfs2_extent_block *)(*last_eb_bh)->b_data;
1075 new_cpos = ocfs2_sum_rightmost_rec(&eb->h_list);
1076
1077 /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be 1149 /* Note: new_eb_bhs[new_blocks - 1] is the guy which will be
1078 * linked with the rest of the tree. 1150 * linked with the rest of the tree.
1079 * conversly, new_eb_bhs[0] is the new bottommost leaf. 1151 * conversly, new_eb_bhs[0] is the new bottommost leaf.
diff --git a/fs/ocfs2/blockcheck.c b/fs/ocfs2/blockcheck.c
index 2a947c44e594..a1163b8b417c 100644
--- a/fs/ocfs2/blockcheck.c
+++ b/fs/ocfs2/blockcheck.c
@@ -22,6 +22,9 @@
22#include <linux/crc32.h> 22#include <linux/crc32.h>
23#include <linux/buffer_head.h> 23#include <linux/buffer_head.h>
24#include <linux/bitops.h> 24#include <linux/bitops.h>
25#include <linux/debugfs.h>
26#include <linux/module.h>
27#include <linux/fs.h>
25#include <asm/byteorder.h> 28#include <asm/byteorder.h>
26 29
27#include <cluster/masklog.h> 30#include <cluster/masklog.h>
@@ -222,6 +225,155 @@ void ocfs2_hamming_fix_block(void *data, unsigned int blocksize,
222 ocfs2_hamming_fix(data, blocksize * 8, 0, fix); 225 ocfs2_hamming_fix(data, blocksize * 8, 0, fix);
223} 226}
224 227
228
229/*
230 * Debugfs handling.
231 */
232
233#ifdef CONFIG_DEBUG_FS
234
235static int blockcheck_u64_get(void *data, u64 *val)
236{
237 *val = *(u64 *)data;
238 return 0;
239}
240DEFINE_SIMPLE_ATTRIBUTE(blockcheck_fops, blockcheck_u64_get, NULL, "%llu\n");
241
242static struct dentry *blockcheck_debugfs_create(const char *name,
243 struct dentry *parent,
244 u64 *value)
245{
246 return debugfs_create_file(name, S_IFREG | S_IRUSR, parent, value,
247 &blockcheck_fops);
248}
249
250static void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
251{
252 if (stats) {
253 debugfs_remove(stats->b_debug_check);
254 stats->b_debug_check = NULL;
255 debugfs_remove(stats->b_debug_failure);
256 stats->b_debug_failure = NULL;
257 debugfs_remove(stats->b_debug_recover);
258 stats->b_debug_recover = NULL;
259 debugfs_remove(stats->b_debug_dir);
260 stats->b_debug_dir = NULL;
261 }
262}
263
264static int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
265 struct dentry *parent)
266{
267 int rc = -EINVAL;
268
269 if (!stats)
270 goto out;
271
272 stats->b_debug_dir = debugfs_create_dir("blockcheck", parent);
273 if (!stats->b_debug_dir)
274 goto out;
275
276 stats->b_debug_check =
277 blockcheck_debugfs_create("blocks_checked",
278 stats->b_debug_dir,
279 &stats->b_check_count);
280
281 stats->b_debug_failure =
282 blockcheck_debugfs_create("checksums_failed",
283 stats->b_debug_dir,
284 &stats->b_failure_count);
285
286 stats->b_debug_recover =
287 blockcheck_debugfs_create("ecc_recoveries",
288 stats->b_debug_dir,
289 &stats->b_recover_count);
290 if (stats->b_debug_check && stats->b_debug_failure &&
291 stats->b_debug_recover)
292 rc = 0;
293
294out:
295 if (rc)
296 ocfs2_blockcheck_debug_remove(stats);
297 return rc;
298}
299#else
300static inline int ocfs2_blockcheck_debug_install(struct ocfs2_blockcheck_stats *stats,
301 struct dentry *parent)
302{
303 return 0;
304}
305
306static inline void ocfs2_blockcheck_debug_remove(struct ocfs2_blockcheck_stats *stats)
307{
308}
309#endif /* CONFIG_DEBUG_FS */
310
311/* Always-called wrappers for starting and stopping the debugfs files */
312int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
313 struct dentry *parent)
314{
315 return ocfs2_blockcheck_debug_install(stats, parent);
316}
317
318void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats)
319{
320 ocfs2_blockcheck_debug_remove(stats);
321}
322
323static void ocfs2_blockcheck_inc_check(struct ocfs2_blockcheck_stats *stats)
324{
325 u64 new_count;
326
327 if (!stats)
328 return;
329
330 spin_lock(&stats->b_lock);
331 stats->b_check_count++;
332 new_count = stats->b_check_count;
333 spin_unlock(&stats->b_lock);
334
335 if (!new_count)
336 mlog(ML_NOTICE, "Block check count has wrapped\n");
337}
338
339static void ocfs2_blockcheck_inc_failure(struct ocfs2_blockcheck_stats *stats)
340{
341 u64 new_count;
342
343 if (!stats)
344 return;
345
346 spin_lock(&stats->b_lock);
347 stats->b_failure_count++;
348 new_count = stats->b_failure_count;
349 spin_unlock(&stats->b_lock);
350
351 if (!new_count)
352 mlog(ML_NOTICE, "Checksum failure count has wrapped\n");
353}
354
355static void ocfs2_blockcheck_inc_recover(struct ocfs2_blockcheck_stats *stats)
356{
357 u64 new_count;
358
359 if (!stats)
360 return;
361
362 spin_lock(&stats->b_lock);
363 stats->b_recover_count++;
364 new_count = stats->b_recover_count;
365 spin_unlock(&stats->b_lock);
366
367 if (!new_count)
368 mlog(ML_NOTICE, "ECC recovery count has wrapped\n");
369}
370
371
372
373/*
374 * These are the low-level APIs for using the ocfs2_block_check structure.
375 */
376
225/* 377/*
226 * This function generates check information for a block. 378 * This function generates check information for a block.
227 * data is the block to be checked. bc is a pointer to the 379 * data is the block to be checked. bc is a pointer to the
@@ -266,12 +418,15 @@ void ocfs2_block_check_compute(void *data, size_t blocksize,
266 * Again, the data passed in should be the on-disk endian. 418 * Again, the data passed in should be the on-disk endian.
267 */ 419 */
268int ocfs2_block_check_validate(void *data, size_t blocksize, 420int ocfs2_block_check_validate(void *data, size_t blocksize,
269 struct ocfs2_block_check *bc) 421 struct ocfs2_block_check *bc,
422 struct ocfs2_blockcheck_stats *stats)
270{ 423{
271 int rc = 0; 424 int rc = 0;
272 struct ocfs2_block_check check; 425 struct ocfs2_block_check check;
273 u32 crc, ecc; 426 u32 crc, ecc;
274 427
428 ocfs2_blockcheck_inc_check(stats);
429
275 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); 430 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
276 check.bc_ecc = le16_to_cpu(bc->bc_ecc); 431 check.bc_ecc = le16_to_cpu(bc->bc_ecc);
277 432
@@ -282,6 +437,7 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
282 if (crc == check.bc_crc32e) 437 if (crc == check.bc_crc32e)
283 goto out; 438 goto out;
284 439
440 ocfs2_blockcheck_inc_failure(stats);
285 mlog(ML_ERROR, 441 mlog(ML_ERROR,
286 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", 442 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
287 (unsigned int)check.bc_crc32e, (unsigned int)crc); 443 (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -292,8 +448,10 @@ int ocfs2_block_check_validate(void *data, size_t blocksize,
292 448
293 /* And check the crc32 again */ 449 /* And check the crc32 again */
294 crc = crc32_le(~0, data, blocksize); 450 crc = crc32_le(~0, data, blocksize);
295 if (crc == check.bc_crc32e) 451 if (crc == check.bc_crc32e) {
452 ocfs2_blockcheck_inc_recover(stats);
296 goto out; 453 goto out;
454 }
297 455
298 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", 456 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
299 (unsigned int)check.bc_crc32e, (unsigned int)crc); 457 (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -366,7 +524,8 @@ void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
366 * Again, the data passed in should be the on-disk endian. 524 * Again, the data passed in should be the on-disk endian.
367 */ 525 */
368int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, 526int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
369 struct ocfs2_block_check *bc) 527 struct ocfs2_block_check *bc,
528 struct ocfs2_blockcheck_stats *stats)
370{ 529{
371 int i, rc = 0; 530 int i, rc = 0;
372 struct ocfs2_block_check check; 531 struct ocfs2_block_check check;
@@ -377,6 +536,8 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
377 if (!nr) 536 if (!nr)
378 return 0; 537 return 0;
379 538
539 ocfs2_blockcheck_inc_check(stats);
540
380 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e); 541 check.bc_crc32e = le32_to_cpu(bc->bc_crc32e);
381 check.bc_ecc = le16_to_cpu(bc->bc_ecc); 542 check.bc_ecc = le16_to_cpu(bc->bc_ecc);
382 543
@@ -388,6 +549,7 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
388 if (crc == check.bc_crc32e) 549 if (crc == check.bc_crc32e)
389 goto out; 550 goto out;
390 551
552 ocfs2_blockcheck_inc_failure(stats);
391 mlog(ML_ERROR, 553 mlog(ML_ERROR,
392 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n", 554 "CRC32 failed: stored: %u, computed %u. Applying ECC.\n",
393 (unsigned int)check.bc_crc32e, (unsigned int)crc); 555 (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -416,8 +578,10 @@ int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
416 /* And check the crc32 again */ 578 /* And check the crc32 again */
417 for (i = 0, crc = ~0; i < nr; i++) 579 for (i = 0, crc = ~0; i < nr; i++)
418 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size); 580 crc = crc32_le(crc, bhs[i]->b_data, bhs[i]->b_size);
419 if (crc == check.bc_crc32e) 581 if (crc == check.bc_crc32e) {
582 ocfs2_blockcheck_inc_recover(stats);
420 goto out; 583 goto out;
584 }
421 585
422 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n", 586 mlog(ML_ERROR, "Fixed CRC32 failed: stored: %u, computed %u\n",
423 (unsigned int)check.bc_crc32e, (unsigned int)crc); 587 (unsigned int)check.bc_crc32e, (unsigned int)crc);
@@ -448,9 +612,11 @@ int ocfs2_validate_meta_ecc(struct super_block *sb, void *data,
448 struct ocfs2_block_check *bc) 612 struct ocfs2_block_check *bc)
449{ 613{
450 int rc = 0; 614 int rc = 0;
615 struct ocfs2_super *osb = OCFS2_SB(sb);
451 616
452 if (ocfs2_meta_ecc(OCFS2_SB(sb))) 617 if (ocfs2_meta_ecc(osb))
453 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc); 618 rc = ocfs2_block_check_validate(data, sb->s_blocksize, bc,
619 &osb->osb_ecc_stats);
454 620
455 return rc; 621 return rc;
456} 622}
@@ -468,9 +634,11 @@ int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
468 struct ocfs2_block_check *bc) 634 struct ocfs2_block_check *bc)
469{ 635{
470 int rc = 0; 636 int rc = 0;
637 struct ocfs2_super *osb = OCFS2_SB(sb);
471 638
472 if (ocfs2_meta_ecc(OCFS2_SB(sb))) 639 if (ocfs2_meta_ecc(osb))
473 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc); 640 rc = ocfs2_block_check_validate_bhs(bhs, nr, bc,
641 &osb->osb_ecc_stats);
474 642
475 return rc; 643 return rc;
476} 644}
diff --git a/fs/ocfs2/blockcheck.h b/fs/ocfs2/blockcheck.h
index 70ec3feda32f..d4b69febf70a 100644
--- a/fs/ocfs2/blockcheck.h
+++ b/fs/ocfs2/blockcheck.h
@@ -21,6 +21,24 @@
21#define OCFS2_BLOCKCHECK_H 21#define OCFS2_BLOCKCHECK_H
22 22
23 23
24/* Count errors and error correction from blockcheck.c */
25struct ocfs2_blockcheck_stats {
26 spinlock_t b_lock;
27 u64 b_check_count; /* Number of blocks we've checked */
28 u64 b_failure_count; /* Number of failed checksums */
29 u64 b_recover_count; /* Number of blocks fixed by ecc */
30
31 /*
32 * debugfs entries, used if this is passed to
33 * ocfs2_blockcheck_stats_debugfs_install()
34 */
35 struct dentry *b_debug_dir; /* Parent of the debugfs files */
36 struct dentry *b_debug_check; /* Exposes b_check_count */
37 struct dentry *b_debug_failure; /* Exposes b_failure_count */
38 struct dentry *b_debug_recover; /* Exposes b_recover_count */
39};
40
41
24/* High level block API */ 42/* High level block API */
25void ocfs2_compute_meta_ecc(struct super_block *sb, void *data, 43void ocfs2_compute_meta_ecc(struct super_block *sb, void *data,
26 struct ocfs2_block_check *bc); 44 struct ocfs2_block_check *bc);
@@ -37,11 +55,18 @@ int ocfs2_validate_meta_ecc_bhs(struct super_block *sb,
37void ocfs2_block_check_compute(void *data, size_t blocksize, 55void ocfs2_block_check_compute(void *data, size_t blocksize,
38 struct ocfs2_block_check *bc); 56 struct ocfs2_block_check *bc);
39int ocfs2_block_check_validate(void *data, size_t blocksize, 57int ocfs2_block_check_validate(void *data, size_t blocksize,
40 struct ocfs2_block_check *bc); 58 struct ocfs2_block_check *bc,
59 struct ocfs2_blockcheck_stats *stats);
41void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr, 60void ocfs2_block_check_compute_bhs(struct buffer_head **bhs, int nr,
42 struct ocfs2_block_check *bc); 61 struct ocfs2_block_check *bc);
43int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr, 62int ocfs2_block_check_validate_bhs(struct buffer_head **bhs, int nr,
44 struct ocfs2_block_check *bc); 63 struct ocfs2_block_check *bc,
64 struct ocfs2_blockcheck_stats *stats);
65
66/* Debug Initialization */
67int ocfs2_blockcheck_stats_debugfs_install(struct ocfs2_blockcheck_stats *stats,
68 struct dentry *parent);
69void ocfs2_blockcheck_stats_debugfs_remove(struct ocfs2_blockcheck_stats *stats);
45 70
46/* 71/*
47 * Hamming code functions 72 * Hamming code functions
diff --git a/fs/ocfs2/cluster/masklog.h b/fs/ocfs2/cluster/masklog.h
index 7e72a81bc2d4..696c32e50716 100644
--- a/fs/ocfs2/cluster/masklog.h
+++ b/fs/ocfs2/cluster/masklog.h
@@ -48,34 +48,33 @@
48 * only emit the appropriage printk() when the caller passes in a constant 48 * only emit the appropriage printk() when the caller passes in a constant
49 * mask, as is almost always the case. 49 * mask, as is almost always the case.
50 * 50 *
51 * All this bitmask nonsense is hidden from the /proc interface so that Joel 51 * All this bitmask nonsense is managed from the files under
52 * doesn't have an aneurism. Reading the file gives a straight forward 52 * /sys/fs/o2cb/logmask/. Reading the files gives a straightforward
53 * indication of which bits are on or off: 53 * indication of which bits are allowed (allow) or denied (off/deny).
54 * ENTRY off 54 * ENTRY deny
55 * EXIT off 55 * EXIT deny
56 * TCP off 56 * TCP off
57 * MSG off 57 * MSG off
58 * SOCKET off 58 * SOCKET off
59 * ERROR off 59 * ERROR allow
60 * NOTICE on 60 * NOTICE allow
61 * 61 *
62 * Writing changes the state of a given bit and requires a strictly formatted 62 * Writing changes the state of a given bit and requires a strictly formatted
63 * single write() call: 63 * single write() call:
64 * 64 *
65 * write(fd, "ENTRY on", 8); 65 * write(fd, "allow", 5);
66 * 66 *
67 * would turn the entry bit on. "1" is also accepted in the place of "on", and 67 * Echoing allow/deny/off string into the logmask files can flip the bits
68 * "off" and "0" behave as expected. 68 * on or off as expected; here is the bash script for example:
69 * 69 *
70 * Some trivial shell can flip all the bits on or off: 70 * log_mask="/sys/fs/o2cb/log_mask"
71 * for node in ENTRY EXIT TCP MSG SOCKET ERROR NOTICE; do
72 * echo allow >"$log_mask"/"$node"
73 * done
71 * 74 *
72 * log_mask="/proc/fs/ocfs2_nodemanager/log_mask" 75 * The debugfs.ocfs2 tool can also flip the bits with the -l option:
73 * cat $log_mask | ( 76 *
74 * while read bit status; do 77 * debugfs.ocfs2 -l TCP allow
75 * # $1 is "on" or "off", say
76 * echo "$bit $1" > $log_mask
77 * done
78 * )
79 */ 78 */
80 79
81/* for task_struct */ 80/* for task_struct */
diff --git a/fs/ocfs2/cluster/tcp.c b/fs/ocfs2/cluster/tcp.c
index 9fbe849f6344..334f231a422c 100644
--- a/fs/ocfs2/cluster/tcp.c
+++ b/fs/ocfs2/cluster/tcp.c
@@ -974,7 +974,7 @@ static int o2net_tx_can_proceed(struct o2net_node *nn,
974int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec, 974int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
975 size_t caller_veclen, u8 target_node, int *status) 975 size_t caller_veclen, u8 target_node, int *status)
976{ 976{
977 int ret, error = 0; 977 int ret;
978 struct o2net_msg *msg = NULL; 978 struct o2net_msg *msg = NULL;
979 size_t veclen, caller_bytes = 0; 979 size_t veclen, caller_bytes = 0;
980 struct kvec *vec = NULL; 980 struct kvec *vec = NULL;
@@ -1015,10 +1015,7 @@ int o2net_send_message_vec(u32 msg_type, u32 key, struct kvec *caller_vec,
1015 1015
1016 o2net_set_nst_sock_time(&nst); 1016 o2net_set_nst_sock_time(&nst);
1017 1017
1018 ret = wait_event_interruptible(nn->nn_sc_wq, 1018 wait_event(nn->nn_sc_wq, o2net_tx_can_proceed(nn, &sc, &ret));
1019 o2net_tx_can_proceed(nn, &sc, &error));
1020 if (!ret && error)
1021 ret = error;
1022 if (ret) 1019 if (ret)
1023 goto out; 1020 goto out;
1024 1021
diff --git a/fs/ocfs2/dir.c b/fs/ocfs2/dir.c
index c5752305627c..b358f3bf896d 100644
--- a/fs/ocfs2/dir.c
+++ b/fs/ocfs2/dir.c
@@ -2900,6 +2900,8 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2900 alloc = ocfs2_clusters_for_bytes(sb, bytes); 2900 alloc = ocfs2_clusters_for_bytes(sb, bytes);
2901 dx_alloc = 0; 2901 dx_alloc = 0;
2902 2902
2903 down_write(&oi->ip_alloc_sem);
2904
2903 if (ocfs2_supports_indexed_dirs(osb)) { 2905 if (ocfs2_supports_indexed_dirs(osb)) {
2904 credits += ocfs2_add_dir_index_credits(sb); 2906 credits += ocfs2_add_dir_index_credits(sb);
2905 2907
@@ -2940,8 +2942,6 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2940 goto out; 2942 goto out;
2941 } 2943 }
2942 2944
2943 down_write(&oi->ip_alloc_sem);
2944
2945 /* 2945 /*
2946 * Prepare for worst case allocation scenario of two separate 2946 * Prepare for worst case allocation scenario of two separate
2947 * extents in the unindexed tree. 2947 * extents in the unindexed tree.
@@ -2953,7 +2953,7 @@ static int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
2953 if (IS_ERR(handle)) { 2953 if (IS_ERR(handle)) {
2954 ret = PTR_ERR(handle); 2954 ret = PTR_ERR(handle);
2955 mlog_errno(ret); 2955 mlog_errno(ret);
2956 goto out_sem; 2956 goto out;
2957 } 2957 }
2958 2958
2959 if (vfs_dq_alloc_space_nodirty(dir, 2959 if (vfs_dq_alloc_space_nodirty(dir,
@@ -3172,10 +3172,8 @@ out_commit:
3172 3172
3173 ocfs2_commit_trans(osb, handle); 3173 ocfs2_commit_trans(osb, handle);
3174 3174
3175out_sem:
3176 up_write(&oi->ip_alloc_sem);
3177
3178out: 3175out:
3176 up_write(&oi->ip_alloc_sem);
3179 if (data_ac) 3177 if (data_ac)
3180 ocfs2_free_alloc_context(data_ac); 3178 ocfs2_free_alloc_context(data_ac);
3181 if (meta_ac) 3179 if (meta_ac)
@@ -3322,11 +3320,15 @@ static int ocfs2_extend_dir(struct ocfs2_super *osb,
3322 brelse(new_bh); 3320 brelse(new_bh);
3323 new_bh = NULL; 3321 new_bh = NULL;
3324 3322
3323 down_write(&OCFS2_I(dir)->ip_alloc_sem);
3324 drop_alloc_sem = 1;
3325 dir_i_size = i_size_read(dir); 3325 dir_i_size = i_size_read(dir);
3326 credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS; 3326 credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
3327 goto do_extend; 3327 goto do_extend;
3328 } 3328 }
3329 3329
3330 down_write(&OCFS2_I(dir)->ip_alloc_sem);
3331 drop_alloc_sem = 1;
3330 dir_i_size = i_size_read(dir); 3332 dir_i_size = i_size_read(dir);
3331 mlog(0, "extending dir %llu (i_size = %lld)\n", 3333 mlog(0, "extending dir %llu (i_size = %lld)\n",
3332 (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size); 3334 (unsigned long long)OCFS2_I(dir)->ip_blkno, dir_i_size);
@@ -3370,9 +3372,6 @@ do_extend:
3370 credits++; /* For attaching the new dirent block to the 3372 credits++; /* For attaching the new dirent block to the
3371 * dx_root */ 3373 * dx_root */
3372 3374
3373 down_write(&OCFS2_I(dir)->ip_alloc_sem);
3374 drop_alloc_sem = 1;
3375
3376 handle = ocfs2_start_trans(osb, credits); 3375 handle = ocfs2_start_trans(osb, credits);
3377 if (IS_ERR(handle)) { 3376 if (IS_ERR(handle)) {
3378 status = PTR_ERR(handle); 3377 status = PTR_ERR(handle);
@@ -3435,10 +3434,10 @@ bail_bh:
3435 *new_de_bh = new_bh; 3434 *new_de_bh = new_bh;
3436 get_bh(*new_de_bh); 3435 get_bh(*new_de_bh);
3437bail: 3436bail:
3438 if (drop_alloc_sem)
3439 up_write(&OCFS2_I(dir)->ip_alloc_sem);
3440 if (handle) 3437 if (handle)
3441 ocfs2_commit_trans(osb, handle); 3438 ocfs2_commit_trans(osb, handle);
3439 if (drop_alloc_sem)
3440 up_write(&OCFS2_I(dir)->ip_alloc_sem);
3442 3441
3443 if (data_ac) 3442 if (data_ac)
3444 ocfs2_free_alloc_context(data_ac); 3443 ocfs2_free_alloc_context(data_ac);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index e15fc7d50827..6cdeaa76f27f 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -248,6 +248,10 @@ static struct ocfs2_lock_res_ops ocfs2_nfs_sync_lops = {
248 .flags = 0, 248 .flags = 0,
249}; 249};
250 250
251static struct ocfs2_lock_res_ops ocfs2_orphan_scan_lops = {
252 .flags = LOCK_TYPE_REQUIRES_REFRESH|LOCK_TYPE_USES_LVB,
253};
254
251static struct ocfs2_lock_res_ops ocfs2_dentry_lops = { 255static struct ocfs2_lock_res_ops ocfs2_dentry_lops = {
252 .get_osb = ocfs2_get_dentry_osb, 256 .get_osb = ocfs2_get_dentry_osb,
253 .post_unlock = ocfs2_dentry_post_unlock, 257 .post_unlock = ocfs2_dentry_post_unlock,
@@ -637,6 +641,19 @@ static void ocfs2_nfs_sync_lock_res_init(struct ocfs2_lock_res *res,
637 &ocfs2_nfs_sync_lops, osb); 641 &ocfs2_nfs_sync_lops, osb);
638} 642}
639 643
644static void ocfs2_orphan_scan_lock_res_init(struct ocfs2_lock_res *res,
645 struct ocfs2_super *osb)
646{
647 struct ocfs2_orphan_scan_lvb *lvb;
648
649 ocfs2_lock_res_init_once(res);
650 ocfs2_build_lock_name(OCFS2_LOCK_TYPE_ORPHAN_SCAN, 0, 0, res->l_name);
651 ocfs2_lock_res_init_common(osb, res, OCFS2_LOCK_TYPE_ORPHAN_SCAN,
652 &ocfs2_orphan_scan_lops, osb);
653 lvb = ocfs2_dlm_lvb(&res->l_lksb);
654 lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
655}
656
640void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres, 657void ocfs2_file_lock_res_init(struct ocfs2_lock_res *lockres,
641 struct ocfs2_file_private *fp) 658 struct ocfs2_file_private *fp)
642{ 659{
@@ -2352,6 +2369,37 @@ void ocfs2_inode_unlock(struct inode *inode,
2352 mlog_exit_void(); 2369 mlog_exit_void();
2353} 2370}
2354 2371
2372int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex)
2373{
2374 struct ocfs2_lock_res *lockres;
2375 struct ocfs2_orphan_scan_lvb *lvb;
2376 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
2377 int status = 0;
2378
2379 lockres = &osb->osb_orphan_scan.os_lockres;
2380 status = ocfs2_cluster_lock(osb, lockres, level, 0, 0);
2381 if (status < 0)
2382 return status;
2383
2384 lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
2385 if (lvb->lvb_version == OCFS2_ORPHAN_LVB_VERSION)
2386 *seqno = be32_to_cpu(lvb->lvb_os_seqno);
2387 return status;
2388}
2389
2390void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex)
2391{
2392 struct ocfs2_lock_res *lockres;
2393 struct ocfs2_orphan_scan_lvb *lvb;
2394 int level = ex ? DLM_LOCK_EX : DLM_LOCK_PR;
2395
2396 lockres = &osb->osb_orphan_scan.os_lockres;
2397 lvb = ocfs2_dlm_lvb(&lockres->l_lksb);
2398 lvb->lvb_version = OCFS2_ORPHAN_LVB_VERSION;
2399 lvb->lvb_os_seqno = cpu_to_be32(seqno);
2400 ocfs2_cluster_unlock(osb, lockres, level);
2401}
2402
2355int ocfs2_super_lock(struct ocfs2_super *osb, 2403int ocfs2_super_lock(struct ocfs2_super *osb,
2356 int ex) 2404 int ex)
2357{ 2405{
@@ -2842,6 +2890,7 @@ local:
2842 ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb); 2890 ocfs2_super_lock_res_init(&osb->osb_super_lockres, osb);
2843 ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb); 2891 ocfs2_rename_lock_res_init(&osb->osb_rename_lockres, osb);
2844 ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb); 2892 ocfs2_nfs_sync_lock_res_init(&osb->osb_nfs_sync_lockres, osb);
2893 ocfs2_orphan_scan_lock_res_init(&osb->osb_orphan_scan.os_lockres, osb);
2845 2894
2846 osb->cconn = conn; 2895 osb->cconn = conn;
2847 2896
@@ -2878,6 +2927,7 @@ void ocfs2_dlm_shutdown(struct ocfs2_super *osb,
2878 ocfs2_lock_res_free(&osb->osb_super_lockres); 2927 ocfs2_lock_res_free(&osb->osb_super_lockres);
2879 ocfs2_lock_res_free(&osb->osb_rename_lockres); 2928 ocfs2_lock_res_free(&osb->osb_rename_lockres);
2880 ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres); 2929 ocfs2_lock_res_free(&osb->osb_nfs_sync_lockres);
2930 ocfs2_lock_res_free(&osb->osb_orphan_scan.os_lockres);
2881 2931
2882 ocfs2_cluster_disconnect(osb->cconn, hangup_pending); 2932 ocfs2_cluster_disconnect(osb->cconn, hangup_pending);
2883 osb->cconn = NULL; 2933 osb->cconn = NULL;
@@ -3061,6 +3111,7 @@ static void ocfs2_drop_osb_locks(struct ocfs2_super *osb)
3061 ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres); 3111 ocfs2_simple_drop_lockres(osb, &osb->osb_super_lockres);
3062 ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres); 3112 ocfs2_simple_drop_lockres(osb, &osb->osb_rename_lockres);
3063 ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres); 3113 ocfs2_simple_drop_lockres(osb, &osb->osb_nfs_sync_lockres);
3114 ocfs2_simple_drop_lockres(osb, &osb->osb_orphan_scan.os_lockres);
3064} 3115}
3065 3116
3066int ocfs2_drop_inode_locks(struct inode *inode) 3117int ocfs2_drop_inode_locks(struct inode *inode)
diff --git a/fs/ocfs2/dlmglue.h b/fs/ocfs2/dlmglue.h
index e1fd5721cd7f..31b90d7b8f51 100644
--- a/fs/ocfs2/dlmglue.h
+++ b/fs/ocfs2/dlmglue.h
@@ -62,6 +62,14 @@ struct ocfs2_qinfo_lvb {
62 __be32 lvb_free_entry; 62 __be32 lvb_free_entry;
63}; 63};
64 64
65#define OCFS2_ORPHAN_LVB_VERSION 1
66
67struct ocfs2_orphan_scan_lvb {
68 __u8 lvb_version;
69 __u8 lvb_reserved[3];
70 __be32 lvb_os_seqno;
71};
72
65/* ocfs2_inode_lock_full() 'arg_flags' flags */ 73/* ocfs2_inode_lock_full() 'arg_flags' flags */
66/* don't wait on recovery. */ 74/* don't wait on recovery. */
67#define OCFS2_META_LOCK_RECOVERY (0x01) 75#define OCFS2_META_LOCK_RECOVERY (0x01)
@@ -113,6 +121,9 @@ int ocfs2_super_lock(struct ocfs2_super *osb,
113 int ex); 121 int ex);
114void ocfs2_super_unlock(struct ocfs2_super *osb, 122void ocfs2_super_unlock(struct ocfs2_super *osb,
115 int ex); 123 int ex);
124int ocfs2_orphan_scan_lock(struct ocfs2_super *osb, u32 *seqno, int ex);
125void ocfs2_orphan_scan_unlock(struct ocfs2_super *osb, u32 seqno, int ex);
126
116int ocfs2_rename_lock(struct ocfs2_super *osb); 127int ocfs2_rename_lock(struct ocfs2_super *osb);
117void ocfs2_rename_unlock(struct ocfs2_super *osb); 128void ocfs2_rename_unlock(struct ocfs2_super *osb);
118int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex); 129int ocfs2_nfs_sync_lock(struct ocfs2_super *osb, int ex);
diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c
index c2a87c885b73..07267e0da909 100644
--- a/fs/ocfs2/file.c
+++ b/fs/ocfs2/file.c
@@ -187,6 +187,9 @@ static int ocfs2_sync_file(struct file *file,
187 if (err) 187 if (err)
188 goto bail; 188 goto bail;
189 189
190 if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
191 goto bail;
192
190 journal = osb->journal->j_journal; 193 journal = osb->journal->j_journal;
191 err = jbd2_journal_force_commit(journal); 194 err = jbd2_journal_force_commit(journal);
192 195
@@ -894,9 +897,9 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
894 struct ocfs2_super *osb = OCFS2_SB(sb); 897 struct ocfs2_super *osb = OCFS2_SB(sb);
895 struct buffer_head *bh = NULL; 898 struct buffer_head *bh = NULL;
896 handle_t *handle = NULL; 899 handle_t *handle = NULL;
897 int locked[MAXQUOTAS] = {0, 0}; 900 int qtype;
898 int credits, qtype; 901 struct dquot *transfer_from[MAXQUOTAS] = { };
899 struct ocfs2_mem_dqinfo *oinfo; 902 struct dquot *transfer_to[MAXQUOTAS] = { };
900 903
901 mlog_entry("(0x%p, '%.*s')\n", dentry, 904 mlog_entry("(0x%p, '%.*s')\n", dentry,
902 dentry->d_name.len, dentry->d_name.name); 905 dentry->d_name.len, dentry->d_name.name);
@@ -969,30 +972,37 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
969 972
970 if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) || 973 if ((attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid) ||
971 (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) { 974 (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid)) {
972 credits = OCFS2_INODE_UPDATE_CREDITS; 975 /*
976 * Gather pointers to quota structures so that allocation /
977 * freeing of quota structures happens here and not inside
978 * vfs_dq_transfer() where we have problems with lock ordering
979 */
973 if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid 980 if (attr->ia_valid & ATTR_UID && attr->ia_uid != inode->i_uid
974 && OCFS2_HAS_RO_COMPAT_FEATURE(sb, 981 && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
975 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) { 982 OCFS2_FEATURE_RO_COMPAT_USRQUOTA)) {
976 oinfo = sb_dqinfo(sb, USRQUOTA)->dqi_priv; 983 transfer_to[USRQUOTA] = dqget(sb, attr->ia_uid,
977 status = ocfs2_lock_global_qf(oinfo, 1); 984 USRQUOTA);
978 if (status < 0) 985 transfer_from[USRQUOTA] = dqget(sb, inode->i_uid,
986 USRQUOTA);
987 if (!transfer_to[USRQUOTA] || !transfer_from[USRQUOTA]) {
988 status = -ESRCH;
979 goto bail_unlock; 989 goto bail_unlock;
980 credits += ocfs2_calc_qinit_credits(sb, USRQUOTA) + 990 }
981 ocfs2_calc_qdel_credits(sb, USRQUOTA);
982 locked[USRQUOTA] = 1;
983 } 991 }
984 if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid 992 if (attr->ia_valid & ATTR_GID && attr->ia_gid != inode->i_gid
985 && OCFS2_HAS_RO_COMPAT_FEATURE(sb, 993 && OCFS2_HAS_RO_COMPAT_FEATURE(sb,
986 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) { 994 OCFS2_FEATURE_RO_COMPAT_GRPQUOTA)) {
987 oinfo = sb_dqinfo(sb, GRPQUOTA)->dqi_priv; 995 transfer_to[GRPQUOTA] = dqget(sb, attr->ia_gid,
988 status = ocfs2_lock_global_qf(oinfo, 1); 996 GRPQUOTA);
989 if (status < 0) 997 transfer_from[GRPQUOTA] = dqget(sb, inode->i_gid,
998 GRPQUOTA);
999 if (!transfer_to[GRPQUOTA] || !transfer_from[GRPQUOTA]) {
1000 status = -ESRCH;
990 goto bail_unlock; 1001 goto bail_unlock;
991 credits += ocfs2_calc_qinit_credits(sb, GRPQUOTA) + 1002 }
992 ocfs2_calc_qdel_credits(sb, GRPQUOTA);
993 locked[GRPQUOTA] = 1;
994 } 1003 }
995 handle = ocfs2_start_trans(osb, credits); 1004 handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS +
1005 2 * ocfs2_quota_trans_credits(sb));
996 if (IS_ERR(handle)) { 1006 if (IS_ERR(handle)) {
997 status = PTR_ERR(handle); 1007 status = PTR_ERR(handle);
998 mlog_errno(status); 1008 mlog_errno(status);
@@ -1030,12 +1040,6 @@ int ocfs2_setattr(struct dentry *dentry, struct iattr *attr)
1030bail_commit: 1040bail_commit:
1031 ocfs2_commit_trans(osb, handle); 1041 ocfs2_commit_trans(osb, handle);
1032bail_unlock: 1042bail_unlock:
1033 for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
1034 if (!locked[qtype])
1035 continue;
1036 oinfo = sb_dqinfo(sb, qtype)->dqi_priv;
1037 ocfs2_unlock_global_qf(oinfo, 1);
1038 }
1039 ocfs2_inode_unlock(inode, 1); 1043 ocfs2_inode_unlock(inode, 1);
1040bail_unlock_rw: 1044bail_unlock_rw:
1041 if (size_change) 1045 if (size_change)
@@ -1043,6 +1047,12 @@ bail_unlock_rw:
1043bail: 1047bail:
1044 brelse(bh); 1048 brelse(bh);
1045 1049
1050 /* Release quota pointers in case we acquired them */
1051 for (qtype = 0; qtype < MAXQUOTAS; qtype++) {
1052 dqput(transfer_to[qtype]);
1053 dqput(transfer_from[qtype]);
1054 }
1055
1046 if (!status && attr->ia_valid & ATTR_MODE) { 1056 if (!status && attr->ia_valid & ATTR_MODE) {
1047 status = ocfs2_acl_chmod(inode); 1057 status = ocfs2_acl_chmod(inode);
1048 if (status < 0) 1058 if (status < 0)
diff --git a/fs/ocfs2/journal.c b/fs/ocfs2/journal.c
index a20a0f1e37fd..4a3b9e6b31ad 100644
--- a/fs/ocfs2/journal.c
+++ b/fs/ocfs2/journal.c
@@ -28,6 +28,8 @@
28#include <linux/slab.h> 28#include <linux/slab.h>
29#include <linux/highmem.h> 29#include <linux/highmem.h>
30#include <linux/kthread.h> 30#include <linux/kthread.h>
31#include <linux/time.h>
32#include <linux/random.h>
31 33
32#define MLOG_MASK_PREFIX ML_JOURNAL 34#define MLOG_MASK_PREFIX ML_JOURNAL
33#include <cluster/masklog.h> 35#include <cluster/masklog.h>
@@ -52,6 +54,8 @@
52 54
53DEFINE_SPINLOCK(trans_inc_lock); 55DEFINE_SPINLOCK(trans_inc_lock);
54 56
57#define ORPHAN_SCAN_SCHEDULE_TIMEOUT 300000
58
55static int ocfs2_force_read_journal(struct inode *inode); 59static int ocfs2_force_read_journal(struct inode *inode);
56static int ocfs2_recover_node(struct ocfs2_super *osb, 60static int ocfs2_recover_node(struct ocfs2_super *osb,
57 int node_num, int slot_num); 61 int node_num, int slot_num);
@@ -1841,6 +1845,113 @@ bail:
1841 return status; 1845 return status;
1842} 1846}
1843 1847
1848/*
1849 * Scan timer should get fired every ORPHAN_SCAN_SCHEDULE_TIMEOUT. Add some
1850 * randomness to the timeout to minimize multple nodes firing the timer at the
1851 * same time.
1852 */
1853static inline unsigned long ocfs2_orphan_scan_timeout(void)
1854{
1855 unsigned long time;
1856
1857 get_random_bytes(&time, sizeof(time));
1858 time = ORPHAN_SCAN_SCHEDULE_TIMEOUT + (time % 5000);
1859 return msecs_to_jiffies(time);
1860}
1861
1862/*
1863 * ocfs2_queue_orphan_scan calls ocfs2_queue_recovery_completion for
1864 * every slot, queuing a recovery of the slot on the ocfs2_wq thread. This
1865 * is done to catch any orphans that are left over in orphan directories.
1866 *
1867 * ocfs2_queue_orphan_scan gets called every ORPHAN_SCAN_SCHEDULE_TIMEOUT
1868 * seconds. It gets an EX lock on os_lockres and checks sequence number
1869 * stored in LVB. If the sequence number has changed, it means some other
1870 * node has done the scan. This node skips the scan and tracks the
1871 * sequence number. If the sequence number didn't change, it means a scan
1872 * hasn't happened. The node queues a scan and increments the
1873 * sequence number in the LVB.
1874 */
1875void ocfs2_queue_orphan_scan(struct ocfs2_super *osb)
1876{
1877 struct ocfs2_orphan_scan *os;
1878 int status, i;
1879 u32 seqno = 0;
1880
1881 os = &osb->osb_orphan_scan;
1882
1883 status = ocfs2_orphan_scan_lock(osb, &seqno, DLM_LOCK_EX);
1884 if (status < 0) {
1885 if (status != -EAGAIN)
1886 mlog_errno(status);
1887 goto out;
1888 }
1889
1890 if (os->os_seqno != seqno) {
1891 os->os_seqno = seqno;
1892 goto unlock;
1893 }
1894
1895 for (i = 0; i < osb->max_slots; i++)
1896 ocfs2_queue_recovery_completion(osb->journal, i, NULL, NULL,
1897 NULL);
1898 /*
1899 * We queued a recovery on orphan slots, increment the sequence
1900 * number and update LVB so other node will skip the scan for a while
1901 */
1902 seqno++;
1903 os->os_count++;
1904 os->os_scantime = CURRENT_TIME;
1905unlock:
1906 ocfs2_orphan_scan_unlock(osb, seqno, DLM_LOCK_EX);
1907out:
1908 return;
1909}
1910
1911/* Worker task that gets fired every ORPHAN_SCAN_SCHEDULE_TIMEOUT millsec */
1912void ocfs2_orphan_scan_work(struct work_struct *work)
1913{
1914 struct ocfs2_orphan_scan *os;
1915 struct ocfs2_super *osb;
1916
1917 os = container_of(work, struct ocfs2_orphan_scan,
1918 os_orphan_scan_work.work);
1919 osb = os->os_osb;
1920
1921 mutex_lock(&os->os_lock);
1922 ocfs2_queue_orphan_scan(osb);
1923 schedule_delayed_work(&os->os_orphan_scan_work,
1924 ocfs2_orphan_scan_timeout());
1925 mutex_unlock(&os->os_lock);
1926}
1927
1928void ocfs2_orphan_scan_stop(struct ocfs2_super *osb)
1929{
1930 struct ocfs2_orphan_scan *os;
1931
1932 os = &osb->osb_orphan_scan;
1933 mutex_lock(&os->os_lock);
1934 cancel_delayed_work(&os->os_orphan_scan_work);
1935 mutex_unlock(&os->os_lock);
1936}
1937
1938int ocfs2_orphan_scan_init(struct ocfs2_super *osb)
1939{
1940 struct ocfs2_orphan_scan *os;
1941
1942 os = &osb->osb_orphan_scan;
1943 os->os_osb = osb;
1944 os->os_count = 0;
1945 os->os_scantime = CURRENT_TIME;
1946 mutex_init(&os->os_lock);
1947
1948 INIT_DELAYED_WORK(&os->os_orphan_scan_work,
1949 ocfs2_orphan_scan_work);
1950 schedule_delayed_work(&os->os_orphan_scan_work,
1951 ocfs2_orphan_scan_timeout());
1952 return 0;
1953}
1954
1844struct ocfs2_orphan_filldir_priv { 1955struct ocfs2_orphan_filldir_priv {
1845 struct inode *head; 1956 struct inode *head;
1846 struct ocfs2_super *osb; 1957 struct ocfs2_super *osb;
diff --git a/fs/ocfs2/journal.h b/fs/ocfs2/journal.h
index eb7b76331eb7..61045eeb3f6e 100644
--- a/fs/ocfs2/journal.h
+++ b/fs/ocfs2/journal.h
@@ -144,6 +144,10 @@ static inline void ocfs2_inode_set_new(struct ocfs2_super *osb,
144} 144}
145 145
146/* Exported only for the journal struct init code in super.c. Do not call. */ 146/* Exported only for the journal struct init code in super.c. Do not call. */
147int ocfs2_orphan_scan_init(struct ocfs2_super *osb);
148void ocfs2_orphan_scan_stop(struct ocfs2_super *osb);
149void ocfs2_orphan_scan_exit(struct ocfs2_super *osb);
150
147void ocfs2_complete_recovery(struct work_struct *work); 151void ocfs2_complete_recovery(struct work_struct *work);
148void ocfs2_wait_for_recovery(struct ocfs2_super *osb); 152void ocfs2_wait_for_recovery(struct ocfs2_super *osb);
149 153
diff --git a/fs/ocfs2/ocfs2.h b/fs/ocfs2/ocfs2.h
index 1386281950db..18c1d9ec1c93 100644
--- a/fs/ocfs2/ocfs2.h
+++ b/fs/ocfs2/ocfs2.h
@@ -47,6 +47,9 @@
47#include "ocfs2_fs.h" 47#include "ocfs2_fs.h"
48#include "ocfs2_lockid.h" 48#include "ocfs2_lockid.h"
49 49
50/* For struct ocfs2_blockcheck_stats */
51#include "blockcheck.h"
52
50/* Most user visible OCFS2 inodes will have very few pieces of 53/* Most user visible OCFS2 inodes will have very few pieces of
51 * metadata, but larger files (including bitmaps, etc) must be taken 54 * metadata, but larger files (including bitmaps, etc) must be taken
52 * into account when designing an access scheme. We allow a small 55 * into account when designing an access scheme. We allow a small
@@ -151,6 +154,16 @@ struct ocfs2_lock_res {
151#endif 154#endif
152}; 155};
153 156
157struct ocfs2_orphan_scan {
158 struct mutex os_lock;
159 struct ocfs2_super *os_osb;
160 struct ocfs2_lock_res os_lockres; /* lock to synchronize scans */
161 struct delayed_work os_orphan_scan_work;
162 struct timespec os_scantime; /* time this node ran the scan */
163 u32 os_count; /* tracks node specific scans */
164 u32 os_seqno; /* tracks cluster wide scans */
165};
166
154struct ocfs2_dlm_debug { 167struct ocfs2_dlm_debug {
155 struct kref d_refcnt; 168 struct kref d_refcnt;
156 struct dentry *d_locking_state; 169 struct dentry *d_locking_state;
@@ -295,6 +308,7 @@ struct ocfs2_super
295 struct ocfs2_dinode *local_alloc_copy; 308 struct ocfs2_dinode *local_alloc_copy;
296 struct ocfs2_quota_recovery *quota_rec; 309 struct ocfs2_quota_recovery *quota_rec;
297 310
311 struct ocfs2_blockcheck_stats osb_ecc_stats;
298 struct ocfs2_alloc_stats alloc_stats; 312 struct ocfs2_alloc_stats alloc_stats;
299 char dev_str[20]; /* "major,minor" of the device */ 313 char dev_str[20]; /* "major,minor" of the device */
300 314
@@ -341,6 +355,8 @@ struct ocfs2_super
341 unsigned int *osb_orphan_wipes; 355 unsigned int *osb_orphan_wipes;
342 wait_queue_head_t osb_wipe_event; 356 wait_queue_head_t osb_wipe_event;
343 357
358 struct ocfs2_orphan_scan osb_orphan_scan;
359
344 /* used to protect metaecc calculation check of xattr. */ 360 /* used to protect metaecc calculation check of xattr. */
345 spinlock_t osb_xattr_lock; 361 spinlock_t osb_xattr_lock;
346 362
diff --git a/fs/ocfs2/ocfs2_lockid.h b/fs/ocfs2/ocfs2_lockid.h
index a53ce87481bf..fcdba091af3d 100644
--- a/fs/ocfs2/ocfs2_lockid.h
+++ b/fs/ocfs2/ocfs2_lockid.h
@@ -48,6 +48,7 @@ enum ocfs2_lock_type {
48 OCFS2_LOCK_TYPE_FLOCK, 48 OCFS2_LOCK_TYPE_FLOCK,
49 OCFS2_LOCK_TYPE_QINFO, 49 OCFS2_LOCK_TYPE_QINFO,
50 OCFS2_LOCK_TYPE_NFS_SYNC, 50 OCFS2_LOCK_TYPE_NFS_SYNC,
51 OCFS2_LOCK_TYPE_ORPHAN_SCAN,
51 OCFS2_NUM_LOCK_TYPES 52 OCFS2_NUM_LOCK_TYPES
52}; 53};
53 54
@@ -85,6 +86,9 @@ static inline char ocfs2_lock_type_char(enum ocfs2_lock_type type)
85 case OCFS2_LOCK_TYPE_NFS_SYNC: 86 case OCFS2_LOCK_TYPE_NFS_SYNC:
86 c = 'Y'; 87 c = 'Y';
87 break; 88 break;
89 case OCFS2_LOCK_TYPE_ORPHAN_SCAN:
90 c = 'P';
91 break;
88 default: 92 default:
89 c = '\0'; 93 c = '\0';
90 } 94 }
@@ -104,6 +108,7 @@ static char *ocfs2_lock_type_strings[] = {
104 [OCFS2_LOCK_TYPE_OPEN] = "Open", 108 [OCFS2_LOCK_TYPE_OPEN] = "Open",
105 [OCFS2_LOCK_TYPE_FLOCK] = "Flock", 109 [OCFS2_LOCK_TYPE_FLOCK] = "Flock",
106 [OCFS2_LOCK_TYPE_QINFO] = "Quota", 110 [OCFS2_LOCK_TYPE_QINFO] = "Quota",
111 [OCFS2_LOCK_TYPE_ORPHAN_SCAN] = "OrphanScan",
107}; 112};
108 113
109static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type) 114static inline const char *ocfs2_lock_type_string(enum ocfs2_lock_type type)
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 1ed0f7c86869..edfa60cd155c 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -421,6 +421,7 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
421 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes; 421 OCFS2_DQUOT(dquot)->dq_originodes = dquot->dq_dqb.dqb_curinodes;
422 if (!dquot->dq_off) { /* No real quota entry? */ 422 if (!dquot->dq_off) { /* No real quota entry? */
423 /* Upgrade to exclusive lock for allocation */ 423 /* Upgrade to exclusive lock for allocation */
424 ocfs2_qinfo_unlock(info, 0);
424 err = ocfs2_qinfo_lock(info, 1); 425 err = ocfs2_qinfo_lock(info, 1);
425 if (err < 0) 426 if (err < 0)
426 goto out_qlock; 427 goto out_qlock;
@@ -435,7 +436,8 @@ int ocfs2_global_read_dquot(struct dquot *dquot)
435out_qlock: 436out_qlock:
436 if (ex) 437 if (ex)
437 ocfs2_qinfo_unlock(info, 1); 438 ocfs2_qinfo_unlock(info, 1);
438 ocfs2_qinfo_unlock(info, 0); 439 else
440 ocfs2_qinfo_unlock(info, 0);
439out: 441out:
440 if (err < 0) 442 if (err < 0)
441 mlog_errno(err); 443 mlog_errno(err);
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 07deec5e9721..5a460fa82553 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -444,10 +444,6 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
444 444
445 mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type); 445 mlog_entry("ino=%lu type=%u", (unsigned long)lqinode->i_ino, type);
446 446
447 status = ocfs2_lock_global_qf(oinfo, 1);
448 if (status < 0)
449 goto out;
450
451 list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) { 447 list_for_each_entry_safe(rchunk, next, &(rec->r_list[type]), rc_list) {
452 chunk = rchunk->rc_chunk; 448 chunk = rchunk->rc_chunk;
453 hbh = NULL; 449 hbh = NULL;
@@ -480,12 +476,18 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
480 type); 476 type);
481 goto out_put_bh; 477 goto out_put_bh;
482 } 478 }
479 status = ocfs2_lock_global_qf(oinfo, 1);
480 if (status < 0) {
481 mlog_errno(status);
482 goto out_put_dquot;
483 }
484
483 handle = ocfs2_start_trans(OCFS2_SB(sb), 485 handle = ocfs2_start_trans(OCFS2_SB(sb),
484 OCFS2_QSYNC_CREDITS); 486 OCFS2_QSYNC_CREDITS);
485 if (IS_ERR(handle)) { 487 if (IS_ERR(handle)) {
486 status = PTR_ERR(handle); 488 status = PTR_ERR(handle);
487 mlog_errno(status); 489 mlog_errno(status);
488 goto out_put_dquot; 490 goto out_drop_lock;
489 } 491 }
490 mutex_lock(&sb_dqopt(sb)->dqio_mutex); 492 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
491 spin_lock(&dq_data_lock); 493 spin_lock(&dq_data_lock);
@@ -523,6 +525,8 @@ static int ocfs2_recover_local_quota_file(struct inode *lqinode,
523out_commit: 525out_commit:
524 mutex_unlock(&sb_dqopt(sb)->dqio_mutex); 526 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
525 ocfs2_commit_trans(OCFS2_SB(sb), handle); 527 ocfs2_commit_trans(OCFS2_SB(sb), handle);
528out_drop_lock:
529 ocfs2_unlock_global_qf(oinfo, 1);
526out_put_dquot: 530out_put_dquot:
527 dqput(dquot); 531 dqput(dquot);
528out_put_bh: 532out_put_bh:
@@ -537,8 +541,6 @@ out_put_bh:
537 if (status < 0) 541 if (status < 0)
538 break; 542 break;
539 } 543 }
540 ocfs2_unlock_global_qf(oinfo, 1);
541out:
542 if (status < 0) 544 if (status < 0)
543 free_recovery_list(&(rec->r_list[type])); 545 free_recovery_list(&(rec->r_list[type]));
544 mlog_exit(status); 546 mlog_exit(status);
@@ -655,6 +657,9 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
655 struct ocfs2_quota_recovery *rec; 657 struct ocfs2_quota_recovery *rec;
656 int locked = 0; 658 int locked = 0;
657 659
660 /* We don't need the lock and we have to acquire quota file locks
661 * which will later depend on this lock */
662 mutex_unlock(&sb_dqopt(sb)->dqio_mutex);
658 info->dqi_maxblimit = 0x7fffffffffffffffLL; 663 info->dqi_maxblimit = 0x7fffffffffffffffLL;
659 info->dqi_maxilimit = 0x7fffffffffffffffLL; 664 info->dqi_maxilimit = 0x7fffffffffffffffLL;
660 oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS); 665 oinfo = kmalloc(sizeof(struct ocfs2_mem_dqinfo), GFP_NOFS);
@@ -733,6 +738,7 @@ static int ocfs2_local_read_info(struct super_block *sb, int type)
733 goto out_err; 738 goto out_err;
734 } 739 }
735 740
741 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
736 return 0; 742 return 0;
737out_err: 743out_err:
738 if (oinfo) { 744 if (oinfo) {
@@ -746,6 +752,7 @@ out_err:
746 kfree(oinfo); 752 kfree(oinfo);
747 } 753 }
748 brelse(bh); 754 brelse(bh);
755 mutex_lock(&sb_dqopt(sb)->dqio_mutex);
749 return -1; 756 return -1;
750} 757}
751 758
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c
index 201b40a441fe..d33767f17ba3 100644
--- a/fs/ocfs2/super.c
+++ b/fs/ocfs2/super.c
@@ -119,10 +119,12 @@ static void ocfs2_release_system_inodes(struct ocfs2_super *osb);
119static int ocfs2_check_volume(struct ocfs2_super *osb); 119static int ocfs2_check_volume(struct ocfs2_super *osb);
120static int ocfs2_verify_volume(struct ocfs2_dinode *di, 120static int ocfs2_verify_volume(struct ocfs2_dinode *di,
121 struct buffer_head *bh, 121 struct buffer_head *bh,
122 u32 sectsize); 122 u32 sectsize,
123 struct ocfs2_blockcheck_stats *stats);
123static int ocfs2_initialize_super(struct super_block *sb, 124static int ocfs2_initialize_super(struct super_block *sb,
124 struct buffer_head *bh, 125 struct buffer_head *bh,
125 int sector_size); 126 int sector_size,
127 struct ocfs2_blockcheck_stats *stats);
126static int ocfs2_get_sector(struct super_block *sb, 128static int ocfs2_get_sector(struct super_block *sb,
127 struct buffer_head **bh, 129 struct buffer_head **bh,
128 int block, 130 int block,
@@ -207,6 +209,7 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len)
207 int i; 209 int i;
208 struct ocfs2_cluster_connection *cconn = osb->cconn; 210 struct ocfs2_cluster_connection *cconn = osb->cconn;
209 struct ocfs2_recovery_map *rm = osb->recovery_map; 211 struct ocfs2_recovery_map *rm = osb->recovery_map;
212 struct ocfs2_orphan_scan *os;
210 213
211 out += snprintf(buf + out, len - out, 214 out += snprintf(buf + out, len - out,
212 "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n", 215 "%10s => Id: %-s Uuid: %-s Gen: 0x%X Label: %-s\n",
@@ -308,6 +311,13 @@ static int ocfs2_osb_dump(struct ocfs2_super *osb, char *buf, int len)
308 i, osb->slot_recovery_generations[i]); 311 i, osb->slot_recovery_generations[i]);
309 } 312 }
310 313
314 os = &osb->osb_orphan_scan;
315 out += snprintf(buf + out, len - out, "Orphan Scan=> ");
316 out += snprintf(buf + out, len - out, "Local: %u Global: %u ",
317 os->os_count, os->os_seqno);
318 out += snprintf(buf + out, len - out, " Last Scan: %lu seconds ago\n",
319 (get_seconds() - os->os_scantime.tv_sec));
320
311 return out; 321 return out;
312} 322}
313 323
@@ -693,7 +703,8 @@ out:
693 703
694static int ocfs2_sb_probe(struct super_block *sb, 704static int ocfs2_sb_probe(struct super_block *sb,
695 struct buffer_head **bh, 705 struct buffer_head **bh,
696 int *sector_size) 706 int *sector_size,
707 struct ocfs2_blockcheck_stats *stats)
697{ 708{
698 int status, tmpstat; 709 int status, tmpstat;
699 struct ocfs1_vol_disk_hdr *hdr; 710 struct ocfs1_vol_disk_hdr *hdr;
@@ -759,7 +770,8 @@ static int ocfs2_sb_probe(struct super_block *sb,
759 goto bail; 770 goto bail;
760 } 771 }
761 di = (struct ocfs2_dinode *) (*bh)->b_data; 772 di = (struct ocfs2_dinode *) (*bh)->b_data;
762 status = ocfs2_verify_volume(di, *bh, blksize); 773 memset(stats, 0, sizeof(struct ocfs2_blockcheck_stats));
774 status = ocfs2_verify_volume(di, *bh, blksize, stats);
763 if (status >= 0) 775 if (status >= 0)
764 goto bail; 776 goto bail;
765 brelse(*bh); 777 brelse(*bh);
@@ -965,6 +977,7 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
965 struct ocfs2_super *osb = NULL; 977 struct ocfs2_super *osb = NULL;
966 struct buffer_head *bh = NULL; 978 struct buffer_head *bh = NULL;
967 char nodestr[8]; 979 char nodestr[8];
980 struct ocfs2_blockcheck_stats stats;
968 981
969 mlog_entry("%p, %p, %i", sb, data, silent); 982 mlog_entry("%p, %p, %i", sb, data, silent);
970 983
@@ -974,13 +987,13 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
974 } 987 }
975 988
976 /* probe for superblock */ 989 /* probe for superblock */
977 status = ocfs2_sb_probe(sb, &bh, &sector_size); 990 status = ocfs2_sb_probe(sb, &bh, &sector_size, &stats);
978 if (status < 0) { 991 if (status < 0) {
979 mlog(ML_ERROR, "superblock probe failed!\n"); 992 mlog(ML_ERROR, "superblock probe failed!\n");
980 goto read_super_error; 993 goto read_super_error;
981 } 994 }
982 995
983 status = ocfs2_initialize_super(sb, bh, sector_size); 996 status = ocfs2_initialize_super(sb, bh, sector_size, &stats);
984 osb = OCFS2_SB(sb); 997 osb = OCFS2_SB(sb);
985 if (status < 0) { 998 if (status < 0) {
986 mlog_errno(status); 999 mlog_errno(status);
@@ -1090,6 +1103,18 @@ static int ocfs2_fill_super(struct super_block *sb, void *data, int silent)
1090 goto read_super_error; 1103 goto read_super_error;
1091 } 1104 }
1092 1105
1106 if (ocfs2_meta_ecc(osb)) {
1107 status = ocfs2_blockcheck_stats_debugfs_install(
1108 &osb->osb_ecc_stats,
1109 osb->osb_debug_root);
1110 if (status) {
1111 mlog(ML_ERROR,
1112 "Unable to create blockcheck statistics "
1113 "files\n");
1114 goto read_super_error;
1115 }
1116 }
1117
1093 status = ocfs2_mount_volume(sb); 1118 status = ocfs2_mount_volume(sb);
1094 if (osb->root_inode) 1119 if (osb->root_inode)
1095 inode = igrab(osb->root_inode); 1120 inode = igrab(osb->root_inode);
@@ -1760,13 +1785,8 @@ static int ocfs2_mount_volume(struct super_block *sb)
1760 } 1785 }
1761 1786
1762 status = ocfs2_truncate_log_init(osb); 1787 status = ocfs2_truncate_log_init(osb);
1763 if (status < 0) { 1788 if (status < 0)
1764 mlog_errno(status); 1789 mlog_errno(status);
1765 goto leave;
1766 }
1767
1768 if (ocfs2_mount_local(osb))
1769 goto leave;
1770 1790
1771leave: 1791leave:
1772 if (unlock_super) 1792 if (unlock_super)
@@ -1796,6 +1816,8 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1796 1816
1797 ocfs2_truncate_log_shutdown(osb); 1817 ocfs2_truncate_log_shutdown(osb);
1798 1818
1819 ocfs2_orphan_scan_stop(osb);
1820
1799 /* This will disable recovery and flush any recovery work. */ 1821 /* This will disable recovery and flush any recovery work. */
1800 ocfs2_recovery_exit(osb); 1822 ocfs2_recovery_exit(osb);
1801 1823
@@ -1833,6 +1855,7 @@ static void ocfs2_dismount_volume(struct super_block *sb, int mnt_err)
1833 if (osb->cconn) 1855 if (osb->cconn)
1834 ocfs2_dlm_shutdown(osb, hangup_needed); 1856 ocfs2_dlm_shutdown(osb, hangup_needed);
1835 1857
1858 ocfs2_blockcheck_stats_debugfs_remove(&osb->osb_ecc_stats);
1836 debugfs_remove(osb->osb_debug_root); 1859 debugfs_remove(osb->osb_debug_root);
1837 1860
1838 if (hangup_needed) 1861 if (hangup_needed)
@@ -1880,7 +1903,8 @@ static int ocfs2_setup_osb_uuid(struct ocfs2_super *osb, const unsigned char *uu
1880 1903
1881static int ocfs2_initialize_super(struct super_block *sb, 1904static int ocfs2_initialize_super(struct super_block *sb,
1882 struct buffer_head *bh, 1905 struct buffer_head *bh,
1883 int sector_size) 1906 int sector_size,
1907 struct ocfs2_blockcheck_stats *stats)
1884{ 1908{
1885 int status; 1909 int status;
1886 int i, cbits, bbits; 1910 int i, cbits, bbits;
@@ -1939,6 +1963,9 @@ static int ocfs2_initialize_super(struct super_block *sb,
1939 atomic_set(&osb->alloc_stats.bg_allocs, 0); 1963 atomic_set(&osb->alloc_stats.bg_allocs, 0);
1940 atomic_set(&osb->alloc_stats.bg_extends, 0); 1964 atomic_set(&osb->alloc_stats.bg_extends, 0);
1941 1965
1966 /* Copy the blockcheck stats from the superblock probe */
1967 osb->osb_ecc_stats = *stats;
1968
1942 ocfs2_init_node_maps(osb); 1969 ocfs2_init_node_maps(osb);
1943 1970
1944 snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u", 1971 snprintf(osb->dev_str, sizeof(osb->dev_str), "%u,%u",
@@ -1951,6 +1978,13 @@ static int ocfs2_initialize_super(struct super_block *sb,
1951 goto bail; 1978 goto bail;
1952 } 1979 }
1953 1980
1981 status = ocfs2_orphan_scan_init(osb);
1982 if (status) {
1983 mlog(ML_ERROR, "Unable to initialize delayed orphan scan\n");
1984 mlog_errno(status);
1985 goto bail;
1986 }
1987
1954 init_waitqueue_head(&osb->checkpoint_event); 1988 init_waitqueue_head(&osb->checkpoint_event);
1955 atomic_set(&osb->needs_checkpoint, 0); 1989 atomic_set(&osb->needs_checkpoint, 0);
1956 1990
@@ -2169,7 +2203,8 @@ bail:
2169 */ 2203 */
2170static int ocfs2_verify_volume(struct ocfs2_dinode *di, 2204static int ocfs2_verify_volume(struct ocfs2_dinode *di,
2171 struct buffer_head *bh, 2205 struct buffer_head *bh,
2172 u32 blksz) 2206 u32 blksz,
2207 struct ocfs2_blockcheck_stats *stats)
2173{ 2208{
2174 int status = -EAGAIN; 2209 int status = -EAGAIN;
2175 2210
@@ -2182,7 +2217,8 @@ static int ocfs2_verify_volume(struct ocfs2_dinode *di,
2182 OCFS2_FEATURE_INCOMPAT_META_ECC) { 2217 OCFS2_FEATURE_INCOMPAT_META_ECC) {
2183 status = ocfs2_block_check_validate(bh->b_data, 2218 status = ocfs2_block_check_validate(bh->b_data,
2184 bh->b_size, 2219 bh->b_size,
2185 &di->i_check); 2220 &di->i_check,
2221 stats);
2186 if (status) 2222 if (status)
2187 goto out; 2223 goto out;
2188 } 2224 }
diff --git a/fs/ocfs2/xattr.c b/fs/ocfs2/xattr.c
index 15631019dc63..ba320e250747 100644
--- a/fs/ocfs2/xattr.c
+++ b/fs/ocfs2/xattr.c
@@ -3154,7 +3154,7 @@ static int ocfs2_iterate_xattr_buckets(struct inode *inode,
3154 le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash)); 3154 le32_to_cpu(bucket_xh(bucket)->xh_entries[0].xe_name_hash));
3155 if (func) { 3155 if (func) {
3156 ret = func(inode, bucket, para); 3156 ret = func(inode, bucket, para);
3157 if (ret) 3157 if (ret && ret != -ERANGE)
3158 mlog_errno(ret); 3158 mlog_errno(ret);
3159 /* Fall through to bucket_relse() */ 3159 /* Fall through to bucket_relse() */
3160 } 3160 }
@@ -3261,7 +3261,8 @@ static int ocfs2_xattr_tree_list_index_block(struct inode *inode,
3261 ocfs2_list_xattr_bucket, 3261 ocfs2_list_xattr_bucket,
3262 &xl); 3262 &xl);
3263 if (ret) { 3263 if (ret) {
3264 mlog_errno(ret); 3264 if (ret != -ERANGE)
3265 mlog_errno(ret);
3265 goto out; 3266 goto out;
3266 } 3267 }
3267 3268
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c
index 3a6b193d8444..0ff7566c767c 100644
--- a/fs/ramfs/inode.c
+++ b/fs/ramfs/inode.c
@@ -202,9 +202,12 @@ static int ramfs_parse_options(char *data, struct ramfs_mount_opts *opts)
202 return -EINVAL; 202 return -EINVAL;
203 opts->mode = option & S_IALLUGO; 203 opts->mode = option & S_IALLUGO;
204 break; 204 break;
205 default: 205 /*
206 printk(KERN_ERR "ramfs: bad mount option: %s\n", p); 206 * We might like to report bad mount options here;
207 return -EINVAL; 207 * but traditionally ramfs has ignored all mount options,
208 * and as it is used as a !CONFIG_SHMEM simple substitute
209 * for tmpfs, better continue to ignore other mount options.
210 */
208 } 211 }
209 } 212 }
210 213
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 3589eab02a2f..3260b73abe29 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -1937,6 +1937,9 @@ static int ubifs_fill_super(struct super_block *sb, void *data, int silent)
1937 err = bdi_init(&c->bdi); 1937 err = bdi_init(&c->bdi);
1938 if (err) 1938 if (err)
1939 goto out_close; 1939 goto out_close;
1940 err = bdi_register(&c->bdi, NULL, "ubifs");
1941 if (err)
1942 goto out_bdi;
1940 1943
1941 err = ubifs_parse_options(c, data, 0); 1944 err = ubifs_parse_options(c, data, 0);
1942 if (err) 1945 if (err)