diff options
author | Steve French <sfrench@us.ibm.com> | 2006-06-25 11:57:32 -0400 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2006-06-25 11:57:32 -0400 |
commit | bbe5d235ee201705530a7153b57e141cd77d818b (patch) | |
tree | e98c31b4cb2ced6357a87a02596f9ecdbd6dbb26 /fs | |
parent | 189acaaef81b1d71aedd0d28810de24160c2e781 (diff) | |
parent | dfd8317d3340f03bc06eba6b58f0ec0861da4a13 (diff) |
Merge with /pub/scm/linux/kernel/git/torvalds/linux-2.6.git
Diffstat (limited to 'fs')
260 files changed, 9074 insertions, 9509 deletions
diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 61c599b4a1e3..872943004e59 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c | |||
@@ -99,12 +99,13 @@ v9fs_fill_super(struct super_block *sb, struct v9fs_session_info *v9ses, | |||
99 | * @flags: mount flags | 99 | * @flags: mount flags |
100 | * @dev_name: device name that was mounted | 100 | * @dev_name: device name that was mounted |
101 | * @data: mount options | 101 | * @data: mount options |
102 | * @mnt: mountpoint record to be instantiated | ||
102 | * | 103 | * |
103 | */ | 104 | */ |
104 | 105 | ||
105 | static struct super_block *v9fs_get_sb(struct file_system_type | 106 | static int v9fs_get_sb(struct file_system_type *fs_type, int flags, |
106 | *fs_type, int flags, | 107 | const char *dev_name, void *data, |
107 | const char *dev_name, void *data) | 108 | struct vfsmount *mnt) |
108 | { | 109 | { |
109 | struct super_block *sb = NULL; | 110 | struct super_block *sb = NULL; |
110 | struct v9fs_fcall *fcall = NULL; | 111 | struct v9fs_fcall *fcall = NULL; |
@@ -123,17 +124,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
123 | 124 | ||
124 | v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); | 125 | v9ses = kzalloc(sizeof(struct v9fs_session_info), GFP_KERNEL); |
125 | if (!v9ses) | 126 | if (!v9ses) |
126 | return ERR_PTR(-ENOMEM); | 127 | return -ENOMEM; |
127 | 128 | ||
128 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { | 129 | if ((newfid = v9fs_session_init(v9ses, dev_name, data)) < 0) { |
129 | dprintk(DEBUG_ERROR, "problem initiating session\n"); | 130 | dprintk(DEBUG_ERROR, "problem initiating session\n"); |
130 | sb = ERR_PTR(newfid); | 131 | retval = newfid; |
131 | goto out_free_session; | 132 | goto out_free_session; |
132 | } | 133 | } |
133 | 134 | ||
134 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); | 135 | sb = sget(fs_type, NULL, v9fs_set_super, v9ses); |
135 | if (IS_ERR(sb)) | 136 | if (IS_ERR(sb)) { |
137 | retval = PTR_ERR(sb); | ||
136 | goto out_close_session; | 138 | goto out_close_session; |
139 | } | ||
137 | v9fs_fill_super(sb, v9ses, flags); | 140 | v9fs_fill_super(sb, v9ses, flags); |
138 | 141 | ||
139 | inode = v9fs_get_inode(sb, S_IFDIR | mode); | 142 | inode = v9fs_get_inode(sb, S_IFDIR | mode); |
@@ -184,19 +187,19 @@ static struct super_block *v9fs_get_sb(struct file_system_type | |||
184 | goto put_back_sb; | 187 | goto put_back_sb; |
185 | } | 188 | } |
186 | 189 | ||
187 | return sb; | 190 | return simple_set_mnt(mnt, sb); |
188 | 191 | ||
189 | out_close_session: | 192 | out_close_session: |
190 | v9fs_session_close(v9ses); | 193 | v9fs_session_close(v9ses); |
191 | out_free_session: | 194 | out_free_session: |
192 | kfree(v9ses); | 195 | kfree(v9ses); |
193 | return sb; | 196 | return retval; |
194 | 197 | ||
195 | put_back_sb: | 198 | put_back_sb: |
196 | /* deactivate_super calls v9fs_kill_super which will frees the rest */ | 199 | /* deactivate_super calls v9fs_kill_super which will frees the rest */ |
197 | up_write(&sb->s_umount); | 200 | up_write(&sb->s_umount); |
198 | deactivate_super(sb); | 201 | deactivate_super(sb); |
199 | return ERR_PTR(retval); | 202 | return retval; |
200 | } | 203 | } |
201 | 204 | ||
202 | /** | 205 | /** |
diff --git a/fs/Kconfig b/fs/Kconfig index d49b2a8c0be6..467f7ae5f092 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -53,7 +53,7 @@ config EXT2_FS_SECURITY | |||
53 | 53 | ||
54 | config EXT2_FS_XIP | 54 | config EXT2_FS_XIP |
55 | bool "Ext2 execute in place support" | 55 | bool "Ext2 execute in place support" |
56 | depends on EXT2_FS | 56 | depends on EXT2_FS && MMU |
57 | help | 57 | help |
58 | Execute in place can be used on memory-backed block devices. If you | 58 | Execute in place can be used on memory-backed block devices. If you |
59 | enable this option, you can select to mount block devices which are | 59 | enable this option, you can select to mount block devices which are |
@@ -393,18 +393,30 @@ config INOTIFY | |||
393 | bool "Inotify file change notification support" | 393 | bool "Inotify file change notification support" |
394 | default y | 394 | default y |
395 | ---help--- | 395 | ---help--- |
396 | Say Y here to enable inotify support and the associated system | 396 | Say Y here to enable inotify support. Inotify is a file change |
397 | calls. Inotify is a file change notification system and a | 397 | notification system and a replacement for dnotify. Inotify fixes |
398 | replacement for dnotify. Inotify fixes numerous shortcomings in | 398 | numerous shortcomings in dnotify and introduces several new features |
399 | dnotify and introduces several new features. It allows monitoring | 399 | including multiple file events, one-shot support, and unmount |
400 | of both files and directories via a single open fd. Other features | ||
401 | include multiple file events, one-shot support, and unmount | ||
402 | notification. | 400 | notification. |
403 | 401 | ||
404 | For more information, see Documentation/filesystems/inotify.txt | 402 | For more information, see Documentation/filesystems/inotify.txt |
405 | 403 | ||
406 | If unsure, say Y. | 404 | If unsure, say Y. |
407 | 405 | ||
406 | config INOTIFY_USER | ||
407 | bool "Inotify support for userspace" | ||
408 | depends on INOTIFY | ||
409 | default y | ||
410 | ---help--- | ||
411 | Say Y here to enable inotify support for userspace, including the | ||
412 | associated system calls. Inotify allows monitoring of both files and | ||
413 | directories via a single open fd. Events are read from the file | ||
414 | descriptor, which is also select()- and poll()-able. | ||
415 | |||
416 | For more information, see Documentation/filesystems/inotify.txt | ||
417 | |||
418 | If unsure, say Y. | ||
419 | |||
408 | config QUOTA | 420 | config QUOTA |
409 | bool "Quota support" | 421 | bool "Quota support" |
410 | help | 422 | help |
@@ -1101,6 +1113,44 @@ config JFFS2_SUMMARY | |||
1101 | 1113 | ||
1102 | If unsure, say 'N'. | 1114 | If unsure, say 'N'. |
1103 | 1115 | ||
1116 | config JFFS2_FS_XATTR | ||
1117 | bool "JFFS2 XATTR support (EXPERIMENTAL)" | ||
1118 | depends on JFFS2_FS && EXPERIMENTAL && !JFFS2_FS_WRITEBUFFER | ||
1119 | default n | ||
1120 | help | ||
1121 | Extended attributes are name:value pairs associated with inodes by | ||
1122 | the kernel or by users (see the attr(5) manual page, or visit | ||
1123 | <http://acl.bestbits.at/> for details). | ||
1124 | |||
1125 | If unsure, say N. | ||
1126 | |||
1127 | config JFFS2_FS_POSIX_ACL | ||
1128 | bool "JFFS2 POSIX Access Control Lists" | ||
1129 | depends on JFFS2_FS_XATTR | ||
1130 | default y | ||
1131 | select FS_POSIX_ACL | ||
1132 | help | ||
1133 | Posix Access Control Lists (ACLs) support permissions for users and | ||
1134 | groups beyond the owner/group/world scheme. | ||
1135 | |||
1136 | To learn more about Access Control Lists, visit the Posix ACLs for | ||
1137 | Linux website <http://acl.bestbits.at/>. | ||
1138 | |||
1139 | If you don't know what Access Control Lists are, say N | ||
1140 | |||
1141 | config JFFS2_FS_SECURITY | ||
1142 | bool "JFFS2 Security Labels" | ||
1143 | depends on JFFS2_FS_XATTR | ||
1144 | default y | ||
1145 | help | ||
1146 | Security labels support alternative access control models | ||
1147 | implemented by security modules like SELinux. This option | ||
1148 | enables an extended attribute handler for file security | ||
1149 | labels in the jffs2 filesystem. | ||
1150 | |||
1151 | If you are not using a security module that requires using | ||
1152 | extended attributes for file security labels, say N. | ||
1153 | |||
1104 | config JFFS2_COMPRESSION_OPTIONS | 1154 | config JFFS2_COMPRESSION_OPTIONS |
1105 | bool "Advanced compression options for JFFS2" | 1155 | bool "Advanced compression options for JFFS2" |
1106 | depends on JFFS2_FS | 1156 | depends on JFFS2_FS |
diff --git a/fs/Makefile b/fs/Makefile index 078d3d1191a5..d0ea6bfccf29 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -13,6 +13,7 @@ obj-y := open.o read_write.o file_table.o buffer.o bio.o super.o \ | |||
13 | ioprio.o pnode.o drop_caches.o splice.o sync.o | 13 | ioprio.o pnode.o drop_caches.o splice.o sync.o |
14 | 14 | ||
15 | obj-$(CONFIG_INOTIFY) += inotify.o | 15 | obj-$(CONFIG_INOTIFY) += inotify.o |
16 | obj-$(CONFIG_INOTIFY_USER) += inotify_user.o | ||
16 | obj-$(CONFIG_EPOLL) += eventpoll.o | 17 | obj-$(CONFIG_EPOLL) += eventpoll.o |
17 | obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o | 18 | obj-$(CONFIG_COMPAT) += compat.o compat_ioctl.o |
18 | 19 | ||
diff --git a/fs/adfs/super.c b/fs/adfs/super.c index 252abda0d200..ba1c88af49fe 100644 --- a/fs/adfs/super.c +++ b/fs/adfs/super.c | |||
@@ -196,17 +196,17 @@ static int adfs_remount(struct super_block *sb, int *flags, char *data) | |||
196 | return parse_options(sb, data); | 196 | return parse_options(sb, data); |
197 | } | 197 | } |
198 | 198 | ||
199 | static int adfs_statfs(struct super_block *sb, struct kstatfs *buf) | 199 | static int adfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
200 | { | 200 | { |
201 | struct adfs_sb_info *asb = ADFS_SB(sb); | 201 | struct adfs_sb_info *asb = ADFS_SB(dentry->d_sb); |
202 | 202 | ||
203 | buf->f_type = ADFS_SUPER_MAGIC; | 203 | buf->f_type = ADFS_SUPER_MAGIC; |
204 | buf->f_namelen = asb->s_namelen; | 204 | buf->f_namelen = asb->s_namelen; |
205 | buf->f_bsize = sb->s_blocksize; | 205 | buf->f_bsize = dentry->d_sb->s_blocksize; |
206 | buf->f_blocks = asb->s_size; | 206 | buf->f_blocks = asb->s_size; |
207 | buf->f_files = asb->s_ids_per_zone * asb->s_map_size; | 207 | buf->f_files = asb->s_ids_per_zone * asb->s_map_size; |
208 | buf->f_bavail = | 208 | buf->f_bavail = |
209 | buf->f_bfree = adfs_map_free(sb); | 209 | buf->f_bfree = adfs_map_free(dentry->d_sb); |
210 | buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; | 210 | buf->f_ffree = (long)(buf->f_bfree * buf->f_files) / (long)buf->f_blocks; |
211 | 211 | ||
212 | return 0; | 212 | return 0; |
@@ -470,10 +470,11 @@ error: | |||
470 | return -EINVAL; | 470 | return -EINVAL; |
471 | } | 471 | } |
472 | 472 | ||
473 | static struct super_block *adfs_get_sb(struct file_system_type *fs_type, | 473 | static int adfs_get_sb(struct file_system_type *fs_type, |
474 | int flags, const char *dev_name, void *data) | 474 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
475 | { | 475 | { |
476 | return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super); | 476 | return get_sb_bdev(fs_type, flags, dev_name, data, adfs_fill_super, |
477 | mnt); | ||
477 | } | 478 | } |
478 | 479 | ||
479 | static struct file_system_type adfs_fs_type = { | 480 | static struct file_system_type adfs_fs_type = { |
diff --git a/fs/affs/super.c b/fs/affs/super.c index 4d7e5b19e5cd..8765cba35bb9 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -18,7 +18,7 @@ | |||
18 | 18 | ||
19 | extern struct timezone sys_tz; | 19 | extern struct timezone sys_tz; |
20 | 20 | ||
21 | static int affs_statfs(struct super_block *sb, struct kstatfs *buf); | 21 | static int affs_statfs(struct dentry *dentry, struct kstatfs *buf); |
22 | static int affs_remount (struct super_block *sb, int *flags, char *data); | 22 | static int affs_remount (struct super_block *sb, int *flags, char *data); |
23 | 23 | ||
24 | static void | 24 | static void |
@@ -508,8 +508,9 @@ affs_remount(struct super_block *sb, int *flags, char *data) | |||
508 | } | 508 | } |
509 | 509 | ||
510 | static int | 510 | static int |
511 | affs_statfs(struct super_block *sb, struct kstatfs *buf) | 511 | affs_statfs(struct dentry *dentry, struct kstatfs *buf) |
512 | { | 512 | { |
513 | struct super_block *sb = dentry->d_sb; | ||
513 | int free; | 514 | int free; |
514 | 515 | ||
515 | pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, | 516 | pr_debug("AFFS: statfs() partsize=%d, reserved=%d\n",AFFS_SB(sb)->s_partition_size, |
@@ -524,10 +525,11 @@ affs_statfs(struct super_block *sb, struct kstatfs *buf) | |||
524 | return 0; | 525 | return 0; |
525 | } | 526 | } |
526 | 527 | ||
527 | static struct super_block *affs_get_sb(struct file_system_type *fs_type, | 528 | static int affs_get_sb(struct file_system_type *fs_type, |
528 | int flags, const char *dev_name, void *data) | 529 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
529 | { | 530 | { |
530 | return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super); | 531 | return get_sb_bdev(fs_type, flags, dev_name, data, affs_fill_super, |
532 | mnt); | ||
531 | } | 533 | } |
532 | 534 | ||
533 | static struct file_system_type affs_fs_type = { | 535 | static struct file_system_type affs_fs_type = { |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index a6dff6a4f204..2fc99877cb0d 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
@@ -185,9 +185,7 @@ static struct page *afs_dir_get_page(struct inode *dir, unsigned long index) | |||
185 | 185 | ||
186 | _enter("{%lu},%lu", dir->i_ino, index); | 186 | _enter("{%lu},%lu", dir->i_ino, index); |
187 | 187 | ||
188 | page = read_cache_page(dir->i_mapping,index, | 188 | page = read_mapping_page(dir->i_mapping, index, NULL); |
189 | (filler_t *) dir->i_mapping->a_ops->readpage, | ||
190 | NULL); | ||
191 | if (!IS_ERR(page)) { | 189 | if (!IS_ERR(page)) { |
192 | wait_on_page_locked(page); | 190 | wait_on_page_locked(page); |
193 | kmap(page); | 191 | kmap(page); |
diff --git a/fs/afs/mntpt.c b/fs/afs/mntpt.c index 4e6eeb59b83c..b5cf9e1205ad 100644 --- a/fs/afs/mntpt.c +++ b/fs/afs/mntpt.c | |||
@@ -63,7 +63,6 @@ unsigned long afs_mntpt_expiry_timeout = 20; | |||
63 | int afs_mntpt_check_symlink(struct afs_vnode *vnode) | 63 | int afs_mntpt_check_symlink(struct afs_vnode *vnode) |
64 | { | 64 | { |
65 | struct page *page; | 65 | struct page *page; |
66 | filler_t *filler; | ||
67 | size_t size; | 66 | size_t size; |
68 | char *buf; | 67 | char *buf; |
69 | int ret; | 68 | int ret; |
@@ -71,10 +70,7 @@ int afs_mntpt_check_symlink(struct afs_vnode *vnode) | |||
71 | _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique); | 70 | _enter("{%u,%u}", vnode->fid.vnode, vnode->fid.unique); |
72 | 71 | ||
73 | /* read the contents of the symlink into the pagecache */ | 72 | /* read the contents of the symlink into the pagecache */ |
74 | filler = (filler_t *) AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage; | 73 | page = read_mapping_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, NULL); |
75 | |||
76 | page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping, 0, | ||
77 | filler, NULL); | ||
78 | if (IS_ERR(page)) { | 74 | if (IS_ERR(page)) { |
79 | ret = PTR_ERR(page); | 75 | ret = PTR_ERR(page); |
80 | goto out; | 76 | goto out; |
@@ -160,7 +156,6 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
160 | struct page *page = NULL; | 156 | struct page *page = NULL; |
161 | size_t size; | 157 | size_t size; |
162 | char *buf, *devname = NULL, *options = NULL; | 158 | char *buf, *devname = NULL, *options = NULL; |
163 | filler_t *filler; | ||
164 | int ret; | 159 | int ret; |
165 | 160 | ||
166 | kenter("{%s}", mntpt->d_name.name); | 161 | kenter("{%s}", mntpt->d_name.name); |
@@ -182,9 +177,7 @@ static struct vfsmount *afs_mntpt_do_automount(struct dentry *mntpt) | |||
182 | goto error; | 177 | goto error; |
183 | 178 | ||
184 | /* read the contents of the AFS special symlink */ | 179 | /* read the contents of the AFS special symlink */ |
185 | filler = (filler_t *)mntpt->d_inode->i_mapping->a_ops->readpage; | 180 | page = read_mapping_page(mntpt->d_inode->i_mapping, 0, NULL); |
186 | |||
187 | page = read_cache_page(mntpt->d_inode->i_mapping, 0, filler, NULL); | ||
188 | if (IS_ERR(page)) { | 181 | if (IS_ERR(page)) { |
189 | ret = PTR_ERR(page); | 182 | ret = PTR_ERR(page); |
190 | goto error; | 183 | goto error; |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 53c56e7231ab..82468df0ba54 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
@@ -38,9 +38,9 @@ struct afs_mount_params { | |||
38 | static void afs_i_init_once(void *foo, kmem_cache_t *cachep, | 38 | static void afs_i_init_once(void *foo, kmem_cache_t *cachep, |
39 | unsigned long flags); | 39 | unsigned long flags); |
40 | 40 | ||
41 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, | 41 | static int afs_get_sb(struct file_system_type *fs_type, |
42 | int flags, const char *dev_name, | 42 | int flags, const char *dev_name, |
43 | void *data); | 43 | void *data, struct vfsmount *mnt); |
44 | 44 | ||
45 | static struct inode *afs_alloc_inode(struct super_block *sb); | 45 | static struct inode *afs_alloc_inode(struct super_block *sb); |
46 | 46 | ||
@@ -294,10 +294,11 @@ static int afs_fill_super(struct super_block *sb, void *data, int silent) | |||
294 | * get an AFS superblock | 294 | * get an AFS superblock |
295 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly | 295 | * - TODO: don't use get_sb_nodev(), but rather call sget() directly |
296 | */ | 296 | */ |
297 | static struct super_block *afs_get_sb(struct file_system_type *fs_type, | 297 | static int afs_get_sb(struct file_system_type *fs_type, |
298 | int flags, | 298 | int flags, |
299 | const char *dev_name, | 299 | const char *dev_name, |
300 | void *options) | 300 | void *options, |
301 | struct vfsmount *mnt) | ||
301 | { | 302 | { |
302 | struct afs_mount_params params; | 303 | struct afs_mount_params params; |
303 | struct super_block *sb; | 304 | struct super_block *sb; |
@@ -311,7 +312,7 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, | |||
311 | ret = afscm_start(); | 312 | ret = afscm_start(); |
312 | if (ret < 0) { | 313 | if (ret < 0) { |
313 | _leave(" = %d", ret); | 314 | _leave(" = %d", ret); |
314 | return ERR_PTR(ret); | 315 | return ret; |
315 | } | 316 | } |
316 | 317 | ||
317 | /* parse the options */ | 318 | /* parse the options */ |
@@ -348,18 +349,19 @@ static struct super_block *afs_get_sb(struct file_system_type *fs_type, | |||
348 | goto error; | 349 | goto error; |
349 | } | 350 | } |
350 | sb->s_flags |= MS_ACTIVE; | 351 | sb->s_flags |= MS_ACTIVE; |
352 | simple_set_mnt(mnt, sb); | ||
351 | 353 | ||
352 | afs_put_volume(params.volume); | 354 | afs_put_volume(params.volume); |
353 | afs_put_cell(params.default_cell); | 355 | afs_put_cell(params.default_cell); |
354 | _leave(" = %p", sb); | 356 | _leave(" = 0 [%p]", 0, sb); |
355 | return sb; | 357 | return 0; |
356 | 358 | ||
357 | error: | 359 | error: |
358 | afs_put_volume(params.volume); | 360 | afs_put_volume(params.volume); |
359 | afs_put_cell(params.default_cell); | 361 | afs_put_cell(params.default_cell); |
360 | afscm_stop(); | 362 | afscm_stop(); |
361 | _leave(" = %d", ret); | 363 | _leave(" = %d", ret); |
362 | return ERR_PTR(ret); | 364 | return ret; |
363 | } /* end afs_get_sb() */ | 365 | } /* end afs_get_sb() */ |
364 | 366 | ||
365 | /*****************************************************************************/ | 367 | /*****************************************************************************/ |
@@ -777,11 +777,11 @@ out: | |||
777 | static int __aio_run_iocbs(struct kioctx *ctx) | 777 | static int __aio_run_iocbs(struct kioctx *ctx) |
778 | { | 778 | { |
779 | struct kiocb *iocb; | 779 | struct kiocb *iocb; |
780 | LIST_HEAD(run_list); | 780 | struct list_head run_list; |
781 | 781 | ||
782 | assert_spin_locked(&ctx->ctx_lock); | 782 | assert_spin_locked(&ctx->ctx_lock); |
783 | 783 | ||
784 | list_splice_init(&ctx->run_list, &run_list); | 784 | list_replace_init(&ctx->run_list, &run_list); |
785 | while (!list_empty(&run_list)) { | 785 | while (!list_empty(&run_list)) { |
786 | iocb = list_entry(run_list.next, struct kiocb, | 786 | iocb = list_entry(run_list.next, struct kiocb, |
787 | ki_run_list); | 787 | ki_run_list); |
diff --git a/fs/autofs/init.c b/fs/autofs/init.c index b977ece69f0c..aca123752406 100644 --- a/fs/autofs/init.c +++ b/fs/autofs/init.c | |||
@@ -14,10 +14,10 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include "autofs_i.h" | 15 | #include "autofs_i.h" |
16 | 16 | ||
17 | static struct super_block *autofs_get_sb(struct file_system_type *fs_type, | 17 | static int autofs_get_sb(struct file_system_type *fs_type, |
18 | int flags, const char *dev_name, void *data) | 18 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
19 | { | 19 | { |
20 | return get_sb_nodev(fs_type, flags, data, autofs_fill_super); | 20 | return get_sb_nodev(fs_type, flags, data, autofs_fill_super, mnt); |
21 | } | 21 | } |
22 | 22 | ||
23 | static struct file_system_type autofs_fs_type = { | 23 | static struct file_system_type autofs_fs_type = { |
diff --git a/fs/autofs4/init.c b/fs/autofs4/init.c index acecec8578ce..5d9193332bef 100644 --- a/fs/autofs4/init.c +++ b/fs/autofs4/init.c | |||
@@ -14,10 +14,10 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include "autofs_i.h" | 15 | #include "autofs_i.h" |
16 | 16 | ||
17 | static struct super_block *autofs_get_sb(struct file_system_type *fs_type, | 17 | static int autofs_get_sb(struct file_system_type *fs_type, |
18 | int flags, const char *dev_name, void *data) | 18 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
19 | { | 19 | { |
20 | return get_sb_nodev(fs_type, flags, data, autofs4_fill_super); | 20 | return get_sb_nodev(fs_type, flags, data, autofs4_fill_super, mnt); |
21 | } | 21 | } |
22 | 22 | ||
23 | static struct file_system_type autofs_fs_type = { | 23 | static struct file_system_type autofs_fs_type = { |
diff --git a/fs/befs/linuxvfs.c b/fs/befs/linuxvfs.c index 68ebd10f345d..08201fab26cd 100644 --- a/fs/befs/linuxvfs.c +++ b/fs/befs/linuxvfs.c | |||
@@ -49,7 +49,7 @@ static int befs_nls2utf(struct super_block *sb, const char *in, int in_len, | |||
49 | char **out, int *out_len); | 49 | char **out, int *out_len); |
50 | static void befs_put_super(struct super_block *); | 50 | static void befs_put_super(struct super_block *); |
51 | static int befs_remount(struct super_block *, int *, char *); | 51 | static int befs_remount(struct super_block *, int *, char *); |
52 | static int befs_statfs(struct super_block *, struct kstatfs *); | 52 | static int befs_statfs(struct dentry *, struct kstatfs *); |
53 | static int parse_options(char *, befs_mount_options *); | 53 | static int parse_options(char *, befs_mount_options *); |
54 | 54 | ||
55 | static const struct super_operations befs_sops = { | 55 | static const struct super_operations befs_sops = { |
@@ -880,8 +880,9 @@ befs_remount(struct super_block *sb, int *flags, char *data) | |||
880 | } | 880 | } |
881 | 881 | ||
882 | static int | 882 | static int |
883 | befs_statfs(struct super_block *sb, struct kstatfs *buf) | 883 | befs_statfs(struct dentry *dentry, struct kstatfs *buf) |
884 | { | 884 | { |
885 | struct super_block *sb = dentry->d_sb; | ||
885 | 886 | ||
886 | befs_debug(sb, "---> befs_statfs()"); | 887 | befs_debug(sb, "---> befs_statfs()"); |
887 | 888 | ||
@@ -899,11 +900,12 @@ befs_statfs(struct super_block *sb, struct kstatfs *buf) | |||
899 | return 0; | 900 | return 0; |
900 | } | 901 | } |
901 | 902 | ||
902 | static struct super_block * | 903 | static int |
903 | befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, | 904 | befs_get_sb(struct file_system_type *fs_type, int flags, const char *dev_name, |
904 | void *data) | 905 | void *data, struct vfsmount *mnt) |
905 | { | 906 | { |
906 | return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super); | 907 | return get_sb_bdev(fs_type, flags, dev_name, data, befs_fill_super, |
908 | mnt); | ||
907 | } | 909 | } |
908 | 910 | ||
909 | static struct file_system_type befs_fs_type = { | 911 | static struct file_system_type befs_fs_type = { |
diff --git a/fs/bfs/inode.c b/fs/bfs/inode.c index 55a7a78332f8..cf74f3d4d966 100644 --- a/fs/bfs/inode.c +++ b/fs/bfs/inode.c | |||
@@ -203,8 +203,9 @@ static void bfs_put_super(struct super_block *s) | |||
203 | s->s_fs_info = NULL; | 203 | s->s_fs_info = NULL; |
204 | } | 204 | } |
205 | 205 | ||
206 | static int bfs_statfs(struct super_block *s, struct kstatfs *buf) | 206 | static int bfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
207 | { | 207 | { |
208 | struct super_block *s = dentry->d_sb; | ||
208 | struct bfs_sb_info *info = BFS_SB(s); | 209 | struct bfs_sb_info *info = BFS_SB(s); |
209 | u64 id = huge_encode_dev(s->s_bdev->bd_dev); | 210 | u64 id = huge_encode_dev(s->s_bdev->bd_dev); |
210 | buf->f_type = BFS_MAGIC; | 211 | buf->f_type = BFS_MAGIC; |
@@ -410,10 +411,10 @@ out: | |||
410 | return -EINVAL; | 411 | return -EINVAL; |
411 | } | 412 | } |
412 | 413 | ||
413 | static struct super_block *bfs_get_sb(struct file_system_type *fs_type, | 414 | static int bfs_get_sb(struct file_system_type *fs_type, |
414 | int flags, const char *dev_name, void *data) | 415 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
415 | { | 416 | { |
416 | return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super); | 417 | return get_sb_bdev(fs_type, flags, dev_name, data, bfs_fill_super, mnt); |
417 | } | 418 | } |
418 | 419 | ||
419 | static struct file_system_type bfs_fs_type = { | 420 | static struct file_system_type bfs_fs_type = { |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 537893a16014..d0434406eaeb 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
@@ -38,15 +38,13 @@ | |||
38 | #include <linux/security.h> | 38 | #include <linux/security.h> |
39 | #include <linux/syscalls.h> | 39 | #include <linux/syscalls.h> |
40 | #include <linux/random.h> | 40 | #include <linux/random.h> |
41 | 41 | #include <linux/elf.h> | |
42 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
43 | #include <asm/param.h> | 43 | #include <asm/param.h> |
44 | #include <asm/page.h> | 44 | #include <asm/page.h> |
45 | 45 | ||
46 | #include <linux/elf.h> | 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
47 | 47 | static int load_elf_library(struct file *); | |
48 | static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs); | ||
49 | static int load_elf_library(struct file*); | ||
50 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); | 48 | static unsigned long elf_map (struct file *, unsigned long, struct elf_phdr *, int, int); |
51 | extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); | 49 | extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); |
52 | 50 | ||
@@ -59,15 +57,15 @@ extern int dump_fpu (struct pt_regs *, elf_fpregset_t *); | |||
59 | * don't even try. | 57 | * don't even try. |
60 | */ | 58 | */ |
61 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) | 59 | #if defined(USE_ELF_CORE_DUMP) && defined(CONFIG_ELF_CORE) |
62 | static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file); | 60 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file); |
63 | #else | 61 | #else |
64 | #define elf_core_dump NULL | 62 | #define elf_core_dump NULL |
65 | #endif | 63 | #endif |
66 | 64 | ||
67 | #if ELF_EXEC_PAGESIZE > PAGE_SIZE | 65 | #if ELF_EXEC_PAGESIZE > PAGE_SIZE |
68 | # define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE | 66 | #define ELF_MIN_ALIGN ELF_EXEC_PAGESIZE |
69 | #else | 67 | #else |
70 | # define ELF_MIN_ALIGN PAGE_SIZE | 68 | #define ELF_MIN_ALIGN PAGE_SIZE |
71 | #endif | 69 | #endif |
72 | 70 | ||
73 | #ifndef ELF_CORE_EFLAGS | 71 | #ifndef ELF_CORE_EFLAGS |
@@ -86,7 +84,7 @@ static struct linux_binfmt elf_format = { | |||
86 | .min_coredump = ELF_EXEC_PAGESIZE | 84 | .min_coredump = ELF_EXEC_PAGESIZE |
87 | }; | 85 | }; |
88 | 86 | ||
89 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) | 87 | #define BAD_ADDR(x) ((unsigned long)(x) > TASK_SIZE) |
90 | 88 | ||
91 | static int set_brk(unsigned long start, unsigned long end) | 89 | static int set_brk(unsigned long start, unsigned long end) |
92 | { | 90 | { |
@@ -104,13 +102,11 @@ static int set_brk(unsigned long start, unsigned long end) | |||
104 | return 0; | 102 | return 0; |
105 | } | 103 | } |
106 | 104 | ||
107 | |||
108 | /* We need to explicitly zero any fractional pages | 105 | /* We need to explicitly zero any fractional pages |
109 | after the data section (i.e. bss). This would | 106 | after the data section (i.e. bss). This would |
110 | contain the junk from the file that should not | 107 | contain the junk from the file that should not |
111 | be in memory */ | 108 | be in memory |
112 | 109 | */ | |
113 | |||
114 | static int padzero(unsigned long elf_bss) | 110 | static int padzero(unsigned long elf_bss) |
115 | { | 111 | { |
116 | unsigned long nbyte; | 112 | unsigned long nbyte; |
@@ -129,7 +125,9 @@ static int padzero(unsigned long elf_bss) | |||
129 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) | 125 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) + (items)) |
130 | #define STACK_ROUND(sp, items) \ | 126 | #define STACK_ROUND(sp, items) \ |
131 | ((15 + (unsigned long) ((sp) + (items))) &~ 15UL) | 127 | ((15 + (unsigned long) ((sp) + (items))) &~ 15UL) |
132 | #define STACK_ALLOC(sp, len) ({ elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; old_sp; }) | 128 | #define STACK_ALLOC(sp, len) ({ \ |
129 | elf_addr_t __user *old_sp = (elf_addr_t __user *)sp; sp += len; \ | ||
130 | old_sp; }) | ||
133 | #else | 131 | #else |
134 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) | 132 | #define STACK_ADD(sp, items) ((elf_addr_t __user *)(sp) - (items)) |
135 | #define STACK_ROUND(sp, items) \ | 133 | #define STACK_ROUND(sp, items) \ |
@@ -138,7 +136,7 @@ static int padzero(unsigned long elf_bss) | |||
138 | #endif | 136 | #endif |
139 | 137 | ||
140 | static int | 138 | static int |
141 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | 139 | create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, |
142 | int interp_aout, unsigned long load_addr, | 140 | int interp_aout, unsigned long load_addr, |
143 | unsigned long interp_load_addr) | 141 | unsigned long interp_load_addr) |
144 | { | 142 | { |
@@ -161,7 +159,6 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
161 | * for userspace to get any other way, in others (i386) it is | 159 | * for userspace to get any other way, in others (i386) it is |
162 | * merely difficult. | 160 | * merely difficult. |
163 | */ | 161 | */ |
164 | |||
165 | u_platform = NULL; | 162 | u_platform = NULL; |
166 | if (k_platform) { | 163 | if (k_platform) { |
167 | size_t len = strlen(k_platform) + 1; | 164 | size_t len = strlen(k_platform) + 1; |
@@ -171,7 +168,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
171 | * evictions by the processes running on the same package. One | 168 | * evictions by the processes running on the same package. One |
172 | * thing we can do is to shuffle the initial stack for them. | 169 | * thing we can do is to shuffle the initial stack for them. |
173 | */ | 170 | */ |
174 | 171 | ||
175 | p = arch_align_stack(p); | 172 | p = arch_align_stack(p); |
176 | 173 | ||
177 | u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); | 174 | u_platform = (elf_addr_t __user *)STACK_ALLOC(p, len); |
@@ -180,9 +177,12 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
180 | } | 177 | } |
181 | 178 | ||
182 | /* Create the ELF interpreter info */ | 179 | /* Create the ELF interpreter info */ |
183 | elf_info = (elf_addr_t *) current->mm->saved_auxv; | 180 | elf_info = (elf_addr_t *)current->mm->saved_auxv; |
184 | #define NEW_AUX_ENT(id, val) \ | 181 | #define NEW_AUX_ENT(id, val) \ |
185 | do { elf_info[ei_index++] = id; elf_info[ei_index++] = val; } while (0) | 182 | do { \ |
183 | elf_info[ei_index++] = id; \ | ||
184 | elf_info[ei_index++] = val; \ | ||
185 | } while (0) | ||
186 | 186 | ||
187 | #ifdef ARCH_DLINFO | 187 | #ifdef ARCH_DLINFO |
188 | /* | 188 | /* |
@@ -195,21 +195,22 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
195 | NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); | 195 | NEW_AUX_ENT(AT_PAGESZ, ELF_EXEC_PAGESIZE); |
196 | NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); | 196 | NEW_AUX_ENT(AT_CLKTCK, CLOCKS_PER_SEC); |
197 | NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); | 197 | NEW_AUX_ENT(AT_PHDR, load_addr + exec->e_phoff); |
198 | NEW_AUX_ENT(AT_PHENT, sizeof (struct elf_phdr)); | 198 | NEW_AUX_ENT(AT_PHENT, sizeof(struct elf_phdr)); |
199 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); | 199 | NEW_AUX_ENT(AT_PHNUM, exec->e_phnum); |
200 | NEW_AUX_ENT(AT_BASE, interp_load_addr); | 200 | NEW_AUX_ENT(AT_BASE, interp_load_addr); |
201 | NEW_AUX_ENT(AT_FLAGS, 0); | 201 | NEW_AUX_ENT(AT_FLAGS, 0); |
202 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); | 202 | NEW_AUX_ENT(AT_ENTRY, exec->e_entry); |
203 | NEW_AUX_ENT(AT_UID, (elf_addr_t) tsk->uid); | 203 | NEW_AUX_ENT(AT_UID, tsk->uid); |
204 | NEW_AUX_ENT(AT_EUID, (elf_addr_t) tsk->euid); | 204 | NEW_AUX_ENT(AT_EUID, tsk->euid); |
205 | NEW_AUX_ENT(AT_GID, (elf_addr_t) tsk->gid); | 205 | NEW_AUX_ENT(AT_GID, tsk->gid); |
206 | NEW_AUX_ENT(AT_EGID, (elf_addr_t) tsk->egid); | 206 | NEW_AUX_ENT(AT_EGID, tsk->egid); |
207 | NEW_AUX_ENT(AT_SECURE, (elf_addr_t) security_bprm_secureexec(bprm)); | 207 | NEW_AUX_ENT(AT_SECURE, security_bprm_secureexec(bprm)); |
208 | if (k_platform) { | 208 | if (k_platform) { |
209 | NEW_AUX_ENT(AT_PLATFORM, (elf_addr_t)(unsigned long)u_platform); | 209 | NEW_AUX_ENT(AT_PLATFORM, |
210 | (elf_addr_t)(unsigned long)u_platform); | ||
210 | } | 211 | } |
211 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { | 212 | if (bprm->interp_flags & BINPRM_FLAGS_EXECFD) { |
212 | NEW_AUX_ENT(AT_EXECFD, (elf_addr_t) bprm->interp_data); | 213 | NEW_AUX_ENT(AT_EXECFD, bprm->interp_data); |
213 | } | 214 | } |
214 | #undef NEW_AUX_ENT | 215 | #undef NEW_AUX_ENT |
215 | /* AT_NULL is zero; clear the rest too */ | 216 | /* AT_NULL is zero; clear the rest too */ |
@@ -232,7 +233,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
232 | /* Point sp at the lowest address on the stack */ | 233 | /* Point sp at the lowest address on the stack */ |
233 | #ifdef CONFIG_STACK_GROWSUP | 234 | #ifdef CONFIG_STACK_GROWSUP |
234 | sp = (elf_addr_t __user *)bprm->p - items - ei_index; | 235 | sp = (elf_addr_t __user *)bprm->p - items - ei_index; |
235 | bprm->exec = (unsigned long) sp; /* XXX: PARISC HACK */ | 236 | bprm->exec = (unsigned long)sp; /* XXX: PARISC HACK */ |
236 | #else | 237 | #else |
237 | sp = (elf_addr_t __user *)bprm->p; | 238 | sp = (elf_addr_t __user *)bprm->p; |
238 | #endif | 239 | #endif |
@@ -285,7 +286,7 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr * exec, | |||
285 | #ifndef elf_map | 286 | #ifndef elf_map |
286 | 287 | ||
287 | static unsigned long elf_map(struct file *filep, unsigned long addr, | 288 | static unsigned long elf_map(struct file *filep, unsigned long addr, |
288 | struct elf_phdr *eppnt, int prot, int type) | 289 | struct elf_phdr *eppnt, int prot, int type) |
289 | { | 290 | { |
290 | unsigned long map_addr; | 291 | unsigned long map_addr; |
291 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); | 292 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); |
@@ -310,9 +311,8 @@ static unsigned long elf_map(struct file *filep, unsigned long addr, | |||
310 | is only provided so that we can read a.out libraries that have | 311 | is only provided so that we can read a.out libraries that have |
311 | an ELF header */ | 312 | an ELF header */ |
312 | 313 | ||
313 | static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | 314 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, |
314 | struct file * interpreter, | 315 | struct file *interpreter, unsigned long *interp_load_addr) |
315 | unsigned long *interp_load_addr) | ||
316 | { | 316 | { |
317 | struct elf_phdr *elf_phdata; | 317 | struct elf_phdr *elf_phdata; |
318 | struct elf_phdr *eppnt; | 318 | struct elf_phdr *eppnt; |
@@ -342,15 +342,15 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
342 | goto out; | 342 | goto out; |
343 | 343 | ||
344 | /* Now read in all of the header information */ | 344 | /* Now read in all of the header information */ |
345 | |||
346 | size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; | 345 | size = sizeof(struct elf_phdr) * interp_elf_ex->e_phnum; |
347 | if (size > ELF_MIN_ALIGN) | 346 | if (size > ELF_MIN_ALIGN) |
348 | goto out; | 347 | goto out; |
349 | elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); | 348 | elf_phdata = kmalloc(size, GFP_KERNEL); |
350 | if (!elf_phdata) | 349 | if (!elf_phdata) |
351 | goto out; | 350 | goto out; |
352 | 351 | ||
353 | retval = kernel_read(interpreter,interp_elf_ex->e_phoff,(char *)elf_phdata,size); | 352 | retval = kernel_read(interpreter, interp_elf_ex->e_phoff, |
353 | (char *)elf_phdata,size); | ||
354 | error = -EIO; | 354 | error = -EIO; |
355 | if (retval != size) { | 355 | if (retval != size) { |
356 | if (retval < 0) | 356 | if (retval < 0) |
@@ -359,58 +359,65 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
359 | } | 359 | } |
360 | 360 | ||
361 | eppnt = elf_phdata; | 361 | eppnt = elf_phdata; |
362 | for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) { | 362 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
363 | if (eppnt->p_type == PT_LOAD) { | 363 | if (eppnt->p_type == PT_LOAD) { |
364 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; | 364 | int elf_type = MAP_PRIVATE | MAP_DENYWRITE; |
365 | int elf_prot = 0; | 365 | int elf_prot = 0; |
366 | unsigned long vaddr = 0; | 366 | unsigned long vaddr = 0; |
367 | unsigned long k, map_addr; | 367 | unsigned long k, map_addr; |
368 | 368 | ||
369 | if (eppnt->p_flags & PF_R) elf_prot = PROT_READ; | 369 | if (eppnt->p_flags & PF_R) |
370 | if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | 370 | elf_prot = PROT_READ; |
371 | if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | 371 | if (eppnt->p_flags & PF_W) |
372 | vaddr = eppnt->p_vaddr; | 372 | elf_prot |= PROT_WRITE; |
373 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 373 | if (eppnt->p_flags & PF_X) |
374 | elf_type |= MAP_FIXED; | 374 | elf_prot |= PROT_EXEC; |
375 | 375 | vaddr = eppnt->p_vaddr; | |
376 | map_addr = elf_map(interpreter, load_addr + vaddr, eppnt, elf_prot, elf_type); | 376 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
377 | error = map_addr; | 377 | elf_type |= MAP_FIXED; |
378 | if (BAD_ADDR(map_addr)) | 378 | |
379 | goto out_close; | 379 | map_addr = elf_map(interpreter, load_addr + vaddr, |
380 | 380 | eppnt, elf_prot, elf_type); | |
381 | if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) { | 381 | error = map_addr; |
382 | load_addr = map_addr - ELF_PAGESTART(vaddr); | 382 | if (BAD_ADDR(map_addr)) |
383 | load_addr_set = 1; | 383 | goto out_close; |
384 | } | 384 | |
385 | 385 | if (!load_addr_set && | |
386 | /* | 386 | interp_elf_ex->e_type == ET_DYN) { |
387 | * Check to see if the section's size will overflow the | 387 | load_addr = map_addr - ELF_PAGESTART(vaddr); |
388 | * allowed task size. Note that p_filesz must always be | 388 | load_addr_set = 1; |
389 | * <= p_memsize so it is only necessary to check p_memsz. | 389 | } |
390 | */ | 390 | |
391 | k = load_addr + eppnt->p_vaddr; | 391 | /* |
392 | if (k > TASK_SIZE || eppnt->p_filesz > eppnt->p_memsz || | 392 | * Check to see if the section's size will overflow the |
393 | eppnt->p_memsz > TASK_SIZE || TASK_SIZE - eppnt->p_memsz < k) { | 393 | * allowed task size. Note that p_filesz must always be |
394 | error = -ENOMEM; | 394 | * <= p_memsize so it's only necessary to check p_memsz. |
395 | goto out_close; | 395 | */ |
396 | } | 396 | k = load_addr + eppnt->p_vaddr; |
397 | 397 | if (k > TASK_SIZE || | |
398 | /* | 398 | eppnt->p_filesz > eppnt->p_memsz || |
399 | * Find the end of the file mapping for this phdr, and keep | 399 | eppnt->p_memsz > TASK_SIZE || |
400 | * track of the largest address we see for this. | 400 | TASK_SIZE - eppnt->p_memsz < k) { |
401 | */ | 401 | error = -ENOMEM; |
402 | k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; | 402 | goto out_close; |
403 | if (k > elf_bss) | 403 | } |
404 | elf_bss = k; | 404 | |
405 | 405 | /* | |
406 | /* | 406 | * Find the end of the file mapping for this phdr, and |
407 | * Do the same thing for the memory mapping - between | 407 | * keep track of the largest address we see for this. |
408 | * elf_bss and last_bss is the bss section. | 408 | */ |
409 | */ | 409 | k = load_addr + eppnt->p_vaddr + eppnt->p_filesz; |
410 | k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; | 410 | if (k > elf_bss) |
411 | if (k > last_bss) | 411 | elf_bss = k; |
412 | last_bss = k; | 412 | |
413 | } | 413 | /* |
414 | * Do the same thing for the memory mapping - between | ||
415 | * elf_bss and last_bss is the bss section. | ||
416 | */ | ||
417 | k = load_addr + eppnt->p_memsz + eppnt->p_vaddr; | ||
418 | if (k > last_bss) | ||
419 | last_bss = k; | ||
420 | } | ||
414 | } | 421 | } |
415 | 422 | ||
416 | /* | 423 | /* |
@@ -424,7 +431,8 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
424 | goto out_close; | 431 | goto out_close; |
425 | } | 432 | } |
426 | 433 | ||
427 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); /* What we have mapped so far */ | 434 | /* What we have mapped so far */ |
435 | elf_bss = ELF_PAGESTART(elf_bss + ELF_MIN_ALIGN - 1); | ||
428 | 436 | ||
429 | /* Map the last of the bss segment */ | 437 | /* Map the last of the bss segment */ |
430 | if (last_bss > elf_bss) { | 438 | if (last_bss > elf_bss) { |
@@ -436,7 +444,7 @@ static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, | |||
436 | } | 444 | } |
437 | 445 | ||
438 | *interp_load_addr = load_addr; | 446 | *interp_load_addr = load_addr; |
439 | error = ((unsigned long) interp_elf_ex->e_entry) + load_addr; | 447 | error = ((unsigned long)interp_elf_ex->e_entry) + load_addr; |
440 | 448 | ||
441 | out_close: | 449 | out_close: |
442 | kfree(elf_phdata); | 450 | kfree(elf_phdata); |
@@ -444,8 +452,8 @@ out: | |||
444 | return error; | 452 | return error; |
445 | } | 453 | } |
446 | 454 | ||
447 | static unsigned long load_aout_interp(struct exec * interp_ex, | 455 | static unsigned long load_aout_interp(struct exec *interp_ex, |
448 | struct file * interpreter) | 456 | struct file *interpreter) |
449 | { | 457 | { |
450 | unsigned long text_data, elf_entry = ~0UL; | 458 | unsigned long text_data, elf_entry = ~0UL; |
451 | char __user * addr; | 459 | char __user * addr; |
@@ -464,7 +472,7 @@ static unsigned long load_aout_interp(struct exec * interp_ex, | |||
464 | case ZMAGIC: | 472 | case ZMAGIC: |
465 | case QMAGIC: | 473 | case QMAGIC: |
466 | offset = N_TXTOFF(*interp_ex); | 474 | offset = N_TXTOFF(*interp_ex); |
467 | addr = (char __user *) N_TXTADDR(*interp_ex); | 475 | addr = (char __user *)N_TXTADDR(*interp_ex); |
468 | break; | 476 | break; |
469 | default: | 477 | default: |
470 | goto out; | 478 | goto out; |
@@ -480,7 +488,6 @@ static unsigned long load_aout_interp(struct exec * interp_ex, | |||
480 | flush_icache_range((unsigned long)addr, | 488 | flush_icache_range((unsigned long)addr, |
481 | (unsigned long)addr + text_data); | 489 | (unsigned long)addr + text_data); |
482 | 490 | ||
483 | |||
484 | down_write(¤t->mm->mmap_sem); | 491 | down_write(¤t->mm->mmap_sem); |
485 | do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), | 492 | do_brk(ELF_PAGESTART(text_data + ELF_MIN_ALIGN - 1), |
486 | interp_ex->a_bss); | 493 | interp_ex->a_bss); |
@@ -519,7 +526,7 @@ static unsigned long randomize_stack_top(unsigned long stack_top) | |||
519 | #endif | 526 | #endif |
520 | } | 527 | } |
521 | 528 | ||
522 | static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | 529 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) |
523 | { | 530 | { |
524 | struct file *interpreter = NULL; /* to shut gcc up */ | 531 | struct file *interpreter = NULL; /* to shut gcc up */ |
525 | unsigned long load_addr = 0, load_bias = 0; | 532 | unsigned long load_addr = 0, load_bias = 0; |
@@ -528,7 +535,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
528 | unsigned int interpreter_type = INTERPRETER_NONE; | 535 | unsigned int interpreter_type = INTERPRETER_NONE; |
529 | unsigned char ibcs2_interpreter = 0; | 536 | unsigned char ibcs2_interpreter = 0; |
530 | unsigned long error; | 537 | unsigned long error; |
531 | struct elf_phdr * elf_ppnt, *elf_phdata; | 538 | struct elf_phdr *elf_ppnt, *elf_phdata; |
532 | unsigned long elf_bss, elf_brk; | 539 | unsigned long elf_bss, elf_brk; |
533 | int elf_exec_fileno; | 540 | int elf_exec_fileno; |
534 | int retval, i; | 541 | int retval, i; |
@@ -553,7 +560,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
553 | } | 560 | } |
554 | 561 | ||
555 | /* Get the exec-header */ | 562 | /* Get the exec-header */ |
556 | loc->elf_ex = *((struct elfhdr *) bprm->buf); | 563 | loc->elf_ex = *((struct elfhdr *)bprm->buf); |
557 | 564 | ||
558 | retval = -ENOEXEC; | 565 | retval = -ENOEXEC; |
559 | /* First of all, some simple consistency checks */ | 566 | /* First of all, some simple consistency checks */ |
@@ -568,7 +575,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
568 | goto out; | 575 | goto out; |
569 | 576 | ||
570 | /* Now read in all of the header information */ | 577 | /* Now read in all of the header information */ |
571 | |||
572 | if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) | 578 | if (loc->elf_ex.e_phentsize != sizeof(struct elf_phdr)) |
573 | goto out; | 579 | goto out; |
574 | if (loc->elf_ex.e_phnum < 1 || | 580 | if (loc->elf_ex.e_phnum < 1 || |
@@ -576,18 +582,19 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
576 | goto out; | 582 | goto out; |
577 | size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); | 583 | size = loc->elf_ex.e_phnum * sizeof(struct elf_phdr); |
578 | retval = -ENOMEM; | 584 | retval = -ENOMEM; |
579 | elf_phdata = (struct elf_phdr *) kmalloc(size, GFP_KERNEL); | 585 | elf_phdata = kmalloc(size, GFP_KERNEL); |
580 | if (!elf_phdata) | 586 | if (!elf_phdata) |
581 | goto out; | 587 | goto out; |
582 | 588 | ||
583 | retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, (char *) elf_phdata, size); | 589 | retval = kernel_read(bprm->file, loc->elf_ex.e_phoff, |
590 | (char *)elf_phdata, size); | ||
584 | if (retval != size) { | 591 | if (retval != size) { |
585 | if (retval >= 0) | 592 | if (retval >= 0) |
586 | retval = -EIO; | 593 | retval = -EIO; |
587 | goto out_free_ph; | 594 | goto out_free_ph; |
588 | } | 595 | } |
589 | 596 | ||
590 | files = current->files; /* Refcounted so ok */ | 597 | files = current->files; /* Refcounted so ok */ |
591 | retval = unshare_files(); | 598 | retval = unshare_files(); |
592 | if (retval < 0) | 599 | if (retval < 0) |
593 | goto out_free_ph; | 600 | goto out_free_ph; |
@@ -598,7 +605,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
598 | 605 | ||
599 | /* exec will make our files private anyway, but for the a.out | 606 | /* exec will make our files private anyway, but for the a.out |
600 | loader stuff we need to do it earlier */ | 607 | loader stuff we need to do it earlier */ |
601 | |||
602 | retval = get_unused_fd(); | 608 | retval = get_unused_fd(); |
603 | if (retval < 0) | 609 | if (retval < 0) |
604 | goto out_free_fh; | 610 | goto out_free_fh; |
@@ -620,7 +626,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
620 | * shared libraries - for now assume that this | 626 | * shared libraries - for now assume that this |
621 | * is an a.out format binary | 627 | * is an a.out format binary |
622 | */ | 628 | */ |
623 | |||
624 | retval = -ENOEXEC; | 629 | retval = -ENOEXEC; |
625 | if (elf_ppnt->p_filesz > PATH_MAX || | 630 | if (elf_ppnt->p_filesz > PATH_MAX || |
626 | elf_ppnt->p_filesz < 2) | 631 | elf_ppnt->p_filesz < 2) |
@@ -628,13 +633,13 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
628 | 633 | ||
629 | retval = -ENOMEM; | 634 | retval = -ENOMEM; |
630 | elf_interpreter = kmalloc(elf_ppnt->p_filesz, | 635 | elf_interpreter = kmalloc(elf_ppnt->p_filesz, |
631 | GFP_KERNEL); | 636 | GFP_KERNEL); |
632 | if (!elf_interpreter) | 637 | if (!elf_interpreter) |
633 | goto out_free_file; | 638 | goto out_free_file; |
634 | 639 | ||
635 | retval = kernel_read(bprm->file, elf_ppnt->p_offset, | 640 | retval = kernel_read(bprm->file, elf_ppnt->p_offset, |
636 | elf_interpreter, | 641 | elf_interpreter, |
637 | elf_ppnt->p_filesz); | 642 | elf_ppnt->p_filesz); |
638 | if (retval != elf_ppnt->p_filesz) { | 643 | if (retval != elf_ppnt->p_filesz) { |
639 | if (retval >= 0) | 644 | if (retval >= 0) |
640 | retval = -EIO; | 645 | retval = -EIO; |
@@ -678,7 +683,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
678 | retval = PTR_ERR(interpreter); | 683 | retval = PTR_ERR(interpreter); |
679 | if (IS_ERR(interpreter)) | 684 | if (IS_ERR(interpreter)) |
680 | goto out_free_interp; | 685 | goto out_free_interp; |
681 | retval = kernel_read(interpreter, 0, bprm->buf, BINPRM_BUF_SIZE); | 686 | retval = kernel_read(interpreter, 0, bprm->buf, |
687 | BINPRM_BUF_SIZE); | ||
682 | if (retval != BINPRM_BUF_SIZE) { | 688 | if (retval != BINPRM_BUF_SIZE) { |
683 | if (retval >= 0) | 689 | if (retval >= 0) |
684 | retval = -EIO; | 690 | retval = -EIO; |
@@ -686,8 +692,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
686 | } | 692 | } |
687 | 693 | ||
688 | /* Get the exec headers */ | 694 | /* Get the exec headers */ |
689 | loc->interp_ex = *((struct exec *) bprm->buf); | 695 | loc->interp_ex = *((struct exec *)bprm->buf); |
690 | loc->interp_elf_ex = *((struct elfhdr *) bprm->buf); | 696 | loc->interp_elf_ex = *((struct elfhdr *)bprm->buf); |
691 | break; | 697 | break; |
692 | } | 698 | } |
693 | elf_ppnt++; | 699 | elf_ppnt++; |
@@ -739,7 +745,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
739 | 745 | ||
740 | /* OK, we are done with that, now set up the arg stuff, | 746 | /* OK, we are done with that, now set up the arg stuff, |
741 | and then start this sucker up */ | 747 | and then start this sucker up */ |
742 | |||
743 | if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { | 748 | if ((!bprm->sh_bang) && (interpreter_type == INTERPRETER_AOUT)) { |
744 | char *passed_p = passed_fileno; | 749 | char *passed_p = passed_fileno; |
745 | sprintf(passed_fileno, "%d", elf_exec_fileno); | 750 | sprintf(passed_fileno, "%d", elf_exec_fileno); |
@@ -759,7 +764,6 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
759 | 764 | ||
760 | /* Discard our unneeded old files struct */ | 765 | /* Discard our unneeded old files struct */ |
761 | if (files) { | 766 | if (files) { |
762 | steal_locks(files); | ||
763 | put_files_struct(files); | 767 | put_files_struct(files); |
764 | files = NULL; | 768 | files = NULL; |
765 | } | 769 | } |
@@ -778,7 +782,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
778 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) | 782 | if (elf_read_implies_exec(loc->elf_ex, executable_stack)) |
779 | current->personality |= READ_IMPLIES_EXEC; | 783 | current->personality |= READ_IMPLIES_EXEC; |
780 | 784 | ||
781 | if ( !(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) | 785 | if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) |
782 | current->flags |= PF_RANDOMIZE; | 786 | current->flags |= PF_RANDOMIZE; |
783 | arch_pick_mmap_layout(current->mm); | 787 | arch_pick_mmap_layout(current->mm); |
784 | 788 | ||
@@ -799,8 +803,8 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
799 | the correct location in memory. At this point, we assume that | 803 | the correct location in memory. At this point, we assume that |
800 | the image should be loaded at fixed address, not at a variable | 804 | the image should be loaded at fixed address, not at a variable |
801 | address. */ | 805 | address. */ |
802 | 806 | for(i = 0, elf_ppnt = elf_phdata; | |
803 | for(i = 0, elf_ppnt = elf_phdata; i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 807 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { |
804 | int elf_prot = 0, elf_flags; | 808 | int elf_prot = 0, elf_flags; |
805 | unsigned long k, vaddr; | 809 | unsigned long k, vaddr; |
806 | 810 | ||
@@ -828,30 +832,35 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
828 | load_bias, nbyte)) { | 832 | load_bias, nbyte)) { |
829 | /* | 833 | /* |
830 | * This bss-zeroing can fail if the ELF | 834 | * This bss-zeroing can fail if the ELF |
831 | * file specifies odd protections. So | 835 | * file specifies odd protections. So |
832 | * we don't check the return value | 836 | * we don't check the return value |
833 | */ | 837 | */ |
834 | } | 838 | } |
835 | } | 839 | } |
836 | } | 840 | } |
837 | 841 | ||
838 | if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; | 842 | if (elf_ppnt->p_flags & PF_R) |
839 | if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; | 843 | elf_prot |= PROT_READ; |
840 | if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; | 844 | if (elf_ppnt->p_flags & PF_W) |
845 | elf_prot |= PROT_WRITE; | ||
846 | if (elf_ppnt->p_flags & PF_X) | ||
847 | elf_prot |= PROT_EXEC; | ||
841 | 848 | ||
842 | elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE; | 849 | elf_flags = MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE; |
843 | 850 | ||
844 | vaddr = elf_ppnt->p_vaddr; | 851 | vaddr = elf_ppnt->p_vaddr; |
845 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { | 852 | if (loc->elf_ex.e_type == ET_EXEC || load_addr_set) { |
846 | elf_flags |= MAP_FIXED; | 853 | elf_flags |= MAP_FIXED; |
847 | } else if (loc->elf_ex.e_type == ET_DYN) { | 854 | } else if (loc->elf_ex.e_type == ET_DYN) { |
848 | /* Try and get dynamic programs out of the way of the default mmap | 855 | /* Try and get dynamic programs out of the way of the |
849 | base, as well as whatever program they might try to exec. This | 856 | * default mmap base, as well as whatever program they |
850 | is because the brk will follow the loader, and is not movable. */ | 857 | * might try to exec. This is because the brk will |
858 | * follow the loader, and is not movable. */ | ||
851 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | 859 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); |
852 | } | 860 | } |
853 | 861 | ||
854 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, elf_prot, elf_flags); | 862 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, |
863 | elf_prot, elf_flags); | ||
855 | if (BAD_ADDR(error)) { | 864 | if (BAD_ADDR(error)) { |
856 | send_sig(SIGKILL, current, 0); | 865 | send_sig(SIGKILL, current, 0); |
857 | goto out_free_dentry; | 866 | goto out_free_dentry; |
@@ -868,8 +877,10 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
868 | } | 877 | } |
869 | } | 878 | } |
870 | k = elf_ppnt->p_vaddr; | 879 | k = elf_ppnt->p_vaddr; |
871 | if (k < start_code) start_code = k; | 880 | if (k < start_code) |
872 | if (start_data < k) start_data = k; | 881 | start_code = k; |
882 | if (start_data < k) | ||
883 | start_data = k; | ||
873 | 884 | ||
874 | /* | 885 | /* |
875 | * Check to see if the section's size will overflow the | 886 | * Check to see if the section's size will overflow the |
@@ -879,7 +890,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
879 | if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || | 890 | if (k > TASK_SIZE || elf_ppnt->p_filesz > elf_ppnt->p_memsz || |
880 | elf_ppnt->p_memsz > TASK_SIZE || | 891 | elf_ppnt->p_memsz > TASK_SIZE || |
881 | TASK_SIZE - elf_ppnt->p_memsz < k) { | 892 | TASK_SIZE - elf_ppnt->p_memsz < k) { |
882 | /* set_brk can never work. Avoid overflows. */ | 893 | /* set_brk can never work. Avoid overflows. */ |
883 | send_sig(SIGKILL, current, 0); | 894 | send_sig(SIGKILL, current, 0); |
884 | goto out_free_dentry; | 895 | goto out_free_dentry; |
885 | } | 896 | } |
@@ -967,8 +978,9 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
967 | 978 | ||
968 | compute_creds(bprm); | 979 | compute_creds(bprm); |
969 | current->flags &= ~PF_FORKNOEXEC; | 980 | current->flags &= ~PF_FORKNOEXEC; |
970 | create_elf_tables(bprm, &loc->elf_ex, (interpreter_type == INTERPRETER_AOUT), | 981 | create_elf_tables(bprm, &loc->elf_ex, |
971 | load_addr, interp_load_addr); | 982 | (interpreter_type == INTERPRETER_AOUT), |
983 | load_addr, interp_load_addr); | ||
972 | /* N.B. passed_fileno might not be initialized? */ | 984 | /* N.B. passed_fileno might not be initialized? */ |
973 | if (interpreter_type == INTERPRETER_AOUT) | 985 | if (interpreter_type == INTERPRETER_AOUT) |
974 | current->mm->arg_start += strlen(passed_fileno) + 1; | 986 | current->mm->arg_start += strlen(passed_fileno) + 1; |
@@ -982,7 +994,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs) | |||
982 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, | 994 | /* Why this, you ask??? Well SVr4 maps page 0 as read-only, |
983 | and some applications "depend" upon this behavior. | 995 | and some applications "depend" upon this behavior. |
984 | Since we do not have the power to recompile these, we | 996 | Since we do not have the power to recompile these, we |
985 | emulate the SVr4 behavior. Sigh. */ | 997 | emulate the SVr4 behavior. Sigh. */ |
986 | down_write(¤t->mm->mmap_sem); | 998 | down_write(¤t->mm->mmap_sem); |
987 | error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, | 999 | error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC, |
988 | MAP_FIXED | MAP_PRIVATE, 0); | 1000 | MAP_FIXED | MAP_PRIVATE, 0); |
@@ -1037,7 +1049,6 @@ out_free_ph: | |||
1037 | 1049 | ||
1038 | /* This is really simpleminded and specialized - we are loading an | 1050 | /* This is really simpleminded and specialized - we are loading an |
1039 | a.out library that is given an ELF header. */ | 1051 | a.out library that is given an ELF header. */ |
1040 | |||
1041 | static int load_elf_library(struct file *file) | 1052 | static int load_elf_library(struct file *file) |
1042 | { | 1053 | { |
1043 | struct elf_phdr *elf_phdata; | 1054 | struct elf_phdr *elf_phdata; |
@@ -1047,7 +1058,7 @@ static int load_elf_library(struct file *file) | |||
1047 | struct elfhdr elf_ex; | 1058 | struct elfhdr elf_ex; |
1048 | 1059 | ||
1049 | error = -ENOEXEC; | 1060 | error = -ENOEXEC; |
1050 | retval = kernel_read(file, 0, (char *) &elf_ex, sizeof(elf_ex)); | 1061 | retval = kernel_read(file, 0, (char *)&elf_ex, sizeof(elf_ex)); |
1051 | if (retval != sizeof(elf_ex)) | 1062 | if (retval != sizeof(elf_ex)) |
1052 | goto out; | 1063 | goto out; |
1053 | 1064 | ||
@@ -1056,7 +1067,7 @@ static int load_elf_library(struct file *file) | |||
1056 | 1067 | ||
1057 | /* First of all, some simple consistency checks */ | 1068 | /* First of all, some simple consistency checks */ |
1058 | if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || | 1069 | if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 || |
1059 | !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) | 1070 | !elf_check_arch(&elf_ex) || !file->f_op || !file->f_op->mmap) |
1060 | goto out; | 1071 | goto out; |
1061 | 1072 | ||
1062 | /* Now read in all of the header information */ | 1073 | /* Now read in all of the header information */ |
@@ -1104,7 +1115,8 @@ static int load_elf_library(struct file *file) | |||
1104 | goto out_free_ph; | 1115 | goto out_free_ph; |
1105 | } | 1116 | } |
1106 | 1117 | ||
1107 | len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + ELF_MIN_ALIGN - 1); | 1118 | len = ELF_PAGESTART(eppnt->p_filesz + eppnt->p_vaddr + |
1119 | ELF_MIN_ALIGN - 1); | ||
1108 | bss = eppnt->p_memsz + eppnt->p_vaddr; | 1120 | bss = eppnt->p_memsz + eppnt->p_vaddr; |
1109 | if (bss > len) { | 1121 | if (bss > len) { |
1110 | down_write(¤t->mm->mmap_sem); | 1122 | down_write(¤t->mm->mmap_sem); |
@@ -1163,7 +1175,7 @@ static int maydump(struct vm_area_struct *vma) | |||
1163 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) | 1175 | if (vma->vm_flags & (VM_IO | VM_RESERVED)) |
1164 | return 0; | 1176 | return 0; |
1165 | 1177 | ||
1166 | /* Dump shared memory only if mapped from an anonymous file. */ | 1178 | /* Dump shared memory only if mapped from an anonymous file. */ |
1167 | if (vma->vm_flags & VM_SHARED) | 1179 | if (vma->vm_flags & VM_SHARED) |
1168 | return vma->vm_file->f_dentry->d_inode->i_nlink == 0; | 1180 | return vma->vm_file->f_dentry->d_inode->i_nlink == 0; |
1169 | 1181 | ||
@@ -1174,7 +1186,7 @@ static int maydump(struct vm_area_struct *vma) | |||
1174 | return 1; | 1186 | return 1; |
1175 | } | 1187 | } |
1176 | 1188 | ||
1177 | #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) | 1189 | #define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) |
1178 | 1190 | ||
1179 | /* An ELF note in memory */ | 1191 | /* An ELF note in memory */ |
1180 | struct memelfnote | 1192 | struct memelfnote |
@@ -1277,11 +1289,11 @@ static void fill_note(struct memelfnote *note, const char *name, int type, | |||
1277 | } | 1289 | } |
1278 | 1290 | ||
1279 | /* | 1291 | /* |
1280 | * fill up all the fields in prstatus from the given task struct, except registers | 1292 | * fill up all the fields in prstatus from the given task struct, except |
1281 | * which need to be filled up separately. | 1293 | * registers which need to be filled up separately. |
1282 | */ | 1294 | */ |
1283 | static void fill_prstatus(struct elf_prstatus *prstatus, | 1295 | static void fill_prstatus(struct elf_prstatus *prstatus, |
1284 | struct task_struct *p, long signr) | 1296 | struct task_struct *p, long signr) |
1285 | { | 1297 | { |
1286 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; | 1298 | prstatus->pr_info.si_signo = prstatus->pr_cursig = signr; |
1287 | prstatus->pr_sigpend = p->pending.signal.sig[0]; | 1299 | prstatus->pr_sigpend = p->pending.signal.sig[0]; |
@@ -1366,8 +1378,8 @@ struct elf_thread_status | |||
1366 | 1378 | ||
1367 | /* | 1379 | /* |
1368 | * In order to add the specific thread information for the elf file format, | 1380 | * In order to add the specific thread information for the elf file format, |
1369 | * we need to keep a linked list of every threads pr_status and then | 1381 | * we need to keep a linked list of every threads pr_status and then create |
1370 | * create a single section for them in the final core file. | 1382 | * a single section for them in the final core file. |
1371 | */ | 1383 | */ |
1372 | static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | 1384 | static int elf_dump_thread_status(long signr, struct elf_thread_status *t) |
1373 | { | 1385 | { |
@@ -1378,19 +1390,23 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1378 | fill_prstatus(&t->prstatus, p, signr); | 1390 | fill_prstatus(&t->prstatus, p, signr); |
1379 | elf_core_copy_task_regs(p, &t->prstatus.pr_reg); | 1391 | elf_core_copy_task_regs(p, &t->prstatus.pr_reg); |
1380 | 1392 | ||
1381 | fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), &(t->prstatus)); | 1393 | fill_note(&t->notes[0], "CORE", NT_PRSTATUS, sizeof(t->prstatus), |
1394 | &(t->prstatus)); | ||
1382 | t->num_notes++; | 1395 | t->num_notes++; |
1383 | sz += notesize(&t->notes[0]); | 1396 | sz += notesize(&t->notes[0]); |
1384 | 1397 | ||
1385 | if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, &t->fpu))) { | 1398 | if ((t->prstatus.pr_fpvalid = elf_core_copy_task_fpregs(p, NULL, |
1386 | fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), &(t->fpu)); | 1399 | &t->fpu))) { |
1400 | fill_note(&t->notes[1], "CORE", NT_PRFPREG, sizeof(t->fpu), | ||
1401 | &(t->fpu)); | ||
1387 | t->num_notes++; | 1402 | t->num_notes++; |
1388 | sz += notesize(&t->notes[1]); | 1403 | sz += notesize(&t->notes[1]); |
1389 | } | 1404 | } |
1390 | 1405 | ||
1391 | #ifdef ELF_CORE_COPY_XFPREGS | 1406 | #ifdef ELF_CORE_COPY_XFPREGS |
1392 | if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { | 1407 | if (elf_core_copy_task_xfpregs(p, &t->xfpu)) { |
1393 | fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), &t->xfpu); | 1408 | fill_note(&t->notes[2], "LINUX", NT_PRXFPREG, sizeof(t->xfpu), |
1409 | &t->xfpu); | ||
1394 | t->num_notes++; | 1410 | t->num_notes++; |
1395 | sz += notesize(&t->notes[2]); | 1411 | sz += notesize(&t->notes[2]); |
1396 | } | 1412 | } |
@@ -1405,7 +1421,7 @@ static int elf_dump_thread_status(long signr, struct elf_thread_status *t) | |||
1405 | * and then they are actually written out. If we run out of core limit | 1421 | * and then they are actually written out. If we run out of core limit |
1406 | * we just truncate. | 1422 | * we just truncate. |
1407 | */ | 1423 | */ |
1408 | static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | 1424 | static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file) |
1409 | { | 1425 | { |
1410 | #define NUM_NOTES 6 | 1426 | #define NUM_NOTES 6 |
1411 | int has_dumped = 0; | 1427 | int has_dumped = 0; |
@@ -1434,12 +1450,12 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1434 | /* | 1450 | /* |
1435 | * We no longer stop all VM operations. | 1451 | * We no longer stop all VM operations. |
1436 | * | 1452 | * |
1437 | * This is because those proceses that could possibly change map_count or | 1453 | * This is because those proceses that could possibly change map_count |
1438 | * the mmap / vma pages are now blocked in do_exit on current finishing | 1454 | * or the mmap / vma pages are now blocked in do_exit on current |
1439 | * this core dump. | 1455 | * finishing this core dump. |
1440 | * | 1456 | * |
1441 | * Only ptrace can touch these memory addresses, but it doesn't change | 1457 | * Only ptrace can touch these memory addresses, but it doesn't change |
1442 | * the map_count or the pages allocated. So no possibility of crashing | 1458 | * the map_count or the pages allocated. So no possibility of crashing |
1443 | * exists while dumping the mm->vm_next areas to the core file. | 1459 | * exists while dumping the mm->vm_next areas to the core file. |
1444 | */ | 1460 | */ |
1445 | 1461 | ||
@@ -1501,7 +1517,7 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1501 | #endif | 1517 | #endif |
1502 | 1518 | ||
1503 | /* Set up header */ | 1519 | /* Set up header */ |
1504 | fill_elf_header(elf, segs+1); /* including notes section */ | 1520 | fill_elf_header(elf, segs + 1); /* including notes section */ |
1505 | 1521 | ||
1506 | has_dumped = 1; | 1522 | has_dumped = 1; |
1507 | current->flags |= PF_DUMPCORE; | 1523 | current->flags |= PF_DUMPCORE; |
@@ -1511,24 +1527,24 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1511 | * with info from their /proc. | 1527 | * with info from their /proc. |
1512 | */ | 1528 | */ |
1513 | 1529 | ||
1514 | fill_note(notes +0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); | 1530 | fill_note(notes + 0, "CORE", NT_PRSTATUS, sizeof(*prstatus), prstatus); |
1515 | |||
1516 | fill_psinfo(psinfo, current->group_leader, current->mm); | 1531 | fill_psinfo(psinfo, current->group_leader, current->mm); |
1517 | fill_note(notes +1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); | 1532 | fill_note(notes + 1, "CORE", NT_PRPSINFO, sizeof(*psinfo), psinfo); |
1518 | 1533 | ||
1519 | numnote = 2; | 1534 | numnote = 2; |
1520 | 1535 | ||
1521 | auxv = (elf_addr_t *) current->mm->saved_auxv; | 1536 | auxv = (elf_addr_t *)current->mm->saved_auxv; |
1522 | 1537 | ||
1523 | i = 0; | 1538 | i = 0; |
1524 | do | 1539 | do |
1525 | i += 2; | 1540 | i += 2; |
1526 | while (auxv[i - 2] != AT_NULL); | 1541 | while (auxv[i - 2] != AT_NULL); |
1527 | fill_note(¬es[numnote++], "CORE", NT_AUXV, | 1542 | fill_note(¬es[numnote++], "CORE", NT_AUXV, |
1528 | i * sizeof (elf_addr_t), auxv); | 1543 | i * sizeof(elf_addr_t), auxv); |
1529 | 1544 | ||
1530 | /* Try to dump the FPU. */ | 1545 | /* Try to dump the FPU. */ |
1531 | if ((prstatus->pr_fpvalid = elf_core_copy_task_fpregs(current, regs, fpu))) | 1546 | if ((prstatus->pr_fpvalid = |
1547 | elf_core_copy_task_fpregs(current, regs, fpu))) | ||
1532 | fill_note(notes + numnote++, | 1548 | fill_note(notes + numnote++, |
1533 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); | 1549 | "CORE", NT_PRFPREG, sizeof(*fpu), fpu); |
1534 | #ifdef ELF_CORE_COPY_XFPREGS | 1550 | #ifdef ELF_CORE_COPY_XFPREGS |
@@ -1577,8 +1593,10 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1577 | phdr.p_memsz = sz; | 1593 | phdr.p_memsz = sz; |
1578 | offset += phdr.p_filesz; | 1594 | offset += phdr.p_filesz; |
1579 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; | 1595 | phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0; |
1580 | if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W; | 1596 | if (vma->vm_flags & VM_WRITE) |
1581 | if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X; | 1597 | phdr.p_flags |= PF_W; |
1598 | if (vma->vm_flags & VM_EXEC) | ||
1599 | phdr.p_flags |= PF_X; | ||
1582 | phdr.p_align = ELF_EXEC_PAGESIZE; | 1600 | phdr.p_align = ELF_EXEC_PAGESIZE; |
1583 | 1601 | ||
1584 | DUMP_WRITE(&phdr, sizeof(phdr)); | 1602 | DUMP_WRITE(&phdr, sizeof(phdr)); |
@@ -1595,7 +1613,9 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1595 | 1613 | ||
1596 | /* write out the thread status notes section */ | 1614 | /* write out the thread status notes section */ |
1597 | list_for_each(t, &thread_list) { | 1615 | list_for_each(t, &thread_list) { |
1598 | struct elf_thread_status *tmp = list_entry(t, struct elf_thread_status, list); | 1616 | struct elf_thread_status *tmp = |
1617 | list_entry(t, struct elf_thread_status, list); | ||
1618 | |||
1599 | for (i = 0; i < tmp->num_notes; i++) | 1619 | for (i = 0; i < tmp->num_notes; i++) |
1600 | if (!writenote(&tmp->notes[i], file)) | 1620 | if (!writenote(&tmp->notes[i], file)) |
1601 | goto end_coredump; | 1621 | goto end_coredump; |
@@ -1612,18 +1632,19 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1612 | for (addr = vma->vm_start; | 1632 | for (addr = vma->vm_start; |
1613 | addr < vma->vm_end; | 1633 | addr < vma->vm_end; |
1614 | addr += PAGE_SIZE) { | 1634 | addr += PAGE_SIZE) { |
1615 | struct page* page; | 1635 | struct page *page; |
1616 | struct vm_area_struct *vma; | 1636 | struct vm_area_struct *vma; |
1617 | 1637 | ||
1618 | if (get_user_pages(current, current->mm, addr, 1, 0, 1, | 1638 | if (get_user_pages(current, current->mm, addr, 1, 0, 1, |
1619 | &page, &vma) <= 0) { | 1639 | &page, &vma) <= 0) { |
1620 | DUMP_SEEK (file->f_pos + PAGE_SIZE); | 1640 | DUMP_SEEK(file->f_pos + PAGE_SIZE); |
1621 | } else { | 1641 | } else { |
1622 | if (page == ZERO_PAGE(addr)) { | 1642 | if (page == ZERO_PAGE(addr)) { |
1623 | DUMP_SEEK (file->f_pos + PAGE_SIZE); | 1643 | DUMP_SEEK(file->f_pos + PAGE_SIZE); |
1624 | } else { | 1644 | } else { |
1625 | void *kaddr; | 1645 | void *kaddr; |
1626 | flush_cache_page(vma, addr, page_to_pfn(page)); | 1646 | flush_cache_page(vma, addr, |
1647 | page_to_pfn(page)); | ||
1627 | kaddr = kmap(page); | 1648 | kaddr = kmap(page); |
1628 | if ((size += PAGE_SIZE) > limit || | 1649 | if ((size += PAGE_SIZE) > limit || |
1629 | !dump_write(file, kaddr, | 1650 | !dump_write(file, kaddr, |
@@ -1645,7 +1666,8 @@ static int elf_core_dump(long signr, struct pt_regs * regs, struct file * file) | |||
1645 | 1666 | ||
1646 | if ((off_t)file->f_pos != offset) { | 1667 | if ((off_t)file->f_pos != offset) { |
1647 | /* Sanity check */ | 1668 | /* Sanity check */ |
1648 | printk(KERN_WARNING "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", | 1669 | printk(KERN_WARNING |
1670 | "elf_core_dump: file->f_pos (%ld) != offset (%ld)\n", | ||
1649 | (off_t)file->f_pos, offset); | 1671 | (off_t)file->f_pos, offset); |
1650 | } | 1672 | } |
1651 | 1673 | ||
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c index a2e48c999c24..eba4e23b9ca0 100644 --- a/fs/binfmt_elf_fdpic.c +++ b/fs/binfmt_elf_fdpic.c | |||
@@ -435,9 +435,10 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
435 | struct elf_fdpic_params *interp_params) | 435 | struct elf_fdpic_params *interp_params) |
436 | { | 436 | { |
437 | unsigned long sp, csp, nitems; | 437 | unsigned long sp, csp, nitems; |
438 | elf_caddr_t *argv, *envp; | 438 | elf_caddr_t __user *argv, *envp; |
439 | size_t platform_len = 0, len; | 439 | size_t platform_len = 0, len; |
440 | char *k_platform, *u_platform, *p; | 440 | char *k_platform; |
441 | char __user *u_platform, *p; | ||
441 | long hwcap; | 442 | long hwcap; |
442 | int loop; | 443 | int loop; |
443 | 444 | ||
@@ -462,12 +463,11 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
462 | if (k_platform) { | 463 | if (k_platform) { |
463 | platform_len = strlen(k_platform) + 1; | 464 | platform_len = strlen(k_platform) + 1; |
464 | sp -= platform_len; | 465 | sp -= platform_len; |
466 | u_platform = (char __user *) sp; | ||
465 | if (__copy_to_user(u_platform, k_platform, platform_len) != 0) | 467 | if (__copy_to_user(u_platform, k_platform, platform_len) != 0) |
466 | return -EFAULT; | 468 | return -EFAULT; |
467 | } | 469 | } |
468 | 470 | ||
469 | u_platform = (char *) sp; | ||
470 | |||
471 | #if defined(__i386__) && defined(CONFIG_SMP) | 471 | #if defined(__i386__) && defined(CONFIG_SMP) |
472 | /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions | 472 | /* in some cases (e.g. Hyper-Threading), we want to avoid L1 evictions |
473 | * by the processes running on the same package. One thing we can do | 473 | * by the processes running on the same package. One thing we can do |
@@ -490,7 +490,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
490 | sp = (sp - len) & ~7UL; | 490 | sp = (sp - len) & ~7UL; |
491 | exec_params->map_addr = sp; | 491 | exec_params->map_addr = sp; |
492 | 492 | ||
493 | if (copy_to_user((void *) sp, exec_params->loadmap, len) != 0) | 493 | if (copy_to_user((void __user *) sp, exec_params->loadmap, len) != 0) |
494 | return -EFAULT; | 494 | return -EFAULT; |
495 | 495 | ||
496 | current->mm->context.exec_fdpic_loadmap = (unsigned long) sp; | 496 | current->mm->context.exec_fdpic_loadmap = (unsigned long) sp; |
@@ -501,7 +501,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
501 | sp = (sp - len) & ~7UL; | 501 | sp = (sp - len) & ~7UL; |
502 | interp_params->map_addr = sp; | 502 | interp_params->map_addr = sp; |
503 | 503 | ||
504 | if (copy_to_user((void *) sp, interp_params->loadmap, len) != 0) | 504 | if (copy_to_user((void __user *) sp, interp_params->loadmap, len) != 0) |
505 | return -EFAULT; | 505 | return -EFAULT; |
506 | 506 | ||
507 | current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; | 507 | current->mm->context.interp_fdpic_loadmap = (unsigned long) sp; |
@@ -527,7 +527,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
527 | /* put the ELF interpreter info on the stack */ | 527 | /* put the ELF interpreter info on the stack */ |
528 | #define NEW_AUX_ENT(nr, id, val) \ | 528 | #define NEW_AUX_ENT(nr, id, val) \ |
529 | do { \ | 529 | do { \ |
530 | struct { unsigned long _id, _val; } *ent = (void *) csp; \ | 530 | struct { unsigned long _id, _val; } __user *ent = (void __user *) csp; \ |
531 | __put_user((id), &ent[nr]._id); \ | 531 | __put_user((id), &ent[nr]._id); \ |
532 | __put_user((val), &ent[nr]._val); \ | 532 | __put_user((val), &ent[nr]._val); \ |
533 | } while (0) | 533 | } while (0) |
@@ -564,13 +564,13 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
564 | 564 | ||
565 | /* allocate room for argv[] and envv[] */ | 565 | /* allocate room for argv[] and envv[] */ |
566 | csp -= (bprm->envc + 1) * sizeof(elf_caddr_t); | 566 | csp -= (bprm->envc + 1) * sizeof(elf_caddr_t); |
567 | envp = (elf_caddr_t *) csp; | 567 | envp = (elf_caddr_t __user *) csp; |
568 | csp -= (bprm->argc + 1) * sizeof(elf_caddr_t); | 568 | csp -= (bprm->argc + 1) * sizeof(elf_caddr_t); |
569 | argv = (elf_caddr_t *) csp; | 569 | argv = (elf_caddr_t __user *) csp; |
570 | 570 | ||
571 | /* stack argc */ | 571 | /* stack argc */ |
572 | csp -= sizeof(unsigned long); | 572 | csp -= sizeof(unsigned long); |
573 | __put_user(bprm->argc, (unsigned long *) csp); | 573 | __put_user(bprm->argc, (unsigned long __user *) csp); |
574 | 574 | ||
575 | BUG_ON(csp != sp); | 575 | BUG_ON(csp != sp); |
576 | 576 | ||
@@ -581,7 +581,7 @@ static int create_elf_fdpic_tables(struct linux_binprm *bprm, | |||
581 | current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); | 581 | current->mm->arg_start = current->mm->start_stack - (MAX_ARG_PAGES * PAGE_SIZE - bprm->p); |
582 | #endif | 582 | #endif |
583 | 583 | ||
584 | p = (char *) current->mm->arg_start; | 584 | p = (char __user *) current->mm->arg_start; |
585 | for (loop = bprm->argc; loop > 0; loop--) { | 585 | for (loop = bprm->argc; loop > 0; loop--) { |
586 | __put_user((elf_caddr_t) p, argv++); | 586 | __put_user((elf_caddr_t) p, argv++); |
587 | len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES); | 587 | len = strnlen_user(p, PAGE_SIZE * MAX_ARG_PAGES); |
@@ -1025,7 +1025,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, | |||
1025 | /* clear the bit between beginning of mapping and beginning of PT_LOAD */ | 1025 | /* clear the bit between beginning of mapping and beginning of PT_LOAD */ |
1026 | if (prot & PROT_WRITE && disp > 0) { | 1026 | if (prot & PROT_WRITE && disp > 0) { |
1027 | kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); | 1027 | kdebug("clear[%d] ad=%lx sz=%lx", loop, maddr, disp); |
1028 | clear_user((void *) maddr, disp); | 1028 | clear_user((void __user *) maddr, disp); |
1029 | maddr += disp; | 1029 | maddr += disp; |
1030 | } | 1030 | } |
1031 | 1031 | ||
@@ -1059,7 +1059,7 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params, | |||
1059 | if (prot & PROT_WRITE && excess1 > 0) { | 1059 | if (prot & PROT_WRITE && excess1 > 0) { |
1060 | kdebug("clear[%d] ad=%lx sz=%lx", | 1060 | kdebug("clear[%d] ad=%lx sz=%lx", |
1061 | loop, maddr + phdr->p_filesz, excess1); | 1061 | loop, maddr + phdr->p_filesz, excess1); |
1062 | clear_user((void *) maddr + phdr->p_filesz, excess1); | 1062 | clear_user((void __user *) maddr + phdr->p_filesz, excess1); |
1063 | } | 1063 | } |
1064 | 1064 | ||
1065 | #else | 1065 | #else |
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c index d73d75591a39..07a4996cca3f 100644 --- a/fs/binfmt_misc.c +++ b/fs/binfmt_misc.c | |||
@@ -203,7 +203,6 @@ static int load_misc_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
203 | goto _error; | 203 | goto _error; |
204 | 204 | ||
205 | if (files) { | 205 | if (files) { |
206 | steal_locks(files); | ||
207 | put_files_struct(files); | 206 | put_files_struct(files); |
208 | files = NULL; | 207 | files = NULL; |
209 | } | 208 | } |
@@ -740,10 +739,10 @@ static int bm_fill_super(struct super_block * sb, void * data, int silent) | |||
740 | return err; | 739 | return err; |
741 | } | 740 | } |
742 | 741 | ||
743 | static struct super_block *bm_get_sb(struct file_system_type *fs_type, | 742 | static int bm_get_sb(struct file_system_type *fs_type, |
744 | int flags, const char *dev_name, void *data) | 743 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
745 | { | 744 | { |
746 | return get_sb_single(fs_type, flags, data, bm_fill_super); | 745 | return get_sb_single(fs_type, flags, data, bm_fill_super, mnt); |
747 | } | 746 | } |
748 | 747 | ||
749 | static struct linux_binfmt misc_format = { | 748 | static struct linux_binfmt misc_format = { |
diff --git a/fs/block_dev.c b/fs/block_dev.c index f5958f413bd1..028d9fb9c2d5 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
@@ -300,10 +300,10 @@ static struct super_operations bdev_sops = { | |||
300 | .clear_inode = bdev_clear_inode, | 300 | .clear_inode = bdev_clear_inode, |
301 | }; | 301 | }; |
302 | 302 | ||
303 | static struct super_block *bd_get_sb(struct file_system_type *fs_type, | 303 | static int bd_get_sb(struct file_system_type *fs_type, |
304 | int flags, const char *dev_name, void *data) | 304 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
305 | { | 305 | { |
306 | return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576); | 306 | return get_sb_pseudo(fs_type, "bdev:", &bdev_sops, 0x62646576, mnt); |
307 | } | 307 | } |
308 | 308 | ||
309 | static struct file_system_type bd_type = { | 309 | static struct file_system_type bd_type = { |
@@ -414,21 +414,31 @@ EXPORT_SYMBOL(bdput); | |||
414 | static struct block_device *bd_acquire(struct inode *inode) | 414 | static struct block_device *bd_acquire(struct inode *inode) |
415 | { | 415 | { |
416 | struct block_device *bdev; | 416 | struct block_device *bdev; |
417 | |||
417 | spin_lock(&bdev_lock); | 418 | spin_lock(&bdev_lock); |
418 | bdev = inode->i_bdev; | 419 | bdev = inode->i_bdev; |
419 | if (bdev && igrab(bdev->bd_inode)) { | 420 | if (bdev) { |
421 | atomic_inc(&bdev->bd_inode->i_count); | ||
420 | spin_unlock(&bdev_lock); | 422 | spin_unlock(&bdev_lock); |
421 | return bdev; | 423 | return bdev; |
422 | } | 424 | } |
423 | spin_unlock(&bdev_lock); | 425 | spin_unlock(&bdev_lock); |
426 | |||
424 | bdev = bdget(inode->i_rdev); | 427 | bdev = bdget(inode->i_rdev); |
425 | if (bdev) { | 428 | if (bdev) { |
426 | spin_lock(&bdev_lock); | 429 | spin_lock(&bdev_lock); |
427 | if (inode->i_bdev) | 430 | if (!inode->i_bdev) { |
428 | __bd_forget(inode); | 431 | /* |
429 | inode->i_bdev = bdev; | 432 | * We take an additional bd_inode->i_count for inode, |
430 | inode->i_mapping = bdev->bd_inode->i_mapping; | 433 | * and it's released in clear_inode() of inode. |
431 | list_add(&inode->i_devices, &bdev->bd_inodes); | 434 | * So, we can access it via ->i_mapping always |
435 | * without igrab(). | ||
436 | */ | ||
437 | atomic_inc(&bdev->bd_inode->i_count); | ||
438 | inode->i_bdev = bdev; | ||
439 | inode->i_mapping = bdev->bd_inode->i_mapping; | ||
440 | list_add(&inode->i_devices, &bdev->bd_inodes); | ||
441 | } | ||
432 | spin_unlock(&bdev_lock); | 442 | spin_unlock(&bdev_lock); |
433 | } | 443 | } |
434 | return bdev; | 444 | return bdev; |
@@ -438,10 +448,18 @@ static struct block_device *bd_acquire(struct inode *inode) | |||
438 | 448 | ||
439 | void bd_forget(struct inode *inode) | 449 | void bd_forget(struct inode *inode) |
440 | { | 450 | { |
451 | struct block_device *bdev = NULL; | ||
452 | |||
441 | spin_lock(&bdev_lock); | 453 | spin_lock(&bdev_lock); |
442 | if (inode->i_bdev) | 454 | if (inode->i_bdev) { |
455 | if (inode->i_sb != blockdev_superblock) | ||
456 | bdev = inode->i_bdev; | ||
443 | __bd_forget(inode); | 457 | __bd_forget(inode); |
458 | } | ||
444 | spin_unlock(&bdev_lock); | 459 | spin_unlock(&bdev_lock); |
460 | |||
461 | if (bdev) | ||
462 | iput(bdev->bd_inode); | ||
445 | } | 463 | } |
446 | 464 | ||
447 | int bd_claim(struct block_device *bdev, void *holder) | 465 | int bd_claim(struct block_device *bdev, void *holder) |
diff --git a/fs/buffer.c b/fs/buffer.c index 23f1f3a68077..373bb6292bdc 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
@@ -331,7 +331,6 @@ long do_fsync(struct file *file, int datasync) | |||
331 | goto out; | 331 | goto out; |
332 | } | 332 | } |
333 | 333 | ||
334 | current->flags |= PF_SYNCWRITE; | ||
335 | ret = filemap_fdatawrite(mapping); | 334 | ret = filemap_fdatawrite(mapping); |
336 | 335 | ||
337 | /* | 336 | /* |
@@ -346,7 +345,6 @@ long do_fsync(struct file *file, int datasync) | |||
346 | err = filemap_fdatawait(mapping); | 345 | err = filemap_fdatawait(mapping); |
347 | if (!ret) | 346 | if (!ret) |
348 | ret = err; | 347 | ret = err; |
349 | current->flags &= ~PF_SYNCWRITE; | ||
350 | out: | 348 | out: |
351 | return ret; | 349 | return ret; |
352 | } | 350 | } |
diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index fb7c11c2c913..f2e285457bee 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c | |||
@@ -166,8 +166,9 @@ cifs_put_super(struct super_block *sb) | |||
166 | } | 166 | } |
167 | 167 | ||
168 | static int | 168 | static int |
169 | cifs_statfs(struct super_block *sb, struct kstatfs *buf) | 169 | cifs_statfs(struct dentry *dentry, struct kstatfs *buf) |
170 | { | 170 | { |
171 | struct super_block *sb = dentry->d_sb; | ||
171 | int xid; | 172 | int xid; |
172 | int rc = -EOPNOTSUPP; | 173 | int rc = -EOPNOTSUPP; |
173 | struct cifs_sb_info *cifs_sb; | 174 | struct cifs_sb_info *cifs_sb; |
@@ -460,9 +461,9 @@ struct super_operations cifs_super_ops = { | |||
460 | .remount_fs = cifs_remount, | 461 | .remount_fs = cifs_remount, |
461 | }; | 462 | }; |
462 | 463 | ||
463 | static struct super_block * | 464 | static int |
464 | cifs_get_sb(struct file_system_type *fs_type, | 465 | cifs_get_sb(struct file_system_type *fs_type, |
465 | int flags, const char *dev_name, void *data) | 466 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
466 | { | 467 | { |
467 | int rc; | 468 | int rc; |
468 | struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); | 469 | struct super_block *sb = sget(fs_type, NULL, set_anon_super, NULL); |
@@ -470,7 +471,7 @@ cifs_get_sb(struct file_system_type *fs_type, | |||
470 | cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); | 471 | cFYI(1, ("Devname: %s flags: %d ", dev_name, flags)); |
471 | 472 | ||
472 | if (IS_ERR(sb)) | 473 | if (IS_ERR(sb)) |
473 | return sb; | 474 | return PTR_ERR(sb); |
474 | 475 | ||
475 | sb->s_flags = flags; | 476 | sb->s_flags = flags; |
476 | 477 | ||
@@ -478,10 +479,10 @@ cifs_get_sb(struct file_system_type *fs_type, | |||
478 | if (rc) { | 479 | if (rc) { |
479 | up_write(&sb->s_umount); | 480 | up_write(&sb->s_umount); |
480 | deactivate_super(sb); | 481 | deactivate_super(sb); |
481 | return ERR_PTR(rc); | 482 | return rc; |
482 | } | 483 | } |
483 | sb->s_flags |= MS_ACTIVE; | 484 | sb->s_flags |= MS_ACTIVE; |
484 | return sb; | 485 | return simple_set_mnt(mnt, sb); |
485 | } | 486 | } |
486 | 487 | ||
487 | static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, | 488 | static ssize_t cifs_file_writev(struct file *file, const struct iovec *iov, |
diff --git a/fs/cifs/cifsfs.h b/fs/cifs/cifsfs.h index 3011df988bd5..a6384d83fdef 100644 --- a/fs/cifs/cifsfs.h +++ b/fs/cifs/cifsfs.h | |||
@@ -75,7 +75,7 @@ extern ssize_t cifs_user_write(struct file *file, const char __user *write_data, | |||
75 | size_t write_size, loff_t * poffset); | 75 | size_t write_size, loff_t * poffset); |
76 | extern int cifs_lock(struct file *, int, struct file_lock *); | 76 | extern int cifs_lock(struct file *, int, struct file_lock *); |
77 | extern int cifs_fsync(struct file *, struct dentry *, int); | 77 | extern int cifs_fsync(struct file *, struct dentry *, int); |
78 | extern int cifs_flush(struct file *); | 78 | extern int cifs_flush(struct file *, fl_owner_t id); |
79 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); | 79 | extern int cifs_file_mmap(struct file * , struct vm_area_struct *); |
80 | extern const struct file_operations cifs_dir_ops; | 80 | extern const struct file_operations cifs_dir_ops; |
81 | extern int cifs_dir_open(struct inode *inode, struct file *file); | 81 | extern int cifs_dir_open(struct inode *inode, struct file *file); |
diff --git a/fs/cifs/file.c b/fs/cifs/file.c index fafdcdffba62..616b140534be 100644 --- a/fs/cifs/file.c +++ b/fs/cifs/file.c | |||
@@ -1084,9 +1084,9 @@ static int cifs_writepages(struct address_space *mapping, | |||
1084 | unsigned int bytes_written; | 1084 | unsigned int bytes_written; |
1085 | struct cifs_sb_info *cifs_sb; | 1085 | struct cifs_sb_info *cifs_sb; |
1086 | int done = 0; | 1086 | int done = 0; |
1087 | pgoff_t end = -1; | 1087 | pgoff_t end; |
1088 | pgoff_t index; | 1088 | pgoff_t index; |
1089 | int is_range = 0; | 1089 | int range_whole = 0; |
1090 | struct kvec iov[32]; | 1090 | struct kvec iov[32]; |
1091 | int len; | 1091 | int len; |
1092 | int n_iov = 0; | 1092 | int n_iov = 0; |
@@ -1127,16 +1127,14 @@ static int cifs_writepages(struct address_space *mapping, | |||
1127 | xid = GetXid(); | 1127 | xid = GetXid(); |
1128 | 1128 | ||
1129 | pagevec_init(&pvec, 0); | 1129 | pagevec_init(&pvec, 0); |
1130 | if (wbc->sync_mode == WB_SYNC_NONE) | 1130 | if (wbc->range_cyclic) { |
1131 | index = mapping->writeback_index; /* Start from prev offset */ | 1131 | index = mapping->writeback_index; /* Start from prev offset */ |
1132 | else { | 1132 | end = -1; |
1133 | index = 0; | 1133 | } else { |
1134 | scanned = 1; | 1134 | index = wbc->range_start >> PAGE_CACHE_SHIFT; |
1135 | } | 1135 | end = wbc->range_end >> PAGE_CACHE_SHIFT; |
1136 | if (wbc->start || wbc->end) { | 1136 | if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) |
1137 | index = wbc->start >> PAGE_CACHE_SHIFT; | 1137 | range_whole = 1; |
1138 | end = wbc->end >> PAGE_CACHE_SHIFT; | ||
1139 | is_range = 1; | ||
1140 | scanned = 1; | 1138 | scanned = 1; |
1141 | } | 1139 | } |
1142 | retry: | 1140 | retry: |
@@ -1172,7 +1170,7 @@ retry: | |||
1172 | break; | 1170 | break; |
1173 | } | 1171 | } |
1174 | 1172 | ||
1175 | if (unlikely(is_range) && (page->index > end)) { | 1173 | if (!wbc->range_cyclic && page->index > end) { |
1176 | done = 1; | 1174 | done = 1; |
1177 | unlock_page(page); | 1175 | unlock_page(page); |
1178 | break; | 1176 | break; |
@@ -1276,7 +1274,7 @@ retry: | |||
1276 | index = 0; | 1274 | index = 0; |
1277 | goto retry; | 1275 | goto retry; |
1278 | } | 1276 | } |
1279 | if (!is_range) | 1277 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
1280 | mapping->writeback_index = index; | 1278 | mapping->writeback_index = index; |
1281 | 1279 | ||
1282 | FreeXid(xid); | 1280 | FreeXid(xid); |
@@ -1424,7 +1422,7 @@ int cifs_fsync(struct file *file, struct dentry *dentry, int datasync) | |||
1424 | * As file closes, flush all cached write data for this inode checking | 1422 | * As file closes, flush all cached write data for this inode checking |
1425 | * for write behind errors. | 1423 | * for write behind errors. |
1426 | */ | 1424 | */ |
1427 | int cifs_flush(struct file *file) | 1425 | int cifs_flush(struct file *file, fl_owner_t id) |
1428 | { | 1426 | { |
1429 | struct inode * inode = file->f_dentry->d_inode; | 1427 | struct inode * inode = file->f_dentry->d_inode; |
1430 | int rc = 0; | 1428 | int rc = 0; |
diff --git a/fs/coda/file.c b/fs/coda/file.c index 7c2642431fa5..cc66c681bd11 100644 --- a/fs/coda/file.c +++ b/fs/coda/file.c | |||
@@ -164,7 +164,7 @@ int coda_open(struct inode *coda_inode, struct file *coda_file) | |||
164 | return 0; | 164 | return 0; |
165 | } | 165 | } |
166 | 166 | ||
167 | int coda_flush(struct file *coda_file) | 167 | int coda_flush(struct file *coda_file, fl_owner_t id) |
168 | { | 168 | { |
169 | unsigned short flags = coda_file->f_flags & ~O_EXCL; | 169 | unsigned short flags = coda_file->f_flags & ~O_EXCL; |
170 | unsigned short coda_flags = coda_flags_to_cflags(flags); | 170 | unsigned short coda_flags = coda_flags_to_cflags(flags); |
diff --git a/fs/coda/inode.c b/fs/coda/inode.c index ada1a81df6bd..87f1dc8aa24b 100644 --- a/fs/coda/inode.c +++ b/fs/coda/inode.c | |||
@@ -36,7 +36,7 @@ | |||
36 | /* VFS super_block ops */ | 36 | /* VFS super_block ops */ |
37 | static void coda_clear_inode(struct inode *); | 37 | static void coda_clear_inode(struct inode *); |
38 | static void coda_put_super(struct super_block *); | 38 | static void coda_put_super(struct super_block *); |
39 | static int coda_statfs(struct super_block *sb, struct kstatfs *buf); | 39 | static int coda_statfs(struct dentry *dentry, struct kstatfs *buf); |
40 | 40 | ||
41 | static kmem_cache_t * coda_inode_cachep; | 41 | static kmem_cache_t * coda_inode_cachep; |
42 | 42 | ||
@@ -278,13 +278,13 @@ struct inode_operations coda_file_inode_operations = { | |||
278 | .setattr = coda_setattr, | 278 | .setattr = coda_setattr, |
279 | }; | 279 | }; |
280 | 280 | ||
281 | static int coda_statfs(struct super_block *sb, struct kstatfs *buf) | 281 | static int coda_statfs(struct dentry *dentry, struct kstatfs *buf) |
282 | { | 282 | { |
283 | int error; | 283 | int error; |
284 | 284 | ||
285 | lock_kernel(); | 285 | lock_kernel(); |
286 | 286 | ||
287 | error = venus_statfs(sb, buf); | 287 | error = venus_statfs(dentry, buf); |
288 | 288 | ||
289 | unlock_kernel(); | 289 | unlock_kernel(); |
290 | 290 | ||
@@ -307,10 +307,10 @@ static int coda_statfs(struct super_block *sb, struct kstatfs *buf) | |||
307 | 307 | ||
308 | /* init_coda: used by filesystems.c to register coda */ | 308 | /* init_coda: used by filesystems.c to register coda */ |
309 | 309 | ||
310 | static struct super_block *coda_get_sb(struct file_system_type *fs_type, | 310 | static int coda_get_sb(struct file_system_type *fs_type, |
311 | int flags, const char *dev_name, void *data) | 311 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
312 | { | 312 | { |
313 | return get_sb_nodev(fs_type, flags, data, coda_fill_super); | 313 | return get_sb_nodev(fs_type, flags, data, coda_fill_super, mnt); |
314 | } | 314 | } |
315 | 315 | ||
316 | struct file_system_type coda_fs_type = { | 316 | struct file_system_type coda_fs_type = { |
diff --git a/fs/coda/upcall.c b/fs/coda/upcall.c index 1bae99650a91..b040eba13a7d 100644 --- a/fs/coda/upcall.c +++ b/fs/coda/upcall.c | |||
@@ -611,7 +611,7 @@ int venus_pioctl(struct super_block *sb, struct CodaFid *fid, | |||
611 | return error; | 611 | return error; |
612 | } | 612 | } |
613 | 613 | ||
614 | int venus_statfs(struct super_block *sb, struct kstatfs *sfs) | 614 | int venus_statfs(struct dentry *dentry, struct kstatfs *sfs) |
615 | { | 615 | { |
616 | union inputArgs *inp; | 616 | union inputArgs *inp; |
617 | union outputArgs *outp; | 617 | union outputArgs *outp; |
@@ -620,7 +620,7 @@ int venus_statfs(struct super_block *sb, struct kstatfs *sfs) | |||
620 | insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); | 620 | insize = max_t(unsigned int, INSIZE(statfs), OUTSIZE(statfs)); |
621 | UPARG(CODA_STATFS); | 621 | UPARG(CODA_STATFS); |
622 | 622 | ||
623 | error = coda_upcall(coda_sbp(sb), insize, &outsize, inp); | 623 | error = coda_upcall(coda_sbp(dentry->d_sb), insize, &outsize, inp); |
624 | 624 | ||
625 | if (!error) { | 625 | if (!error) { |
626 | sfs->f_blocks = outp->coda_statfs.stat.f_blocks; | 626 | sfs->f_blocks = outp->coda_statfs.stat.f_blocks; |
diff --git a/fs/compat.c b/fs/compat.c index b1f64786a613..7e7e5bc4f3cf 100644 --- a/fs/compat.c +++ b/fs/compat.c | |||
@@ -197,7 +197,7 @@ asmlinkage long compat_sys_statfs(const char __user *path, struct compat_statfs | |||
197 | error = user_path_walk(path, &nd); | 197 | error = user_path_walk(path, &nd); |
198 | if (!error) { | 198 | if (!error) { |
199 | struct kstatfs tmp; | 199 | struct kstatfs tmp; |
200 | error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); | 200 | error = vfs_statfs(nd.dentry, &tmp); |
201 | if (!error) | 201 | if (!error) |
202 | error = put_compat_statfs(buf, &tmp); | 202 | error = put_compat_statfs(buf, &tmp); |
203 | path_release(&nd); | 203 | path_release(&nd); |
@@ -215,7 +215,7 @@ asmlinkage long compat_sys_fstatfs(unsigned int fd, struct compat_statfs __user | |||
215 | file = fget(fd); | 215 | file = fget(fd); |
216 | if (!file) | 216 | if (!file) |
217 | goto out; | 217 | goto out; |
218 | error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); | 218 | error = vfs_statfs(file->f_dentry, &tmp); |
219 | if (!error) | 219 | if (!error) |
220 | error = put_compat_statfs(buf, &tmp); | 220 | error = put_compat_statfs(buf, &tmp); |
221 | fput(file); | 221 | fput(file); |
@@ -265,7 +265,7 @@ asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, s | |||
265 | error = user_path_walk(path, &nd); | 265 | error = user_path_walk(path, &nd); |
266 | if (!error) { | 266 | if (!error) { |
267 | struct kstatfs tmp; | 267 | struct kstatfs tmp; |
268 | error = vfs_statfs(nd.dentry->d_inode->i_sb, &tmp); | 268 | error = vfs_statfs(nd.dentry, &tmp); |
269 | if (!error) | 269 | if (!error) |
270 | error = put_compat_statfs64(buf, &tmp); | 270 | error = put_compat_statfs64(buf, &tmp); |
271 | path_release(&nd); | 271 | path_release(&nd); |
@@ -286,7 +286,7 @@ asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct c | |||
286 | file = fget(fd); | 286 | file = fget(fd); |
287 | if (!file) | 287 | if (!file) |
288 | goto out; | 288 | goto out; |
289 | error = vfs_statfs(file->f_dentry->d_inode->i_sb, &tmp); | 289 | error = vfs_statfs(file->f_dentry, &tmp); |
290 | if (!error) | 290 | if (!error) |
291 | error = put_compat_statfs64(buf, &tmp); | 291 | error = put_compat_statfs64(buf, &tmp); |
292 | fput(file); | 292 | fput(file); |
diff --git a/fs/configfs/mount.c b/fs/configfs/mount.c index f920d30478e5..94dab7bdd851 100644 --- a/fs/configfs/mount.c +++ b/fs/configfs/mount.c | |||
@@ -103,10 +103,10 @@ static int configfs_fill_super(struct super_block *sb, void *data, int silent) | |||
103 | return 0; | 103 | return 0; |
104 | } | 104 | } |
105 | 105 | ||
106 | static struct super_block *configfs_get_sb(struct file_system_type *fs_type, | 106 | static int configfs_get_sb(struct file_system_type *fs_type, |
107 | int flags, const char *dev_name, void *data) | 107 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
108 | { | 108 | { |
109 | return get_sb_single(fs_type, flags, data, configfs_fill_super); | 109 | return get_sb_single(fs_type, flags, data, configfs_fill_super, mnt); |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct file_system_type configfs_fs_type = { | 112 | static struct file_system_type configfs_fs_type = { |
diff --git a/fs/cramfs/inode.c b/fs/cramfs/inode.c index 9efcc3a164e8..c45d73860803 100644 --- a/fs/cramfs/inode.c +++ b/fs/cramfs/inode.c | |||
@@ -181,9 +181,7 @@ static void *cramfs_read(struct super_block *sb, unsigned int offset, unsigned i | |||
181 | struct page *page = NULL; | 181 | struct page *page = NULL; |
182 | 182 | ||
183 | if (blocknr + i < devsize) { | 183 | if (blocknr + i < devsize) { |
184 | page = read_cache_page(mapping, blocknr + i, | 184 | page = read_mapping_page(mapping, blocknr + i, NULL); |
185 | (filler_t *)mapping->a_ops->readpage, | ||
186 | NULL); | ||
187 | /* synchronous error? */ | 185 | /* synchronous error? */ |
188 | if (IS_ERR(page)) | 186 | if (IS_ERR(page)) |
189 | page = NULL; | 187 | page = NULL; |
@@ -322,8 +320,10 @@ out: | |||
322 | return -EINVAL; | 320 | return -EINVAL; |
323 | } | 321 | } |
324 | 322 | ||
325 | static int cramfs_statfs(struct super_block *sb, struct kstatfs *buf) | 323 | static int cramfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
326 | { | 324 | { |
325 | struct super_block *sb = dentry->d_sb; | ||
326 | |||
327 | buf->f_type = CRAMFS_MAGIC; | 327 | buf->f_type = CRAMFS_MAGIC; |
328 | buf->f_bsize = PAGE_CACHE_SIZE; | 328 | buf->f_bsize = PAGE_CACHE_SIZE; |
329 | buf->f_blocks = CRAMFS_SB(sb)->blocks; | 329 | buf->f_blocks = CRAMFS_SB(sb)->blocks; |
@@ -528,10 +528,11 @@ static struct super_operations cramfs_ops = { | |||
528 | .statfs = cramfs_statfs, | 528 | .statfs = cramfs_statfs, |
529 | }; | 529 | }; |
530 | 530 | ||
531 | static struct super_block *cramfs_get_sb(struct file_system_type *fs_type, | 531 | static int cramfs_get_sb(struct file_system_type *fs_type, |
532 | int flags, const char *dev_name, void *data) | 532 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
533 | { | 533 | { |
534 | return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super); | 534 | return get_sb_bdev(fs_type, flags, dev_name, data, cramfs_fill_super, |
535 | mnt); | ||
535 | } | 536 | } |
536 | 537 | ||
537 | static struct file_system_type cramfs_fs_type = { | 538 | static struct file_system_type cramfs_fs_type = { |
diff --git a/fs/dcache.c b/fs/dcache.c index 940d188e5d14..313b54b2b8f2 100644 --- a/fs/dcache.c +++ b/fs/dcache.c | |||
@@ -359,12 +359,13 @@ restart: | |||
359 | } | 359 | } |
360 | 360 | ||
361 | /* | 361 | /* |
362 | * Throw away a dentry - free the inode, dput the parent. | 362 | * Throw away a dentry - free the inode, dput the parent. This requires that |
363 | * This requires that the LRU list has already been | 363 | * the LRU list has already been removed. |
364 | * removed. | 364 | * |
365 | * Called with dcache_lock, drops it and then regains. | 365 | * Called with dcache_lock, drops it and then regains. |
366 | * Called with dentry->d_lock held, drops it. | ||
366 | */ | 367 | */ |
367 | static inline void prune_one_dentry(struct dentry * dentry) | 368 | static void prune_one_dentry(struct dentry * dentry) |
368 | { | 369 | { |
369 | struct dentry * parent; | 370 | struct dentry * parent; |
370 | 371 | ||
@@ -382,6 +383,8 @@ static inline void prune_one_dentry(struct dentry * dentry) | |||
382 | /** | 383 | /** |
383 | * prune_dcache - shrink the dcache | 384 | * prune_dcache - shrink the dcache |
384 | * @count: number of entries to try and free | 385 | * @count: number of entries to try and free |
386 | * @sb: if given, ignore dentries for other superblocks | ||
387 | * which are being unmounted. | ||
385 | * | 388 | * |
386 | * Shrink the dcache. This is done when we need | 389 | * Shrink the dcache. This is done when we need |
387 | * more memory, or simply when we need to unmount | 390 | * more memory, or simply when we need to unmount |
@@ -392,16 +395,29 @@ static inline void prune_one_dentry(struct dentry * dentry) | |||
392 | * all the dentries are in use. | 395 | * all the dentries are in use. |
393 | */ | 396 | */ |
394 | 397 | ||
395 | static void prune_dcache(int count) | 398 | static void prune_dcache(int count, struct super_block *sb) |
396 | { | 399 | { |
397 | spin_lock(&dcache_lock); | 400 | spin_lock(&dcache_lock); |
398 | for (; count ; count--) { | 401 | for (; count ; count--) { |
399 | struct dentry *dentry; | 402 | struct dentry *dentry; |
400 | struct list_head *tmp; | 403 | struct list_head *tmp; |
404 | struct rw_semaphore *s_umount; | ||
401 | 405 | ||
402 | cond_resched_lock(&dcache_lock); | 406 | cond_resched_lock(&dcache_lock); |
403 | 407 | ||
404 | tmp = dentry_unused.prev; | 408 | tmp = dentry_unused.prev; |
409 | if (unlikely(sb)) { | ||
410 | /* Try to find a dentry for this sb, but don't try | ||
411 | * too hard, if they aren't near the tail they will | ||
412 | * be moved down again soon | ||
413 | */ | ||
414 | int skip = count; | ||
415 | while (skip && tmp != &dentry_unused && | ||
416 | list_entry(tmp, struct dentry, d_lru)->d_sb != sb) { | ||
417 | skip--; | ||
418 | tmp = tmp->prev; | ||
419 | } | ||
420 | } | ||
405 | if (tmp == &dentry_unused) | 421 | if (tmp == &dentry_unused) |
406 | break; | 422 | break; |
407 | list_del_init(tmp); | 423 | list_del_init(tmp); |
@@ -427,7 +443,45 @@ static void prune_dcache(int count) | |||
427 | spin_unlock(&dentry->d_lock); | 443 | spin_unlock(&dentry->d_lock); |
428 | continue; | 444 | continue; |
429 | } | 445 | } |
430 | prune_one_dentry(dentry); | 446 | /* |
447 | * If the dentry is not DCACHED_REFERENCED, it is time | ||
448 | * to remove it from the dcache, provided the super block is | ||
449 | * NULL (which means we are trying to reclaim memory) | ||
450 | * or this dentry belongs to the same super block that | ||
451 | * we want to shrink. | ||
452 | */ | ||
453 | /* | ||
454 | * If this dentry is for "my" filesystem, then I can prune it | ||
455 | * without taking the s_umount lock (I already hold it). | ||
456 | */ | ||
457 | if (sb && dentry->d_sb == sb) { | ||
458 | prune_one_dentry(dentry); | ||
459 | continue; | ||
460 | } | ||
461 | /* | ||
462 | * ...otherwise we need to be sure this filesystem isn't being | ||
463 | * unmounted, otherwise we could race with | ||
464 | * generic_shutdown_super(), and end up holding a reference to | ||
465 | * an inode while the filesystem is unmounted. | ||
466 | * So we try to get s_umount, and make sure s_root isn't NULL. | ||
467 | * (Take a local copy of s_umount to avoid a use-after-free of | ||
468 | * `dentry'). | ||
469 | */ | ||
470 | s_umount = &dentry->d_sb->s_umount; | ||
471 | if (down_read_trylock(s_umount)) { | ||
472 | if (dentry->d_sb->s_root != NULL) { | ||
473 | prune_one_dentry(dentry); | ||
474 | up_read(s_umount); | ||
475 | continue; | ||
476 | } | ||
477 | up_read(s_umount); | ||
478 | } | ||
479 | spin_unlock(&dentry->d_lock); | ||
480 | /* Cannot remove the first dentry, and it isn't appropriate | ||
481 | * to move it to the head of the list, so give up, and try | ||
482 | * later | ||
483 | */ | ||
484 | break; | ||
431 | } | 485 | } |
432 | spin_unlock(&dcache_lock); | 486 | spin_unlock(&dcache_lock); |
433 | } | 487 | } |
@@ -630,46 +684,7 @@ void shrink_dcache_parent(struct dentry * parent) | |||
630 | int found; | 684 | int found; |
631 | 685 | ||
632 | while ((found = select_parent(parent)) != 0) | 686 | while ((found = select_parent(parent)) != 0) |
633 | prune_dcache(found); | 687 | prune_dcache(found, parent->d_sb); |
634 | } | ||
635 | |||
636 | /** | ||
637 | * shrink_dcache_anon - further prune the cache | ||
638 | * @head: head of d_hash list of dentries to prune | ||
639 | * | ||
640 | * Prune the dentries that are anonymous | ||
641 | * | ||
642 | * parsing d_hash list does not hlist_for_each_entry_rcu() as it | ||
643 | * done under dcache_lock. | ||
644 | * | ||
645 | */ | ||
646 | void shrink_dcache_anon(struct hlist_head *head) | ||
647 | { | ||
648 | struct hlist_node *lp; | ||
649 | int found; | ||
650 | do { | ||
651 | found = 0; | ||
652 | spin_lock(&dcache_lock); | ||
653 | hlist_for_each(lp, head) { | ||
654 | struct dentry *this = hlist_entry(lp, struct dentry, d_hash); | ||
655 | if (!list_empty(&this->d_lru)) { | ||
656 | dentry_stat.nr_unused--; | ||
657 | list_del_init(&this->d_lru); | ||
658 | } | ||
659 | |||
660 | /* | ||
661 | * move only zero ref count dentries to the end | ||
662 | * of the unused list for prune_dcache | ||
663 | */ | ||
664 | if (!atomic_read(&this->d_count)) { | ||
665 | list_add_tail(&this->d_lru, &dentry_unused); | ||
666 | dentry_stat.nr_unused++; | ||
667 | found++; | ||
668 | } | ||
669 | } | ||
670 | spin_unlock(&dcache_lock); | ||
671 | prune_dcache(found); | ||
672 | } while(found); | ||
673 | } | 688 | } |
674 | 689 | ||
675 | /* | 690 | /* |
@@ -689,7 +704,7 @@ static int shrink_dcache_memory(int nr, gfp_t gfp_mask) | |||
689 | if (nr) { | 704 | if (nr) { |
690 | if (!(gfp_mask & __GFP_FS)) | 705 | if (!(gfp_mask & __GFP_FS)) |
691 | return -1; | 706 | return -1; |
692 | prune_dcache(nr); | 707 | prune_dcache(nr, NULL); |
693 | } | 708 | } |
694 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; | 709 | return (dentry_stat.nr_unused / 100) * sysctl_vfs_cache_pressure; |
695 | } | 710 | } |
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c index b55b4ea9a676..440128ebef3b 100644 --- a/fs/debugfs/inode.c +++ b/fs/debugfs/inode.c | |||
@@ -111,11 +111,11 @@ static int debug_fill_super(struct super_block *sb, void *data, int silent) | |||
111 | return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); | 111 | return simple_fill_super(sb, DEBUGFS_MAGIC, debug_files); |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct super_block *debug_get_sb(struct file_system_type *fs_type, | 114 | static int debug_get_sb(struct file_system_type *fs_type, |
115 | int flags, const char *dev_name, | 115 | int flags, const char *dev_name, |
116 | void *data) | 116 | void *data, struct vfsmount *mnt) |
117 | { | 117 | { |
118 | return get_sb_single(fs_type, flags, data, debug_fill_super); | 118 | return get_sb_single(fs_type, flags, data, debug_fill_super, mnt); |
119 | } | 119 | } |
120 | 120 | ||
121 | static struct file_system_type debug_fs_type = { | 121 | static struct file_system_type debug_fs_type = { |
diff --git a/fs/devfs/base.c b/fs/devfs/base.c index 52f5059c4f31..51a97f132745 100644 --- a/fs/devfs/base.c +++ b/fs/devfs/base.c | |||
@@ -2549,11 +2549,11 @@ static int devfs_fill_super(struct super_block *sb, void *data, int silent) | |||
2549 | return -EINVAL; | 2549 | return -EINVAL; |
2550 | } /* End Function devfs_fill_super */ | 2550 | } /* End Function devfs_fill_super */ |
2551 | 2551 | ||
2552 | static struct super_block *devfs_get_sb(struct file_system_type *fs_type, | 2552 | static int devfs_get_sb(struct file_system_type *fs_type, |
2553 | int flags, const char *dev_name, | 2553 | int flags, const char *dev_name, |
2554 | void *data) | 2554 | void *data, struct vfsmount *mnt) |
2555 | { | 2555 | { |
2556 | return get_sb_single(fs_type, flags, data, devfs_fill_super); | 2556 | return get_sb_single(fs_type, flags, data, devfs_fill_super, mnt); |
2557 | } | 2557 | } |
2558 | 2558 | ||
2559 | static struct file_system_type devfs_fs_type = { | 2559 | static struct file_system_type devfs_fs_type = { |
diff --git a/fs/devpts/inode.c b/fs/devpts/inode.c index 14c5620b5cab..f7aef5bb584a 100644 --- a/fs/devpts/inode.c +++ b/fs/devpts/inode.c | |||
@@ -130,10 +130,10 @@ fail: | |||
130 | return -ENOMEM; | 130 | return -ENOMEM; |
131 | } | 131 | } |
132 | 132 | ||
133 | static struct super_block *devpts_get_sb(struct file_system_type *fs_type, | 133 | static int devpts_get_sb(struct file_system_type *fs_type, |
134 | int flags, const char *dev_name, void *data) | 134 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
135 | { | 135 | { |
136 | return get_sb_single(fs_type, flags, data, devpts_fill_super); | 136 | return get_sb_single(fs_type, flags, data, devpts_fill_super, mnt); |
137 | } | 137 | } |
138 | 138 | ||
139 | static struct file_system_type devpts_fs_type = { | 139 | static struct file_system_type devpts_fs_type = { |
diff --git a/fs/direct-io.c b/fs/direct-io.c index b05d1b218776..538fb0418fba 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c | |||
@@ -162,7 +162,7 @@ static int dio_refill_pages(struct dio *dio) | |||
162 | NULL); /* vmas */ | 162 | NULL); /* vmas */ |
163 | up_read(¤t->mm->mmap_sem); | 163 | up_read(¤t->mm->mmap_sem); |
164 | 164 | ||
165 | if (ret < 0 && dio->blocks_available && (dio->rw == WRITE)) { | 165 | if (ret < 0 && dio->blocks_available && (dio->rw & WRITE)) { |
166 | struct page *page = ZERO_PAGE(dio->curr_user_address); | 166 | struct page *page = ZERO_PAGE(dio->curr_user_address); |
167 | /* | 167 | /* |
168 | * A memory fault, but the filesystem has some outstanding | 168 | * A memory fault, but the filesystem has some outstanding |
@@ -535,7 +535,7 @@ static int get_more_blocks(struct dio *dio) | |||
535 | map_bh->b_state = 0; | 535 | map_bh->b_state = 0; |
536 | map_bh->b_size = fs_count << dio->inode->i_blkbits; | 536 | map_bh->b_size = fs_count << dio->inode->i_blkbits; |
537 | 537 | ||
538 | create = dio->rw == WRITE; | 538 | create = dio->rw & WRITE; |
539 | if (dio->lock_type == DIO_LOCKING) { | 539 | if (dio->lock_type == DIO_LOCKING) { |
540 | if (dio->block_in_file < (i_size_read(dio->inode) >> | 540 | if (dio->block_in_file < (i_size_read(dio->inode) >> |
541 | dio->blkbits)) | 541 | dio->blkbits)) |
@@ -867,7 +867,7 @@ do_holes: | |||
867 | loff_t i_size_aligned; | 867 | loff_t i_size_aligned; |
868 | 868 | ||
869 | /* AKPM: eargh, -ENOTBLK is a hack */ | 869 | /* AKPM: eargh, -ENOTBLK is a hack */ |
870 | if (dio->rw == WRITE) { | 870 | if (dio->rw & WRITE) { |
871 | page_cache_release(page); | 871 | page_cache_release(page); |
872 | return -ENOTBLK; | 872 | return -ENOTBLK; |
873 | } | 873 | } |
@@ -1045,7 +1045,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1045 | } | 1045 | } |
1046 | } /* end iovec loop */ | 1046 | } /* end iovec loop */ |
1047 | 1047 | ||
1048 | if (ret == -ENOTBLK && rw == WRITE) { | 1048 | if (ret == -ENOTBLK && (rw & WRITE)) { |
1049 | /* | 1049 | /* |
1050 | * The remaining part of the request will be | 1050 | * The remaining part of the request will be |
1051 | * be handled by buffered I/O when we return | 1051 | * be handled by buffered I/O when we return |
@@ -1089,7 +1089,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1089 | if (dio->is_async) { | 1089 | if (dio->is_async) { |
1090 | int should_wait = 0; | 1090 | int should_wait = 0; |
1091 | 1091 | ||
1092 | if (dio->result < dio->size && rw == WRITE) { | 1092 | if (dio->result < dio->size && (rw & WRITE)) { |
1093 | dio->waiter = current; | 1093 | dio->waiter = current; |
1094 | should_wait = 1; | 1094 | should_wait = 1; |
1095 | } | 1095 | } |
@@ -1142,7 +1142,7 @@ direct_io_worker(int rw, struct kiocb *iocb, struct inode *inode, | |||
1142 | ret = transferred; | 1142 | ret = transferred; |
1143 | 1143 | ||
1144 | /* We could have also come here on an AIO file extend */ | 1144 | /* We could have also come here on an AIO file extend */ |
1145 | if (!is_sync_kiocb(iocb) && rw == WRITE && | 1145 | if (!is_sync_kiocb(iocb) && (rw & WRITE) && |
1146 | ret >= 0 && dio->result == dio->size) | 1146 | ret >= 0 && dio->result == dio->size) |
1147 | /* | 1147 | /* |
1148 | * For AIO writes where we have completed the | 1148 | * For AIO writes where we have completed the |
@@ -1194,7 +1194,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
1194 | int acquire_i_mutex = 0; | 1194 | int acquire_i_mutex = 0; |
1195 | 1195 | ||
1196 | if (rw & WRITE) | 1196 | if (rw & WRITE) |
1197 | current->flags |= PF_SYNCWRITE; | 1197 | rw = WRITE_SYNC; |
1198 | 1198 | ||
1199 | if (bdev) | 1199 | if (bdev) |
1200 | bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); | 1200 | bdev_blkbits = blksize_bits(bdev_hardsect_size(bdev)); |
@@ -1270,7 +1270,7 @@ __blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, | |||
1270 | * even for AIO, we need to wait for i/o to complete before | 1270 | * even for AIO, we need to wait for i/o to complete before |
1271 | * returning in this case. | 1271 | * returning in this case. |
1272 | */ | 1272 | */ |
1273 | dio->is_async = !is_sync_kiocb(iocb) && !((rw == WRITE) && | 1273 | dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) && |
1274 | (end > i_size_read(inode))); | 1274 | (end > i_size_read(inode))); |
1275 | 1275 | ||
1276 | retval = direct_io_worker(rw, iocb, inode, iov, offset, | 1276 | retval = direct_io_worker(rw, iocb, inode, iov, offset, |
@@ -1284,8 +1284,6 @@ out: | |||
1284 | mutex_unlock(&inode->i_mutex); | 1284 | mutex_unlock(&inode->i_mutex); |
1285 | else if (acquire_i_mutex) | 1285 | else if (acquire_i_mutex) |
1286 | mutex_lock(&inode->i_mutex); | 1286 | mutex_lock(&inode->i_mutex); |
1287 | if (rw & WRITE) | ||
1288 | current->flags &= ~PF_SYNCWRITE; | ||
1289 | return retval; | 1287 | return retval; |
1290 | } | 1288 | } |
1291 | EXPORT_SYMBOL(__blockdev_direct_IO); | 1289 | EXPORT_SYMBOL(__blockdev_direct_IO); |
diff --git a/fs/efs/super.c b/fs/efs/super.c index dff623e3ddbf..8ac2462ae5dd 100644 --- a/fs/efs/super.c +++ b/fs/efs/super.c | |||
@@ -15,13 +15,13 @@ | |||
15 | #include <linux/buffer_head.h> | 15 | #include <linux/buffer_head.h> |
16 | #include <linux/vfs.h> | 16 | #include <linux/vfs.h> |
17 | 17 | ||
18 | static int efs_statfs(struct super_block *s, struct kstatfs *buf); | 18 | static int efs_statfs(struct dentry *dentry, struct kstatfs *buf); |
19 | static int efs_fill_super(struct super_block *s, void *d, int silent); | 19 | static int efs_fill_super(struct super_block *s, void *d, int silent); |
20 | 20 | ||
21 | static struct super_block *efs_get_sb(struct file_system_type *fs_type, | 21 | static int efs_get_sb(struct file_system_type *fs_type, |
22 | int flags, const char *dev_name, void *data) | 22 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
23 | { | 23 | { |
24 | return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super); | 24 | return get_sb_bdev(fs_type, flags, dev_name, data, efs_fill_super, mnt); |
25 | } | 25 | } |
26 | 26 | ||
27 | static struct file_system_type efs_fs_type = { | 27 | static struct file_system_type efs_fs_type = { |
@@ -322,8 +322,8 @@ out_no_fs: | |||
322 | return -EINVAL; | 322 | return -EINVAL; |
323 | } | 323 | } |
324 | 324 | ||
325 | static int efs_statfs(struct super_block *s, struct kstatfs *buf) { | 325 | static int efs_statfs(struct dentry *dentry, struct kstatfs *buf) { |
326 | struct efs_sb_info *sb = SUPER_INFO(s); | 326 | struct efs_sb_info *sb = SUPER_INFO(dentry->d_sb); |
327 | 327 | ||
328 | buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ | 328 | buf->f_type = EFS_SUPER_MAGIC; /* efs magic number */ |
329 | buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ | 329 | buf->f_bsize = EFS_BLOCKSIZE; /* blocksize */ |
diff --git a/fs/eventpoll.c b/fs/eventpoll.c index 1b4491cdd115..08e7e6a555ca 100644 --- a/fs/eventpoll.c +++ b/fs/eventpoll.c | |||
@@ -268,9 +268,9 @@ static int ep_poll(struct eventpoll *ep, struct epoll_event __user *events, | |||
268 | int maxevents, long timeout); | 268 | int maxevents, long timeout); |
269 | static int eventpollfs_delete_dentry(struct dentry *dentry); | 269 | static int eventpollfs_delete_dentry(struct dentry *dentry); |
270 | static struct inode *ep_eventpoll_inode(void); | 270 | static struct inode *ep_eventpoll_inode(void); |
271 | static struct super_block *eventpollfs_get_sb(struct file_system_type *fs_type, | 271 | static int eventpollfs_get_sb(struct file_system_type *fs_type, |
272 | int flags, const char *dev_name, | 272 | int flags, const char *dev_name, |
273 | void *data); | 273 | void *data, struct vfsmount *mnt); |
274 | 274 | ||
275 | /* | 275 | /* |
276 | * This semaphore is used to serialize ep_free() and eventpoll_release_file(). | 276 | * This semaphore is used to serialize ep_free() and eventpoll_release_file(). |
@@ -337,20 +337,20 @@ static inline int ep_cmp_ffd(struct epoll_filefd *p1, | |||
337 | /* Special initialization for the rb-tree node to detect linkage */ | 337 | /* Special initialization for the rb-tree node to detect linkage */ |
338 | static inline void ep_rb_initnode(struct rb_node *n) | 338 | static inline void ep_rb_initnode(struct rb_node *n) |
339 | { | 339 | { |
340 | n->rb_parent = n; | 340 | rb_set_parent(n, n); |
341 | } | 341 | } |
342 | 342 | ||
343 | /* Removes a node from the rb-tree and marks it for a fast is-linked check */ | 343 | /* Removes a node from the rb-tree and marks it for a fast is-linked check */ |
344 | static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r) | 344 | static inline void ep_rb_erase(struct rb_node *n, struct rb_root *r) |
345 | { | 345 | { |
346 | rb_erase(n, r); | 346 | rb_erase(n, r); |
347 | n->rb_parent = n; | 347 | rb_set_parent(n, n); |
348 | } | 348 | } |
349 | 349 | ||
350 | /* Fast check to verify that the item is linked to the main rb-tree */ | 350 | /* Fast check to verify that the item is linked to the main rb-tree */ |
351 | static inline int ep_rb_linked(struct rb_node *n) | 351 | static inline int ep_rb_linked(struct rb_node *n) |
352 | { | 352 | { |
353 | return n->rb_parent != n; | 353 | return rb_parent(n) != n; |
354 | } | 354 | } |
355 | 355 | ||
356 | /* | 356 | /* |
@@ -1595,11 +1595,12 @@ eexit_1: | |||
1595 | } | 1595 | } |
1596 | 1596 | ||
1597 | 1597 | ||
1598 | static struct super_block * | 1598 | static int |
1599 | eventpollfs_get_sb(struct file_system_type *fs_type, int flags, | 1599 | eventpollfs_get_sb(struct file_system_type *fs_type, int flags, |
1600 | const char *dev_name, void *data) | 1600 | const char *dev_name, void *data, struct vfsmount *mnt) |
1601 | { | 1601 | { |
1602 | return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC); | 1602 | return get_sb_pseudo(fs_type, "eventpoll:", NULL, EVENTPOLLFS_MAGIC, |
1603 | mnt); | ||
1603 | } | 1604 | } |
1604 | 1605 | ||
1605 | 1606 | ||
@@ -49,6 +49,7 @@ | |||
49 | #include <linux/rmap.h> | 49 | #include <linux/rmap.h> |
50 | #include <linux/acct.h> | 50 | #include <linux/acct.h> |
51 | #include <linux/cn_proc.h> | 51 | #include <linux/cn_proc.h> |
52 | #include <linux/audit.h> | ||
52 | 53 | ||
53 | #include <asm/uaccess.h> | 54 | #include <asm/uaccess.h> |
54 | #include <asm/mmu_context.h> | 55 | #include <asm/mmu_context.h> |
@@ -865,7 +866,6 @@ int flush_old_exec(struct linux_binprm * bprm) | |||
865 | bprm->mm = NULL; /* We're using it now */ | 866 | bprm->mm = NULL; /* We're using it now */ |
866 | 867 | ||
867 | /* This is the point of no return */ | 868 | /* This is the point of no return */ |
868 | steal_locks(files); | ||
869 | put_files_struct(files); | 869 | put_files_struct(files); |
870 | 870 | ||
871 | current->sas_ss_sp = current->sas_ss_size = 0; | 871 | current->sas_ss_sp = current->sas_ss_size = 0; |
@@ -1085,6 +1085,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs) | |||
1085 | /* kernel module loader fixup */ | 1085 | /* kernel module loader fixup */ |
1086 | /* so we don't try to load run modprobe in kernel space. */ | 1086 | /* so we don't try to load run modprobe in kernel space. */ |
1087 | set_fs(USER_DS); | 1087 | set_fs(USER_DS); |
1088 | |||
1089 | retval = audit_bprm(bprm); | ||
1090 | if (retval) | ||
1091 | return retval; | ||
1092 | |||
1088 | retval = -ENOENT; | 1093 | retval = -ENOENT; |
1089 | for (try=0; try<2; try++) { | 1094 | for (try=0; try<2; try++) { |
1090 | read_lock(&binfmt_lock); | 1095 | read_lock(&binfmt_lock); |
diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index d672aa9f4061..3c1c9aaaca6b 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c | |||
@@ -159,8 +159,7 @@ fail: | |||
159 | static struct page * ext2_get_page(struct inode *dir, unsigned long n) | 159 | static struct page * ext2_get_page(struct inode *dir, unsigned long n) |
160 | { | 160 | { |
161 | struct address_space *mapping = dir->i_mapping; | 161 | struct address_space *mapping = dir->i_mapping; |
162 | struct page *page = read_cache_page(mapping, n, | 162 | struct page *page = read_mapping_page(mapping, n, NULL); |
163 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
164 | if (!IS_ERR(page)) { | 163 | if (!IS_ERR(page)) { |
165 | wait_on_page_locked(page); | 164 | wait_on_page_locked(page); |
166 | kmap(page); | 165 | kmap(page); |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 7e30bae174ed..ee4ba759581e 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
@@ -39,7 +39,7 @@ | |||
39 | static void ext2_sync_super(struct super_block *sb, | 39 | static void ext2_sync_super(struct super_block *sb, |
40 | struct ext2_super_block *es); | 40 | struct ext2_super_block *es); |
41 | static int ext2_remount (struct super_block * sb, int * flags, char * data); | 41 | static int ext2_remount (struct super_block * sb, int * flags, char * data); |
42 | static int ext2_statfs (struct super_block * sb, struct kstatfs * buf); | 42 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf); |
43 | 43 | ||
44 | void ext2_error (struct super_block * sb, const char * function, | 44 | void ext2_error (struct super_block * sb, const char * function, |
45 | const char * fmt, ...) | 45 | const char * fmt, ...) |
@@ -834,9 +834,6 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
834 | printk ("EXT2-fs: not enough memory\n"); | 834 | printk ("EXT2-fs: not enough memory\n"); |
835 | goto failed_mount; | 835 | goto failed_mount; |
836 | } | 836 | } |
837 | percpu_counter_init(&sbi->s_freeblocks_counter); | ||
838 | percpu_counter_init(&sbi->s_freeinodes_counter); | ||
839 | percpu_counter_init(&sbi->s_dirs_counter); | ||
840 | bgl_lock_init(&sbi->s_blockgroup_lock); | 837 | bgl_lock_init(&sbi->s_blockgroup_lock); |
841 | sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts), | 838 | sbi->s_debts = kmalloc(sbi->s_groups_count * sizeof(*sbi->s_debts), |
842 | GFP_KERNEL); | 839 | GFP_KERNEL); |
@@ -863,6 +860,13 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
863 | sbi->s_gdb_count = db_count; | 860 | sbi->s_gdb_count = db_count; |
864 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 861 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
865 | spin_lock_init(&sbi->s_next_gen_lock); | 862 | spin_lock_init(&sbi->s_next_gen_lock); |
863 | |||
864 | percpu_counter_init(&sbi->s_freeblocks_counter, | ||
865 | ext2_count_free_blocks(sb)); | ||
866 | percpu_counter_init(&sbi->s_freeinodes_counter, | ||
867 | ext2_count_free_inodes(sb)); | ||
868 | percpu_counter_init(&sbi->s_dirs_counter, | ||
869 | ext2_count_dirs(sb)); | ||
866 | /* | 870 | /* |
867 | * set up enough so that it can read an inode | 871 | * set up enough so that it can read an inode |
868 | */ | 872 | */ |
@@ -874,24 +878,18 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) | |||
874 | if (!sb->s_root) { | 878 | if (!sb->s_root) { |
875 | iput(root); | 879 | iput(root); |
876 | printk(KERN_ERR "EXT2-fs: get root inode failed\n"); | 880 | printk(KERN_ERR "EXT2-fs: get root inode failed\n"); |
877 | goto failed_mount2; | 881 | goto failed_mount3; |
878 | } | 882 | } |
879 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | 883 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { |
880 | dput(sb->s_root); | 884 | dput(sb->s_root); |
881 | sb->s_root = NULL; | 885 | sb->s_root = NULL; |
882 | printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); | 886 | printk(KERN_ERR "EXT2-fs: corrupt root inode, run e2fsck\n"); |
883 | goto failed_mount2; | 887 | goto failed_mount3; |
884 | } | 888 | } |
885 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) | 889 | if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) |
886 | ext2_warning(sb, __FUNCTION__, | 890 | ext2_warning(sb, __FUNCTION__, |
887 | "mounting ext3 filesystem as ext2"); | 891 | "mounting ext3 filesystem as ext2"); |
888 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); | 892 | ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
889 | percpu_counter_mod(&sbi->s_freeblocks_counter, | ||
890 | ext2_count_free_blocks(sb)); | ||
891 | percpu_counter_mod(&sbi->s_freeinodes_counter, | ||
892 | ext2_count_free_inodes(sb)); | ||
893 | percpu_counter_mod(&sbi->s_dirs_counter, | ||
894 | ext2_count_dirs(sb)); | ||
895 | return 0; | 893 | return 0; |
896 | 894 | ||
897 | cantfind_ext2: | 895 | cantfind_ext2: |
@@ -899,7 +897,10 @@ cantfind_ext2: | |||
899 | printk("VFS: Can't find an ext2 filesystem on dev %s.\n", | 897 | printk("VFS: Can't find an ext2 filesystem on dev %s.\n", |
900 | sb->s_id); | 898 | sb->s_id); |
901 | goto failed_mount; | 899 | goto failed_mount; |
902 | 900 | failed_mount3: | |
901 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
902 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
903 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
903 | failed_mount2: | 904 | failed_mount2: |
904 | for (i = 0; i < db_count; i++) | 905 | for (i = 0; i < db_count; i++) |
905 | brelse(sbi->s_group_desc[i]); | 906 | brelse(sbi->s_group_desc[i]); |
@@ -1038,8 +1039,9 @@ restore_opts: | |||
1038 | return err; | 1039 | return err; |
1039 | } | 1040 | } |
1040 | 1041 | ||
1041 | static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) | 1042 | static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) |
1042 | { | 1043 | { |
1044 | struct super_block *sb = dentry->d_sb; | ||
1043 | struct ext2_sb_info *sbi = EXT2_SB(sb); | 1045 | struct ext2_sb_info *sbi = EXT2_SB(sb); |
1044 | unsigned long overhead; | 1046 | unsigned long overhead; |
1045 | int i; | 1047 | int i; |
@@ -1087,10 +1089,10 @@ static int ext2_statfs (struct super_block * sb, struct kstatfs * buf) | |||
1087 | return 0; | 1089 | return 0; |
1088 | } | 1090 | } |
1089 | 1091 | ||
1090 | static struct super_block *ext2_get_sb(struct file_system_type *fs_type, | 1092 | static int ext2_get_sb(struct file_system_type *fs_type, |
1091 | int flags, const char *dev_name, void *data) | 1093 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1092 | { | 1094 | { |
1093 | return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super); | 1095 | return get_sb_bdev(fs_type, flags, dev_name, data, ext2_fill_super, mnt); |
1094 | } | 1096 | } |
1095 | 1097 | ||
1096 | #ifdef CONFIG_QUOTA | 1098 | #ifdef CONFIG_QUOTA |
diff --git a/fs/ext3/dir.c b/fs/ext3/dir.c index f37528ed222e..fbb0d4ed07d4 100644 --- a/fs/ext3/dir.c +++ b/fs/ext3/dir.c | |||
@@ -284,7 +284,7 @@ static void free_rb_tree_fname(struct rb_root *root) | |||
284 | * beginning of the loop and try to free the parent | 284 | * beginning of the loop and try to free the parent |
285 | * node. | 285 | * node. |
286 | */ | 286 | */ |
287 | parent = n->rb_parent; | 287 | parent = rb_parent(n); |
288 | fname = rb_entry(n, struct fname, rb_hash); | 288 | fname = rb_entry(n, struct fname, rb_hash); |
289 | while (fname) { | 289 | while (fname) { |
290 | struct fname * old = fname; | 290 | struct fname * old = fname; |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index f8a5266ea1ff..a60cc6ec130f 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
@@ -58,7 +58,7 @@ static int ext3_sync_fs(struct super_block *sb, int wait); | |||
58 | static const char *ext3_decode_error(struct super_block * sb, int errno, | 58 | static const char *ext3_decode_error(struct super_block * sb, int errno, |
59 | char nbuf[16]); | 59 | char nbuf[16]); |
60 | static int ext3_remount (struct super_block * sb, int * flags, char * data); | 60 | static int ext3_remount (struct super_block * sb, int * flags, char * data); |
61 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf); | 61 | static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf); |
62 | static void ext3_unlockfs(struct super_block *sb); | 62 | static void ext3_unlockfs(struct super_block *sb); |
63 | static void ext3_write_super (struct super_block * sb); | 63 | static void ext3_write_super (struct super_block * sb); |
64 | static void ext3_write_super_lockfs(struct super_block *sb); | 64 | static void ext3_write_super_lockfs(struct super_block *sb); |
@@ -499,20 +499,21 @@ static void ext3_clear_inode(struct inode *inode) | |||
499 | { | 499 | { |
500 | struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info; | 500 | struct ext3_block_alloc_info *rsv = EXT3_I(inode)->i_block_alloc_info; |
501 | #ifdef CONFIG_EXT3_FS_POSIX_ACL | 501 | #ifdef CONFIG_EXT3_FS_POSIX_ACL |
502 | if (EXT3_I(inode)->i_acl && | 502 | if (EXT3_I(inode)->i_acl && |
503 | EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) { | 503 | EXT3_I(inode)->i_acl != EXT3_ACL_NOT_CACHED) { |
504 | posix_acl_release(EXT3_I(inode)->i_acl); | 504 | posix_acl_release(EXT3_I(inode)->i_acl); |
505 | EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED; | 505 | EXT3_I(inode)->i_acl = EXT3_ACL_NOT_CACHED; |
506 | } | 506 | } |
507 | if (EXT3_I(inode)->i_default_acl && | 507 | if (EXT3_I(inode)->i_default_acl && |
508 | EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) { | 508 | EXT3_I(inode)->i_default_acl != EXT3_ACL_NOT_CACHED) { |
509 | posix_acl_release(EXT3_I(inode)->i_default_acl); | 509 | posix_acl_release(EXT3_I(inode)->i_default_acl); |
510 | EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED; | 510 | EXT3_I(inode)->i_default_acl = EXT3_ACL_NOT_CACHED; |
511 | } | 511 | } |
512 | #endif | 512 | #endif |
513 | ext3_discard_reservation(inode); | 513 | ext3_discard_reservation(inode); |
514 | EXT3_I(inode)->i_block_alloc_info = NULL; | 514 | EXT3_I(inode)->i_block_alloc_info = NULL; |
515 | kfree(rsv); | 515 | if (unlikely(rsv)) |
516 | kfree(rsv); | ||
516 | } | 517 | } |
517 | 518 | ||
518 | static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb) | 519 | static inline void ext3_show_quota_options(struct seq_file *seq, struct super_block *sb) |
@@ -1579,9 +1580,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1579 | goto failed_mount; | 1580 | goto failed_mount; |
1580 | } | 1581 | } |
1581 | 1582 | ||
1582 | percpu_counter_init(&sbi->s_freeblocks_counter); | ||
1583 | percpu_counter_init(&sbi->s_freeinodes_counter); | ||
1584 | percpu_counter_init(&sbi->s_dirs_counter); | ||
1585 | bgl_lock_init(&sbi->s_blockgroup_lock); | 1583 | bgl_lock_init(&sbi->s_blockgroup_lock); |
1586 | 1584 | ||
1587 | for (i = 0; i < db_count; i++) { | 1585 | for (i = 0; i < db_count; i++) { |
@@ -1601,6 +1599,14 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1601 | sbi->s_gdb_count = db_count; | 1599 | sbi->s_gdb_count = db_count; |
1602 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 1600 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
1603 | spin_lock_init(&sbi->s_next_gen_lock); | 1601 | spin_lock_init(&sbi->s_next_gen_lock); |
1602 | |||
1603 | percpu_counter_init(&sbi->s_freeblocks_counter, | ||
1604 | ext3_count_free_blocks(sb)); | ||
1605 | percpu_counter_init(&sbi->s_freeinodes_counter, | ||
1606 | ext3_count_free_inodes(sb)); | ||
1607 | percpu_counter_init(&sbi->s_dirs_counter, | ||
1608 | ext3_count_dirs(sb)); | ||
1609 | |||
1604 | /* per fileystem reservation list head & lock */ | 1610 | /* per fileystem reservation list head & lock */ |
1605 | spin_lock_init(&sbi->s_rsv_window_lock); | 1611 | spin_lock_init(&sbi->s_rsv_window_lock); |
1606 | sbi->s_rsv_window_root = RB_ROOT; | 1612 | sbi->s_rsv_window_root = RB_ROOT; |
@@ -1639,16 +1645,16 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1639 | if (!test_opt(sb, NOLOAD) && | 1645 | if (!test_opt(sb, NOLOAD) && |
1640 | EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { | 1646 | EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) { |
1641 | if (ext3_load_journal(sb, es, journal_devnum)) | 1647 | if (ext3_load_journal(sb, es, journal_devnum)) |
1642 | goto failed_mount2; | 1648 | goto failed_mount3; |
1643 | } else if (journal_inum) { | 1649 | } else if (journal_inum) { |
1644 | if (ext3_create_journal(sb, es, journal_inum)) | 1650 | if (ext3_create_journal(sb, es, journal_inum)) |
1645 | goto failed_mount2; | 1651 | goto failed_mount3; |
1646 | } else { | 1652 | } else { |
1647 | if (!silent) | 1653 | if (!silent) |
1648 | printk (KERN_ERR | 1654 | printk (KERN_ERR |
1649 | "ext3: No journal on filesystem on %s\n", | 1655 | "ext3: No journal on filesystem on %s\n", |
1650 | sb->s_id); | 1656 | sb->s_id); |
1651 | goto failed_mount2; | 1657 | goto failed_mount3; |
1652 | } | 1658 | } |
1653 | 1659 | ||
1654 | /* We have now updated the journal if required, so we can | 1660 | /* We have now updated the journal if required, so we can |
@@ -1671,7 +1677,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1671 | (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) { | 1677 | (sbi->s_journal, 0, 0, JFS_FEATURE_INCOMPAT_REVOKE)) { |
1672 | printk(KERN_ERR "EXT3-fs: Journal does not support " | 1678 | printk(KERN_ERR "EXT3-fs: Journal does not support " |
1673 | "requested data journaling mode\n"); | 1679 | "requested data journaling mode\n"); |
1674 | goto failed_mount3; | 1680 | goto failed_mount4; |
1675 | } | 1681 | } |
1676 | default: | 1682 | default: |
1677 | break; | 1683 | break; |
@@ -1694,13 +1700,13 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1694 | if (!sb->s_root) { | 1700 | if (!sb->s_root) { |
1695 | printk(KERN_ERR "EXT3-fs: get root inode failed\n"); | 1701 | printk(KERN_ERR "EXT3-fs: get root inode failed\n"); |
1696 | iput(root); | 1702 | iput(root); |
1697 | goto failed_mount3; | 1703 | goto failed_mount4; |
1698 | } | 1704 | } |
1699 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { | 1705 | if (!S_ISDIR(root->i_mode) || !root->i_blocks || !root->i_size) { |
1700 | dput(sb->s_root); | 1706 | dput(sb->s_root); |
1701 | sb->s_root = NULL; | 1707 | sb->s_root = NULL; |
1702 | printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n"); | 1708 | printk(KERN_ERR "EXT3-fs: corrupt root inode, run e2fsck\n"); |
1703 | goto failed_mount3; | 1709 | goto failed_mount4; |
1704 | } | 1710 | } |
1705 | 1711 | ||
1706 | ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); | 1712 | ext3_setup_super (sb, es, sb->s_flags & MS_RDONLY); |
@@ -1723,13 +1729,6 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
1723 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": | 1729 | test_opt(sb,DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA ? "ordered": |
1724 | "writeback"); | 1730 | "writeback"); |
1725 | 1731 | ||
1726 | percpu_counter_mod(&sbi->s_freeblocks_counter, | ||
1727 | ext3_count_free_blocks(sb)); | ||
1728 | percpu_counter_mod(&sbi->s_freeinodes_counter, | ||
1729 | ext3_count_free_inodes(sb)); | ||
1730 | percpu_counter_mod(&sbi->s_dirs_counter, | ||
1731 | ext3_count_dirs(sb)); | ||
1732 | |||
1733 | lock_kernel(); | 1732 | lock_kernel(); |
1734 | return 0; | 1733 | return 0; |
1735 | 1734 | ||
@@ -1739,8 +1738,12 @@ cantfind_ext3: | |||
1739 | sb->s_id); | 1738 | sb->s_id); |
1740 | goto failed_mount; | 1739 | goto failed_mount; |
1741 | 1740 | ||
1742 | failed_mount3: | 1741 | failed_mount4: |
1743 | journal_destroy(sbi->s_journal); | 1742 | journal_destroy(sbi->s_journal); |
1743 | failed_mount3: | ||
1744 | percpu_counter_destroy(&sbi->s_freeblocks_counter); | ||
1745 | percpu_counter_destroy(&sbi->s_freeinodes_counter); | ||
1746 | percpu_counter_destroy(&sbi->s_dirs_counter); | ||
1744 | failed_mount2: | 1747 | failed_mount2: |
1745 | for (i = 0; i < db_count; i++) | 1748 | for (i = 0; i < db_count; i++) |
1746 | brelse(sbi->s_group_desc[i]); | 1749 | brelse(sbi->s_group_desc[i]); |
@@ -2318,8 +2321,9 @@ restore_opts: | |||
2318 | return err; | 2321 | return err; |
2319 | } | 2322 | } |
2320 | 2323 | ||
2321 | static int ext3_statfs (struct super_block * sb, struct kstatfs * buf) | 2324 | static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) |
2322 | { | 2325 | { |
2326 | struct super_block *sb = dentry->d_sb; | ||
2323 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 2327 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
2324 | struct ext3_super_block *es = sbi->s_es; | 2328 | struct ext3_super_block *es = sbi->s_es; |
2325 | unsigned long overhead; | 2329 | unsigned long overhead; |
@@ -2646,10 +2650,10 @@ out: | |||
2646 | 2650 | ||
2647 | #endif | 2651 | #endif |
2648 | 2652 | ||
2649 | static struct super_block *ext3_get_sb(struct file_system_type *fs_type, | 2653 | static int ext3_get_sb(struct file_system_type *fs_type, |
2650 | int flags, const char *dev_name, void *data) | 2654 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
2651 | { | 2655 | { |
2652 | return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super); | 2656 | return get_sb_bdev(fs_type, flags, dev_name, data, ext3_fill_super, mnt); |
2653 | } | 2657 | } |
2654 | 2658 | ||
2655 | static struct file_system_type ext3_fs_type = { | 2659 | static struct file_system_type ext3_fs_type = { |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index c1ce284f8a94..7c35d582ec10 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
@@ -539,18 +539,18 @@ static int fat_remount(struct super_block *sb, int *flags, char *data) | |||
539 | return 0; | 539 | return 0; |
540 | } | 540 | } |
541 | 541 | ||
542 | static int fat_statfs(struct super_block *sb, struct kstatfs *buf) | 542 | static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) |
543 | { | 543 | { |
544 | struct msdos_sb_info *sbi = MSDOS_SB(sb); | 544 | struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); |
545 | 545 | ||
546 | /* If the count of free cluster is still unknown, counts it here. */ | 546 | /* If the count of free cluster is still unknown, counts it here. */ |
547 | if (sbi->free_clusters == -1) { | 547 | if (sbi->free_clusters == -1) { |
548 | int err = fat_count_free_clusters(sb); | 548 | int err = fat_count_free_clusters(dentry->d_sb); |
549 | if (err) | 549 | if (err) |
550 | return err; | 550 | return err; |
551 | } | 551 | } |
552 | 552 | ||
553 | buf->f_type = sb->s_magic; | 553 | buf->f_type = dentry->d_sb->s_magic; |
554 | buf->f_bsize = sbi->cluster_size; | 554 | buf->f_bsize = sbi->cluster_size; |
555 | buf->f_blocks = sbi->max_cluster - FAT_START_ENT; | 555 | buf->f_blocks = sbi->max_cluster - FAT_START_ENT; |
556 | buf->f_bfree = sbi->free_clusters; | 556 | buf->f_bfree = sbi->free_clusters; |
diff --git a/fs/fat/misc.c b/fs/fat/misc.c index 944652e9dde1..308f2b6b5026 100644 --- a/fs/fat/misc.c +++ b/fs/fat/misc.c | |||
@@ -210,4 +210,3 @@ int fat_sync_bhs(struct buffer_head **bhs, int nr_bhs) | |||
210 | return err; | 210 | return err; |
211 | } | 211 | } |
212 | 212 | ||
213 | EXPORT_SYMBOL_GPL(fat_sync_bhs); | ||
diff --git a/fs/file_table.c b/fs/file_table.c index bcea1998b4de..506d5307108d 100644 --- a/fs/file_table.c +++ b/fs/file_table.c | |||
@@ -300,5 +300,5 @@ void __init files_init(unsigned long mempages) | |||
300 | if (files_stat.max_files < NR_FILE) | 300 | if (files_stat.max_files < NR_FILE) |
301 | files_stat.max_files = NR_FILE; | 301 | files_stat.max_files = NR_FILE; |
302 | files_defer_init(); | 302 | files_defer_init(); |
303 | percpu_counter_init(&nr_files); | 303 | percpu_counter_init(&nr_files, 0); |
304 | } | 304 | } |
diff --git a/fs/freevxfs/vxfs_subr.c b/fs/freevxfs/vxfs_subr.c index 50aae77651b2..c1be118fc067 100644 --- a/fs/freevxfs/vxfs_subr.c +++ b/fs/freevxfs/vxfs_subr.c | |||
@@ -71,8 +71,7 @@ vxfs_get_page(struct address_space *mapping, u_long n) | |||
71 | { | 71 | { |
72 | struct page * pp; | 72 | struct page * pp; |
73 | 73 | ||
74 | pp = read_cache_page(mapping, n, | 74 | pp = read_mapping_page(mapping, n, NULL); |
75 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
76 | 75 | ||
77 | if (!IS_ERR(pp)) { | 76 | if (!IS_ERR(pp)) { |
78 | wait_on_page_locked(pp); | 77 | wait_on_page_locked(pp); |
diff --git a/fs/freevxfs/vxfs_super.c b/fs/freevxfs/vxfs_super.c index b44c916d24a1..b74b791fc23b 100644 --- a/fs/freevxfs/vxfs_super.c +++ b/fs/freevxfs/vxfs_super.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/stat.h> | 41 | #include <linux/stat.h> |
42 | #include <linux/vfs.h> | 42 | #include <linux/vfs.h> |
43 | #include <linux/mount.h> | ||
43 | 44 | ||
44 | #include "vxfs.h" | 45 | #include "vxfs.h" |
45 | #include "vxfs_extern.h" | 46 | #include "vxfs_extern.h" |
@@ -55,7 +56,7 @@ MODULE_ALIAS("vxfs"); /* makes mount -t vxfs autoload the module */ | |||
55 | 56 | ||
56 | 57 | ||
57 | static void vxfs_put_super(struct super_block *); | 58 | static void vxfs_put_super(struct super_block *); |
58 | static int vxfs_statfs(struct super_block *, struct kstatfs *); | 59 | static int vxfs_statfs(struct dentry *, struct kstatfs *); |
59 | static int vxfs_remount(struct super_block *, int *, char *); | 60 | static int vxfs_remount(struct super_block *, int *, char *); |
60 | 61 | ||
61 | static struct super_operations vxfs_super_ops = { | 62 | static struct super_operations vxfs_super_ops = { |
@@ -90,12 +91,12 @@ vxfs_put_super(struct super_block *sbp) | |||
90 | 91 | ||
91 | /** | 92 | /** |
92 | * vxfs_statfs - get filesystem information | 93 | * vxfs_statfs - get filesystem information |
93 | * @sbp: VFS superblock | 94 | * @dentry: VFS dentry to locate superblock |
94 | * @bufp: output buffer | 95 | * @bufp: output buffer |
95 | * | 96 | * |
96 | * Description: | 97 | * Description: |
97 | * vxfs_statfs fills the statfs buffer @bufp with information | 98 | * vxfs_statfs fills the statfs buffer @bufp with information |
98 | * about the filesystem described by @sbp. | 99 | * about the filesystem described by @dentry. |
99 | * | 100 | * |
100 | * Returns: | 101 | * Returns: |
101 | * Zero. | 102 | * Zero. |
@@ -107,12 +108,12 @@ vxfs_put_super(struct super_block *sbp) | |||
107 | * This is everything but complete... | 108 | * This is everything but complete... |
108 | */ | 109 | */ |
109 | static int | 110 | static int |
110 | vxfs_statfs(struct super_block *sbp, struct kstatfs *bufp) | 111 | vxfs_statfs(struct dentry *dentry, struct kstatfs *bufp) |
111 | { | 112 | { |
112 | struct vxfs_sb_info *infp = VXFS_SBI(sbp); | 113 | struct vxfs_sb_info *infp = VXFS_SBI(dentry->d_sb); |
113 | 114 | ||
114 | bufp->f_type = VXFS_SUPER_MAGIC; | 115 | bufp->f_type = VXFS_SUPER_MAGIC; |
115 | bufp->f_bsize = sbp->s_blocksize; | 116 | bufp->f_bsize = dentry->d_sb->s_blocksize; |
116 | bufp->f_blocks = infp->vsi_raw->vs_dsize; | 117 | bufp->f_blocks = infp->vsi_raw->vs_dsize; |
117 | bufp->f_bfree = infp->vsi_raw->vs_free; | 118 | bufp->f_bfree = infp->vsi_raw->vs_free; |
118 | bufp->f_bavail = 0; | 119 | bufp->f_bavail = 0; |
@@ -241,10 +242,11 @@ out: | |||
241 | /* | 242 | /* |
242 | * The usual module blurb. | 243 | * The usual module blurb. |
243 | */ | 244 | */ |
244 | static struct super_block *vxfs_get_sb(struct file_system_type *fs_type, | 245 | static int vxfs_get_sb(struct file_system_type *fs_type, |
245 | int flags, const char *dev_name, void *data) | 246 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
246 | { | 247 | { |
247 | return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super); | 248 | return get_sb_bdev(fs_type, flags, dev_name, data, vxfs_fill_super, |
249 | mnt); | ||
248 | } | 250 | } |
249 | 251 | ||
250 | static struct file_system_type vxfs_fs_type = { | 252 | static struct file_system_type vxfs_fs_type = { |
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index f3fbe2d030f4..031b27a4bc9a 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -461,6 +461,8 @@ void sync_inodes_sb(struct super_block *sb, int wait) | |||
461 | { | 461 | { |
462 | struct writeback_control wbc = { | 462 | struct writeback_control wbc = { |
463 | .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, | 463 | .sync_mode = wait ? WB_SYNC_ALL : WB_SYNC_HOLD, |
464 | .range_start = 0, | ||
465 | .range_end = LLONG_MAX, | ||
464 | }; | 466 | }; |
465 | unsigned long nr_dirty = read_page_state(nr_dirty); | 467 | unsigned long nr_dirty = read_page_state(nr_dirty); |
466 | unsigned long nr_unstable = read_page_state(nr_unstable); | 468 | unsigned long nr_unstable = read_page_state(nr_unstable); |
@@ -559,6 +561,8 @@ int write_inode_now(struct inode *inode, int sync) | |||
559 | struct writeback_control wbc = { | 561 | struct writeback_control wbc = { |
560 | .nr_to_write = LONG_MAX, | 562 | .nr_to_write = LONG_MAX, |
561 | .sync_mode = WB_SYNC_ALL, | 563 | .sync_mode = WB_SYNC_ALL, |
564 | .range_start = 0, | ||
565 | .range_end = LLONG_MAX, | ||
562 | }; | 566 | }; |
563 | 567 | ||
564 | if (!mapping_cap_writeback_dirty(inode->i_mapping)) | 568 | if (!mapping_cap_writeback_dirty(inode->i_mapping)) |
@@ -619,7 +623,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int | |||
619 | int need_write_inode_now = 0; | 623 | int need_write_inode_now = 0; |
620 | int err2; | 624 | int err2; |
621 | 625 | ||
622 | current->flags |= PF_SYNCWRITE; | ||
623 | if (what & OSYNC_DATA) | 626 | if (what & OSYNC_DATA) |
624 | err = filemap_fdatawrite(mapping); | 627 | err = filemap_fdatawrite(mapping); |
625 | if (what & (OSYNC_METADATA|OSYNC_DATA)) { | 628 | if (what & (OSYNC_METADATA|OSYNC_DATA)) { |
@@ -632,7 +635,6 @@ int generic_osync_inode(struct inode *inode, struct address_space *mapping, int | |||
632 | if (!err) | 635 | if (!err) |
633 | err = err2; | 636 | err = err2; |
634 | } | 637 | } |
635 | current->flags &= ~PF_SYNCWRITE; | ||
636 | 638 | ||
637 | spin_lock(&inode_lock); | 639 | spin_lock(&inode_lock); |
638 | if ((inode->i_state & I_DIRTY) && | 640 | if ((inode->i_state & I_DIRTY) && |
diff --git a/fs/fuse/file.c b/fs/fuse/file.c index fc342cf7c2cc..087f3b734f40 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c | |||
@@ -169,7 +169,7 @@ static int fuse_release(struct inode *inode, struct file *file) | |||
169 | return fuse_release_common(inode, file, 0); | 169 | return fuse_release_common(inode, file, 0); |
170 | } | 170 | } |
171 | 171 | ||
172 | static int fuse_flush(struct file *file) | 172 | static int fuse_flush(struct file *file, fl_owner_t id) |
173 | { | 173 | { |
174 | struct inode *inode = file->f_dentry->d_inode; | 174 | struct inode *inode = file->f_dentry->d_inode; |
175 | struct fuse_conn *fc = get_fuse_conn(inode); | 175 | struct fuse_conn *fc = get_fuse_conn(inode); |
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c index 7627022446b2..a13c0f529058 100644 --- a/fs/fuse/inode.c +++ b/fs/fuse/inode.c | |||
@@ -236,8 +236,9 @@ static void convert_fuse_statfs(struct kstatfs *stbuf, struct fuse_kstatfs *attr | |||
236 | /* fsid is left zero */ | 236 | /* fsid is left zero */ |
237 | } | 237 | } |
238 | 238 | ||
239 | static int fuse_statfs(struct super_block *sb, struct kstatfs *buf) | 239 | static int fuse_statfs(struct dentry *dentry, struct kstatfs *buf) |
240 | { | 240 | { |
241 | struct super_block *sb = dentry->d_sb; | ||
241 | struct fuse_conn *fc = get_fuse_conn_super(sb); | 242 | struct fuse_conn *fc = get_fuse_conn_super(sb); |
242 | struct fuse_req *req; | 243 | struct fuse_req *req; |
243 | struct fuse_statfs_out outarg; | 244 | struct fuse_statfs_out outarg; |
@@ -569,11 +570,11 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent) | |||
569 | return err; | 570 | return err; |
570 | } | 571 | } |
571 | 572 | ||
572 | static struct super_block *fuse_get_sb(struct file_system_type *fs_type, | 573 | static int fuse_get_sb(struct file_system_type *fs_type, |
573 | int flags, const char *dev_name, | 574 | int flags, const char *dev_name, |
574 | void *raw_data) | 575 | void *raw_data, struct vfsmount *mnt) |
575 | { | 576 | { |
576 | return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super); | 577 | return get_sb_nodev(fs_type, flags, raw_data, fuse_fill_super, mnt); |
577 | } | 578 | } |
578 | 579 | ||
579 | static struct file_system_type fuse_fs_type = { | 580 | static struct file_system_type fuse_fs_type = { |
diff --git a/fs/hfs/bnode.c b/fs/hfs/bnode.c index 1e44dcfe49c4..13231dd5ce66 100644 --- a/fs/hfs/bnode.c +++ b/fs/hfs/bnode.c | |||
@@ -280,7 +280,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) | |||
280 | block = off >> PAGE_CACHE_SHIFT; | 280 | block = off >> PAGE_CACHE_SHIFT; |
281 | node->page_offset = off & ~PAGE_CACHE_MASK; | 281 | node->page_offset = off & ~PAGE_CACHE_MASK; |
282 | for (i = 0; i < tree->pages_per_bnode; i++) { | 282 | for (i = 0; i < tree->pages_per_bnode; i++) { |
283 | page = read_cache_page(mapping, block++, (filler_t *)mapping->a_ops->readpage, NULL); | 283 | page = read_mapping_page(mapping, block++, NULL); |
284 | if (IS_ERR(page)) | 284 | if (IS_ERR(page)) |
285 | goto fail; | 285 | goto fail; |
286 | if (PageError(page)) { | 286 | if (PageError(page)) { |
diff --git a/fs/hfs/btree.c b/fs/hfs/btree.c index d20131ce4b95..400357994319 100644 --- a/fs/hfs/btree.c +++ b/fs/hfs/btree.c | |||
@@ -59,7 +59,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id, btree_keycmp ke | |||
59 | unlock_new_inode(tree->inode); | 59 | unlock_new_inode(tree->inode); |
60 | 60 | ||
61 | mapping = tree->inode->i_mapping; | 61 | mapping = tree->inode->i_mapping; |
62 | page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL); | 62 | page = read_mapping_page(mapping, 0, NULL); |
63 | if (IS_ERR(page)) | 63 | if (IS_ERR(page)) |
64 | goto free_tree; | 64 | goto free_tree; |
65 | 65 | ||
diff --git a/fs/hfs/super.c b/fs/hfs/super.c index 1181d116117d..d9227bf14e86 100644 --- a/fs/hfs/super.c +++ b/fs/hfs/super.c | |||
@@ -80,8 +80,10 @@ static void hfs_put_super(struct super_block *sb) | |||
80 | * | 80 | * |
81 | * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. | 81 | * changed f_files/f_ffree to reflect the fs_ablock/free_ablocks. |
82 | */ | 82 | */ |
83 | static int hfs_statfs(struct super_block *sb, struct kstatfs *buf) | 83 | static int hfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
84 | { | 84 | { |
85 | struct super_block *sb = dentry->d_sb; | ||
86 | |||
85 | buf->f_type = HFS_SUPER_MAGIC; | 87 | buf->f_type = HFS_SUPER_MAGIC; |
86 | buf->f_bsize = sb->s_blocksize; | 88 | buf->f_bsize = sb->s_blocksize; |
87 | buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div; | 89 | buf->f_blocks = (u32)HFS_SB(sb)->fs_ablocks * HFS_SB(sb)->fs_div; |
@@ -413,10 +415,11 @@ bail: | |||
413 | return res; | 415 | return res; |
414 | } | 416 | } |
415 | 417 | ||
416 | static struct super_block *hfs_get_sb(struct file_system_type *fs_type, | 418 | static int hfs_get_sb(struct file_system_type *fs_type, |
417 | int flags, const char *dev_name, void *data) | 419 | int flags, const char *dev_name, void *data, |
420 | struct vfsmount *mnt) | ||
418 | { | 421 | { |
419 | return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super); | 422 | return get_sb_bdev(fs_type, flags, dev_name, data, hfs_fill_super, mnt); |
420 | } | 423 | } |
421 | 424 | ||
422 | static struct file_system_type hfs_fs_type = { | 425 | static struct file_system_type hfs_fs_type = { |
diff --git a/fs/hfsplus/bitmap.c b/fs/hfsplus/bitmap.c index 9fb51632303c..d128a25b74d2 100644 --- a/fs/hfsplus/bitmap.c +++ b/fs/hfsplus/bitmap.c | |||
@@ -31,8 +31,7 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma | |||
31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); | 31 | dprint(DBG_BITMAP, "block_allocate: %u,%u,%u\n", size, offset, len); |
32 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 32 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 33 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; |
34 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | 34 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, NULL); |
35 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
36 | pptr = kmap(page); | 35 | pptr = kmap(page); |
37 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; | 36 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; |
38 | i = offset % 32; | 37 | i = offset % 32; |
@@ -72,8 +71,8 @@ int hfsplus_block_allocate(struct super_block *sb, u32 size, u32 offset, u32 *ma | |||
72 | offset += PAGE_CACHE_BITS; | 71 | offset += PAGE_CACHE_BITS; |
73 | if (offset >= size) | 72 | if (offset >= size) |
74 | break; | 73 | break; |
75 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | 74 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, |
76 | (filler_t *)mapping->a_ops->readpage, NULL); | 75 | NULL); |
77 | curr = pptr = kmap(page); | 76 | curr = pptr = kmap(page); |
78 | if ((size ^ offset) / PAGE_CACHE_BITS) | 77 | if ((size ^ offset) / PAGE_CACHE_BITS) |
79 | end = pptr + PAGE_CACHE_BITS / 32; | 78 | end = pptr + PAGE_CACHE_BITS / 32; |
@@ -119,8 +118,8 @@ found: | |||
119 | set_page_dirty(page); | 118 | set_page_dirty(page); |
120 | kunmap(page); | 119 | kunmap(page); |
121 | offset += PAGE_CACHE_BITS; | 120 | offset += PAGE_CACHE_BITS; |
122 | page = read_cache_page(mapping, offset / PAGE_CACHE_BITS, | 121 | page = read_mapping_page(mapping, offset / PAGE_CACHE_BITS, |
123 | (filler_t *)mapping->a_ops->readpage, NULL); | 122 | NULL); |
124 | pptr = kmap(page); | 123 | pptr = kmap(page); |
125 | curr = pptr; | 124 | curr = pptr; |
126 | end = pptr + PAGE_CACHE_BITS / 32; | 125 | end = pptr + PAGE_CACHE_BITS / 32; |
@@ -167,7 +166,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | |||
167 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); | 166 | mutex_lock(&HFSPLUS_SB(sb).alloc_file->i_mutex); |
168 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; | 167 | mapping = HFSPLUS_SB(sb).alloc_file->i_mapping; |
169 | pnr = offset / PAGE_CACHE_BITS; | 168 | pnr = offset / PAGE_CACHE_BITS; |
170 | page = read_cache_page(mapping, pnr, (filler_t *)mapping->a_ops->readpage, NULL); | 169 | page = read_mapping_page(mapping, pnr, NULL); |
171 | pptr = kmap(page); | 170 | pptr = kmap(page); |
172 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; | 171 | curr = pptr + (offset & (PAGE_CACHE_BITS - 1)) / 32; |
173 | end = pptr + PAGE_CACHE_BITS / 32; | 172 | end = pptr + PAGE_CACHE_BITS / 32; |
@@ -199,7 +198,7 @@ int hfsplus_block_free(struct super_block *sb, u32 offset, u32 count) | |||
199 | break; | 198 | break; |
200 | set_page_dirty(page); | 199 | set_page_dirty(page); |
201 | kunmap(page); | 200 | kunmap(page); |
202 | page = read_cache_page(mapping, ++pnr, (filler_t *)mapping->a_ops->readpage, NULL); | 201 | page = read_mapping_page(mapping, ++pnr, NULL); |
203 | pptr = kmap(page); | 202 | pptr = kmap(page); |
204 | curr = pptr; | 203 | curr = pptr; |
205 | end = pptr + PAGE_CACHE_BITS / 32; | 204 | end = pptr + PAGE_CACHE_BITS / 32; |
diff --git a/fs/hfsplus/bnode.c b/fs/hfsplus/bnode.c index 746abc9ecf70..77bf434da679 100644 --- a/fs/hfsplus/bnode.c +++ b/fs/hfsplus/bnode.c | |||
@@ -440,7 +440,7 @@ static struct hfs_bnode *__hfs_bnode_create(struct hfs_btree *tree, u32 cnid) | |||
440 | block = off >> PAGE_CACHE_SHIFT; | 440 | block = off >> PAGE_CACHE_SHIFT; |
441 | node->page_offset = off & ~PAGE_CACHE_MASK; | 441 | node->page_offset = off & ~PAGE_CACHE_MASK; |
442 | for (i = 0; i < tree->pages_per_bnode; block++, i++) { | 442 | for (i = 0; i < tree->pages_per_bnode; block++, i++) { |
443 | page = read_cache_page(mapping, block, (filler_t *)mapping->a_ops->readpage, NULL); | 443 | page = read_mapping_page(mapping, block, NULL); |
444 | if (IS_ERR(page)) | 444 | if (IS_ERR(page)) |
445 | goto fail; | 445 | goto fail; |
446 | if (PageError(page)) { | 446 | if (PageError(page)) { |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index effa8991999c..cfc852fdd1b5 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
@@ -38,7 +38,7 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
38 | goto free_tree; | 38 | goto free_tree; |
39 | 39 | ||
40 | mapping = tree->inode->i_mapping; | 40 | mapping = tree->inode->i_mapping; |
41 | page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, NULL); | 41 | page = read_mapping_page(mapping, 0, NULL); |
42 | if (IS_ERR(page)) | 42 | if (IS_ERR(page)) |
43 | goto free_tree; | 43 | goto free_tree; |
44 | 44 | ||
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index 7843f792a4b7..0a92fa2336a2 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
@@ -212,8 +212,10 @@ static void hfsplus_put_super(struct super_block *sb) | |||
212 | sb->s_fs_info = NULL; | 212 | sb->s_fs_info = NULL; |
213 | } | 213 | } |
214 | 214 | ||
215 | static int hfsplus_statfs(struct super_block *sb, struct kstatfs *buf) | 215 | static int hfsplus_statfs(struct dentry *dentry, struct kstatfs *buf) |
216 | { | 216 | { |
217 | struct super_block *sb = dentry->d_sb; | ||
218 | |||
217 | buf->f_type = HFSPLUS_SUPER_MAGIC; | 219 | buf->f_type = HFSPLUS_SUPER_MAGIC; |
218 | buf->f_bsize = sb->s_blocksize; | 220 | buf->f_bsize = sb->s_blocksize; |
219 | buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; | 221 | buf->f_blocks = HFSPLUS_SB(sb).total_blocks << HFSPLUS_SB(sb).fs_shift; |
@@ -450,10 +452,12 @@ static void hfsplus_destroy_inode(struct inode *inode) | |||
450 | 452 | ||
451 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) | 453 | #define HFSPLUS_INODE_SIZE sizeof(struct hfsplus_inode_info) |
452 | 454 | ||
453 | static struct super_block *hfsplus_get_sb(struct file_system_type *fs_type, | 455 | static int hfsplus_get_sb(struct file_system_type *fs_type, |
454 | int flags, const char *dev_name, void *data) | 456 | int flags, const char *dev_name, void *data, |
457 | struct vfsmount *mnt) | ||
455 | { | 458 | { |
456 | return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super); | 459 | return get_sb_bdev(fs_type, flags, dev_name, data, hfsplus_fill_super, |
460 | mnt); | ||
457 | } | 461 | } |
458 | 462 | ||
459 | static struct file_system_type hfsplus_fs_type = { | 463 | static struct file_system_type hfsplus_fs_type = { |
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index bf0f8e16e433..8e0d37743e7c 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c | |||
@@ -239,7 +239,7 @@ static int read_inode(struct inode *ino) | |||
239 | return(err); | 239 | return(err); |
240 | } | 240 | } |
241 | 241 | ||
242 | int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) | 242 | int hostfs_statfs(struct dentry *dentry, struct kstatfs *sf) |
243 | { | 243 | { |
244 | /* do_statfs uses struct statfs64 internally, but the linux kernel | 244 | /* do_statfs uses struct statfs64 internally, but the linux kernel |
245 | * struct statfs still has 32-bit versions for most of these fields, | 245 | * struct statfs still has 32-bit versions for most of these fields, |
@@ -252,7 +252,7 @@ int hostfs_statfs(struct super_block *sb, struct kstatfs *sf) | |||
252 | long long f_files; | 252 | long long f_files; |
253 | long long f_ffree; | 253 | long long f_ffree; |
254 | 254 | ||
255 | err = do_statfs(HOSTFS_I(sb->s_root->d_inode)->host_filename, | 255 | err = do_statfs(HOSTFS_I(dentry->d_sb->s_root->d_inode)->host_filename, |
256 | &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, | 256 | &sf->f_bsize, &f_blocks, &f_bfree, &f_bavail, &f_files, |
257 | &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), | 257 | &f_ffree, &sf->f_fsid, sizeof(sf->f_fsid), |
258 | &sf->f_namelen, sf->f_spare); | 258 | &sf->f_namelen, sf->f_spare); |
@@ -993,11 +993,11 @@ static int hostfs_fill_sb_common(struct super_block *sb, void *d, int silent) | |||
993 | return(err); | 993 | return(err); |
994 | } | 994 | } |
995 | 995 | ||
996 | static struct super_block *hostfs_read_sb(struct file_system_type *type, | 996 | static int hostfs_read_sb(struct file_system_type *type, |
997 | int flags, const char *dev_name, | 997 | int flags, const char *dev_name, |
998 | void *data) | 998 | void *data, struct vfsmount *mnt) |
999 | { | 999 | { |
1000 | return(get_sb_nodev(type, flags, data, hostfs_fill_sb_common)); | 1000 | return get_sb_nodev(type, flags, data, hostfs_fill_sb_common, mnt); |
1001 | } | 1001 | } |
1002 | 1002 | ||
1003 | static struct file_system_type hostfs_type = { | 1003 | static struct file_system_type hostfs_type = { |
diff --git a/fs/hpfs/super.c b/fs/hpfs/super.c index d72d8c87c996..f798480a363f 100644 --- a/fs/hpfs/super.c +++ b/fs/hpfs/super.c | |||
@@ -135,8 +135,9 @@ static unsigned count_bitmaps(struct super_block *s) | |||
135 | return count; | 135 | return count; |
136 | } | 136 | } |
137 | 137 | ||
138 | static int hpfs_statfs(struct super_block *s, struct kstatfs *buf) | 138 | static int hpfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
139 | { | 139 | { |
140 | struct super_block *s = dentry->d_sb; | ||
140 | struct hpfs_sb_info *sbi = hpfs_sb(s); | 141 | struct hpfs_sb_info *sbi = hpfs_sb(s); |
141 | lock_kernel(); | 142 | lock_kernel(); |
142 | 143 | ||
@@ -662,10 +663,11 @@ bail0: | |||
662 | return -EINVAL; | 663 | return -EINVAL; |
663 | } | 664 | } |
664 | 665 | ||
665 | static struct super_block *hpfs_get_sb(struct file_system_type *fs_type, | 666 | static int hpfs_get_sb(struct file_system_type *fs_type, |
666 | int flags, const char *dev_name, void *data) | 667 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
667 | { | 668 | { |
668 | return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super); | 669 | return get_sb_bdev(fs_type, flags, dev_name, data, hpfs_fill_super, |
670 | mnt); | ||
669 | } | 671 | } |
670 | 672 | ||
671 | static struct file_system_type hpfs_fs_type = { | 673 | static struct file_system_type hpfs_fs_type = { |
diff --git a/fs/hppfs/hppfs_kern.c b/fs/hppfs/hppfs_kern.c index 5e6363be246f..3a9bdf58166f 100644 --- a/fs/hppfs/hppfs_kern.c +++ b/fs/hppfs/hppfs_kern.c | |||
@@ -616,7 +616,7 @@ static const struct file_operations hppfs_dir_fops = { | |||
616 | .fsync = hppfs_fsync, | 616 | .fsync = hppfs_fsync, |
617 | }; | 617 | }; |
618 | 618 | ||
619 | static int hppfs_statfs(struct super_block *sb, struct kstatfs *sf) | 619 | static int hppfs_statfs(struct dentry *dentry, struct kstatfs *sf) |
620 | { | 620 | { |
621 | sf->f_blocks = 0; | 621 | sf->f_blocks = 0; |
622 | sf->f_bfree = 0; | 622 | sf->f_bfree = 0; |
@@ -769,11 +769,11 @@ static int hppfs_fill_super(struct super_block *sb, void *d, int silent) | |||
769 | return(err); | 769 | return(err); |
770 | } | 770 | } |
771 | 771 | ||
772 | static struct super_block *hppfs_read_super(struct file_system_type *type, | 772 | static int hppfs_read_super(struct file_system_type *type, |
773 | int flags, const char *dev_name, | 773 | int flags, const char *dev_name, |
774 | void *data) | 774 | void *data, struct vfsmount *mnt) |
775 | { | 775 | { |
776 | return(get_sb_nodev(type, flags, data, hppfs_fill_super)); | 776 | return get_sb_nodev(type, flags, data, hppfs_fill_super, mnt); |
777 | } | 777 | } |
778 | 778 | ||
779 | static struct file_system_type hppfs_type = { | 779 | static struct file_system_type hppfs_type = { |
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 3a5b4e923455..e6410d8edd0e 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
@@ -59,7 +59,6 @@ static void huge_pagevec_release(struct pagevec *pvec) | |||
59 | static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | 59 | static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) |
60 | { | 60 | { |
61 | struct inode *inode = file->f_dentry->d_inode; | 61 | struct inode *inode = file->f_dentry->d_inode; |
62 | struct hugetlbfs_inode_info *info = HUGETLBFS_I(inode); | ||
63 | loff_t len, vma_len; | 62 | loff_t len, vma_len; |
64 | int ret; | 63 | int ret; |
65 | 64 | ||
@@ -87,9 +86,10 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma) | |||
87 | if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) | 86 | if (!(vma->vm_flags & VM_WRITE) && len > inode->i_size) |
88 | goto out; | 87 | goto out; |
89 | 88 | ||
90 | if (vma->vm_flags & VM_MAYSHARE) | 89 | if (vma->vm_flags & VM_MAYSHARE && |
91 | if (hugetlb_extend_reservation(info, len >> HPAGE_SHIFT) != 0) | 90 | hugetlb_reserve_pages(inode, vma->vm_pgoff >> (HPAGE_SHIFT-PAGE_SHIFT), |
92 | goto out; | 91 | len >> HPAGE_SHIFT)) |
92 | goto out; | ||
93 | 93 | ||
94 | ret = 0; | 94 | ret = 0; |
95 | hugetlb_prefault_arch_hook(vma->vm_mm); | 95 | hugetlb_prefault_arch_hook(vma->vm_mm); |
@@ -195,12 +195,8 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) | |||
195 | const pgoff_t start = lstart >> HPAGE_SHIFT; | 195 | const pgoff_t start = lstart >> HPAGE_SHIFT; |
196 | struct pagevec pvec; | 196 | struct pagevec pvec; |
197 | pgoff_t next; | 197 | pgoff_t next; |
198 | int i; | 198 | int i, freed = 0; |
199 | 199 | ||
200 | hugetlb_truncate_reservation(HUGETLBFS_I(inode), | ||
201 | lstart >> HPAGE_SHIFT); | ||
202 | if (!mapping->nrpages) | ||
203 | return; | ||
204 | pagevec_init(&pvec, 0); | 200 | pagevec_init(&pvec, 0); |
205 | next = start; | 201 | next = start; |
206 | while (1) { | 202 | while (1) { |
@@ -221,10 +217,12 @@ static void truncate_hugepages(struct inode *inode, loff_t lstart) | |||
221 | truncate_huge_page(page); | 217 | truncate_huge_page(page); |
222 | unlock_page(page); | 218 | unlock_page(page); |
223 | hugetlb_put_quota(mapping); | 219 | hugetlb_put_quota(mapping); |
220 | freed++; | ||
224 | } | 221 | } |
225 | huge_pagevec_release(&pvec); | 222 | huge_pagevec_release(&pvec); |
226 | } | 223 | } |
227 | BUG_ON(!lstart && mapping->nrpages); | 224 | BUG_ON(!lstart && mapping->nrpages); |
225 | hugetlb_unreserve_pages(inode, start, freed); | ||
228 | } | 226 | } |
229 | 227 | ||
230 | static void hugetlbfs_delete_inode(struct inode *inode) | 228 | static void hugetlbfs_delete_inode(struct inode *inode) |
@@ -366,6 +364,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, | |||
366 | inode->i_mapping->a_ops = &hugetlbfs_aops; | 364 | inode->i_mapping->a_ops = &hugetlbfs_aops; |
367 | inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; | 365 | inode->i_mapping->backing_dev_info =&hugetlbfs_backing_dev_info; |
368 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; | 366 | inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; |
367 | INIT_LIST_HEAD(&inode->i_mapping->private_list); | ||
369 | info = HUGETLBFS_I(inode); | 368 | info = HUGETLBFS_I(inode); |
370 | mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); | 369 | mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); |
371 | switch (mode & S_IFMT) { | 370 | switch (mode & S_IFMT) { |
@@ -467,9 +466,9 @@ static int hugetlbfs_set_page_dirty(struct page *page) | |||
467 | return 0; | 466 | return 0; |
468 | } | 467 | } |
469 | 468 | ||
470 | static int hugetlbfs_statfs(struct super_block *sb, struct kstatfs *buf) | 469 | static int hugetlbfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
471 | { | 470 | { |
472 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(sb); | 471 | struct hugetlbfs_sb_info *sbinfo = HUGETLBFS_SB(dentry->d_sb); |
473 | 472 | ||
474 | buf->f_type = HUGETLBFS_MAGIC; | 473 | buf->f_type = HUGETLBFS_MAGIC; |
475 | buf->f_bsize = HPAGE_SIZE; | 474 | buf->f_bsize = HPAGE_SIZE; |
@@ -538,7 +537,6 @@ static struct inode *hugetlbfs_alloc_inode(struct super_block *sb) | |||
538 | hugetlbfs_inc_free_inodes(sbinfo); | 537 | hugetlbfs_inc_free_inodes(sbinfo); |
539 | return NULL; | 538 | return NULL; |
540 | } | 539 | } |
541 | p->prereserved_hpages = 0; | ||
542 | return &p->vfs_inode; | 540 | return &p->vfs_inode; |
543 | } | 541 | } |
544 | 542 | ||
@@ -723,10 +721,10 @@ void hugetlb_put_quota(struct address_space *mapping) | |||
723 | } | 721 | } |
724 | } | 722 | } |
725 | 723 | ||
726 | static struct super_block *hugetlbfs_get_sb(struct file_system_type *fs_type, | 724 | static int hugetlbfs_get_sb(struct file_system_type *fs_type, |
727 | int flags, const char *dev_name, void *data) | 725 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
728 | { | 726 | { |
729 | return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super); | 727 | return get_sb_nodev(fs_type, flags, data, hugetlbfs_fill_super, mnt); |
730 | } | 728 | } |
731 | 729 | ||
732 | static struct file_system_type hugetlbfs_fs_type = { | 730 | static struct file_system_type hugetlbfs_fs_type = { |
@@ -781,8 +779,7 @@ struct file *hugetlb_zero_setup(size_t size) | |||
781 | goto out_file; | 779 | goto out_file; |
782 | 780 | ||
783 | error = -ENOMEM; | 781 | error = -ENOMEM; |
784 | if (hugetlb_extend_reservation(HUGETLBFS_I(inode), | 782 | if (hugetlb_reserve_pages(inode, 0, size >> HPAGE_SHIFT)) |
785 | size >> HPAGE_SHIFT) != 0) | ||
786 | goto out_inode; | 783 | goto out_inode; |
787 | 784 | ||
788 | d_instantiate(dentry, inode); | 785 | d_instantiate(dentry, inode); |
diff --git a/fs/inotify.c b/fs/inotify.c index 732ec4bd5774..723836a1f718 100644 --- a/fs/inotify.c +++ b/fs/inotify.c | |||
@@ -5,7 +5,10 @@ | |||
5 | * John McCutchan <ttb@tentacle.dhs.org> | 5 | * John McCutchan <ttb@tentacle.dhs.org> |
6 | * Robert Love <rml@novell.com> | 6 | * Robert Love <rml@novell.com> |
7 | * | 7 | * |
8 | * Kernel API added by: Amy Griffis <amy.griffis@hp.com> | ||
9 | * | ||
8 | * Copyright (C) 2005 John McCutchan | 10 | * Copyright (C) 2005 John McCutchan |
11 | * Copyright 2006 Hewlett-Packard Development Company, L.P. | ||
9 | * | 12 | * |
10 | * This program is free software; you can redistribute it and/or modify it | 13 | * This program is free software; you can redistribute it and/or modify it |
11 | * under the terms of the GNU General Public License as published by the | 14 | * under the terms of the GNU General Public License as published by the |
@@ -20,35 +23,17 @@ | |||
20 | 23 | ||
21 | #include <linux/module.h> | 24 | #include <linux/module.h> |
22 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
23 | #include <linux/sched.h> | ||
24 | #include <linux/spinlock.h> | 26 | #include <linux/spinlock.h> |
25 | #include <linux/idr.h> | 27 | #include <linux/idr.h> |
26 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
27 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
28 | #include <linux/file.h> | ||
29 | #include <linux/mount.h> | ||
30 | #include <linux/namei.h> | ||
31 | #include <linux/poll.h> | ||
32 | #include <linux/init.h> | 30 | #include <linux/init.h> |
33 | #include <linux/list.h> | 31 | #include <linux/list.h> |
34 | #include <linux/writeback.h> | 32 | #include <linux/writeback.h> |
35 | #include <linux/inotify.h> | 33 | #include <linux/inotify.h> |
36 | #include <linux/syscalls.h> | ||
37 | |||
38 | #include <asm/ioctls.h> | ||
39 | 34 | ||
40 | static atomic_t inotify_cookie; | 35 | static atomic_t inotify_cookie; |
41 | 36 | ||
42 | static kmem_cache_t *watch_cachep __read_mostly; | ||
43 | static kmem_cache_t *event_cachep __read_mostly; | ||
44 | |||
45 | static struct vfsmount *inotify_mnt __read_mostly; | ||
46 | |||
47 | /* these are configurable via /proc/sys/fs/inotify/ */ | ||
48 | int inotify_max_user_instances __read_mostly; | ||
49 | int inotify_max_user_watches __read_mostly; | ||
50 | int inotify_max_queued_events __read_mostly; | ||
51 | |||
52 | /* | 37 | /* |
53 | * Lock ordering: | 38 | * Lock ordering: |
54 | * | 39 | * |
@@ -56,327 +41,108 @@ int inotify_max_queued_events __read_mostly; | |||
56 | * iprune_mutex (synchronize shrink_icache_memory()) | 41 | * iprune_mutex (synchronize shrink_icache_memory()) |
57 | * inode_lock (protects the super_block->s_inodes list) | 42 | * inode_lock (protects the super_block->s_inodes list) |
58 | * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) | 43 | * inode->inotify_mutex (protects inode->inotify_watches and watches->i_list) |
59 | * inotify_dev->mutex (protects inotify_device and watches->d_list) | 44 | * inotify_handle->mutex (protects inotify_handle and watches->h_list) |
45 | * | ||
46 | * The inode->inotify_mutex and inotify_handle->mutex and held during execution | ||
47 | * of a caller's event handler. Thus, the caller must not hold any locks | ||
48 | * taken in their event handler while calling any of the published inotify | ||
49 | * interfaces. | ||
60 | */ | 50 | */ |
61 | 51 | ||
62 | /* | 52 | /* |
63 | * Lifetimes of the three main data structures--inotify_device, inode, and | 53 | * Lifetimes of the three main data structures--inotify_handle, inode, and |
64 | * inotify_watch--are managed by reference count. | 54 | * inotify_watch--are managed by reference count. |
65 | * | 55 | * |
66 | * inotify_device: Lifetime is from inotify_init() until release. Additional | 56 | * inotify_handle: Lifetime is from inotify_init() to inotify_destroy(). |
67 | * references can bump the count via get_inotify_dev() and drop the count via | 57 | * Additional references can bump the count via get_inotify_handle() and drop |
68 | * put_inotify_dev(). | 58 | * the count via put_inotify_handle(). |
69 | * | 59 | * |
70 | * inotify_watch: Lifetime is from create_watch() to destory_watch(). | 60 | * inotify_watch: for inotify's purposes, lifetime is from inotify_add_watch() |
71 | * Additional references can bump the count via get_inotify_watch() and drop | 61 | * to remove_watch_no_event(). Additional references can bump the count via |
72 | * the count via put_inotify_watch(). | 62 | * get_inotify_watch() and drop the count via put_inotify_watch(). The caller |
63 | * is reponsible for the final put after receiving IN_IGNORED, or when using | ||
64 | * IN_ONESHOT after receiving the first event. Inotify does the final put if | ||
65 | * inotify_destroy() is called. | ||
73 | * | 66 | * |
74 | * inode: Pinned so long as the inode is associated with a watch, from | 67 | * inode: Pinned so long as the inode is associated with a watch, from |
75 | * create_watch() to put_inotify_watch(). | 68 | * inotify_add_watch() to the final put_inotify_watch(). |
76 | */ | 69 | */ |
77 | 70 | ||
78 | /* | 71 | /* |
79 | * struct inotify_device - represents an inotify instance | 72 | * struct inotify_handle - represents an inotify instance |
80 | * | 73 | * |
81 | * This structure is protected by the mutex 'mutex'. | 74 | * This structure is protected by the mutex 'mutex'. |
82 | */ | 75 | */ |
83 | struct inotify_device { | 76 | struct inotify_handle { |
84 | wait_queue_head_t wq; /* wait queue for i/o */ | ||
85 | struct idr idr; /* idr mapping wd -> watch */ | 77 | struct idr idr; /* idr mapping wd -> watch */ |
86 | struct mutex mutex; /* protects this bad boy */ | 78 | struct mutex mutex; /* protects this bad boy */ |
87 | struct list_head events; /* list of queued events */ | ||
88 | struct list_head watches; /* list of watches */ | 79 | struct list_head watches; /* list of watches */ |
89 | atomic_t count; /* reference count */ | 80 | atomic_t count; /* reference count */ |
90 | struct user_struct *user; /* user who opened this dev */ | ||
91 | unsigned int queue_size; /* size of the queue (bytes) */ | ||
92 | unsigned int event_count; /* number of pending events */ | ||
93 | unsigned int max_events; /* maximum number of events */ | ||
94 | u32 last_wd; /* the last wd allocated */ | 81 | u32 last_wd; /* the last wd allocated */ |
82 | const struct inotify_operations *in_ops; /* inotify caller operations */ | ||
95 | }; | 83 | }; |
96 | 84 | ||
97 | /* | 85 | static inline void get_inotify_handle(struct inotify_handle *ih) |
98 | * struct inotify_kernel_event - An inotify event, originating from a watch and | ||
99 | * queued for user-space. A list of these is attached to each instance of the | ||
100 | * device. In read(), this list is walked and all events that can fit in the | ||
101 | * buffer are returned. | ||
102 | * | ||
103 | * Protected by dev->mutex of the device in which we are queued. | ||
104 | */ | ||
105 | struct inotify_kernel_event { | ||
106 | struct inotify_event event; /* the user-space event */ | ||
107 | struct list_head list; /* entry in inotify_device's list */ | ||
108 | char *name; /* filename, if any */ | ||
109 | }; | ||
110 | |||
111 | /* | ||
112 | * struct inotify_watch - represents a watch request on a specific inode | ||
113 | * | ||
114 | * d_list is protected by dev->mutex of the associated watch->dev. | ||
115 | * i_list and mask are protected by inode->inotify_mutex of the associated inode. | ||
116 | * dev, inode, and wd are never written to once the watch is created. | ||
117 | */ | ||
118 | struct inotify_watch { | ||
119 | struct list_head d_list; /* entry in inotify_device's list */ | ||
120 | struct list_head i_list; /* entry in inode's list */ | ||
121 | atomic_t count; /* reference count */ | ||
122 | struct inotify_device *dev; /* associated device */ | ||
123 | struct inode *inode; /* associated inode */ | ||
124 | s32 wd; /* watch descriptor */ | ||
125 | u32 mask; /* event mask for this watch */ | ||
126 | }; | ||
127 | |||
128 | #ifdef CONFIG_SYSCTL | ||
129 | |||
130 | #include <linux/sysctl.h> | ||
131 | |||
132 | static int zero; | ||
133 | |||
134 | ctl_table inotify_table[] = { | ||
135 | { | ||
136 | .ctl_name = INOTIFY_MAX_USER_INSTANCES, | ||
137 | .procname = "max_user_instances", | ||
138 | .data = &inotify_max_user_instances, | ||
139 | .maxlen = sizeof(int), | ||
140 | .mode = 0644, | ||
141 | .proc_handler = &proc_dointvec_minmax, | ||
142 | .strategy = &sysctl_intvec, | ||
143 | .extra1 = &zero, | ||
144 | }, | ||
145 | { | ||
146 | .ctl_name = INOTIFY_MAX_USER_WATCHES, | ||
147 | .procname = "max_user_watches", | ||
148 | .data = &inotify_max_user_watches, | ||
149 | .maxlen = sizeof(int), | ||
150 | .mode = 0644, | ||
151 | .proc_handler = &proc_dointvec_minmax, | ||
152 | .strategy = &sysctl_intvec, | ||
153 | .extra1 = &zero, | ||
154 | }, | ||
155 | { | ||
156 | .ctl_name = INOTIFY_MAX_QUEUED_EVENTS, | ||
157 | .procname = "max_queued_events", | ||
158 | .data = &inotify_max_queued_events, | ||
159 | .maxlen = sizeof(int), | ||
160 | .mode = 0644, | ||
161 | .proc_handler = &proc_dointvec_minmax, | ||
162 | .strategy = &sysctl_intvec, | ||
163 | .extra1 = &zero | ||
164 | }, | ||
165 | { .ctl_name = 0 } | ||
166 | }; | ||
167 | #endif /* CONFIG_SYSCTL */ | ||
168 | |||
169 | static inline void get_inotify_dev(struct inotify_device *dev) | ||
170 | { | 86 | { |
171 | atomic_inc(&dev->count); | 87 | atomic_inc(&ih->count); |
172 | } | 88 | } |
173 | 89 | ||
174 | static inline void put_inotify_dev(struct inotify_device *dev) | 90 | static inline void put_inotify_handle(struct inotify_handle *ih) |
175 | { | 91 | { |
176 | if (atomic_dec_and_test(&dev->count)) { | 92 | if (atomic_dec_and_test(&ih->count)) { |
177 | atomic_dec(&dev->user->inotify_devs); | 93 | idr_destroy(&ih->idr); |
178 | free_uid(dev->user); | 94 | kfree(ih); |
179 | idr_destroy(&dev->idr); | ||
180 | kfree(dev); | ||
181 | } | 95 | } |
182 | } | 96 | } |
183 | 97 | ||
184 | static inline void get_inotify_watch(struct inotify_watch *watch) | 98 | /** |
99 | * get_inotify_watch - grab a reference to an inotify_watch | ||
100 | * @watch: watch to grab | ||
101 | */ | ||
102 | void get_inotify_watch(struct inotify_watch *watch) | ||
185 | { | 103 | { |
186 | atomic_inc(&watch->count); | 104 | atomic_inc(&watch->count); |
187 | } | 105 | } |
106 | EXPORT_SYMBOL_GPL(get_inotify_watch); | ||
188 | 107 | ||
189 | /* | 108 | /** |
190 | * put_inotify_watch - decrements the ref count on a given watch. cleans up | 109 | * put_inotify_watch - decrements the ref count on a given watch. cleans up |
191 | * the watch and its references if the count reaches zero. | 110 | * watch references if the count reaches zero. inotify_watch is freed by |
111 | * inotify callers via the destroy_watch() op. | ||
112 | * @watch: watch to release | ||
192 | */ | 113 | */ |
193 | static inline void put_inotify_watch(struct inotify_watch *watch) | 114 | void put_inotify_watch(struct inotify_watch *watch) |
194 | { | 115 | { |
195 | if (atomic_dec_and_test(&watch->count)) { | 116 | if (atomic_dec_and_test(&watch->count)) { |
196 | put_inotify_dev(watch->dev); | 117 | struct inotify_handle *ih = watch->ih; |
197 | iput(watch->inode); | ||
198 | kmem_cache_free(watch_cachep, watch); | ||
199 | } | ||
200 | } | ||
201 | |||
202 | /* | ||
203 | * kernel_event - create a new kernel event with the given parameters | ||
204 | * | ||
205 | * This function can sleep. | ||
206 | */ | ||
207 | static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, | ||
208 | const char *name) | ||
209 | { | ||
210 | struct inotify_kernel_event *kevent; | ||
211 | |||
212 | kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL); | ||
213 | if (unlikely(!kevent)) | ||
214 | return NULL; | ||
215 | |||
216 | /* we hand this out to user-space, so zero it just in case */ | ||
217 | memset(&kevent->event, 0, sizeof(struct inotify_event)); | ||
218 | |||
219 | kevent->event.wd = wd; | ||
220 | kevent->event.mask = mask; | ||
221 | kevent->event.cookie = cookie; | ||
222 | |||
223 | INIT_LIST_HEAD(&kevent->list); | ||
224 | |||
225 | if (name) { | ||
226 | size_t len, rem, event_size = sizeof(struct inotify_event); | ||
227 | |||
228 | /* | ||
229 | * We need to pad the filename so as to properly align an | ||
230 | * array of inotify_event structures. Because the structure is | ||
231 | * small and the common case is a small filename, we just round | ||
232 | * up to the next multiple of the structure's sizeof. This is | ||
233 | * simple and safe for all architectures. | ||
234 | */ | ||
235 | len = strlen(name) + 1; | ||
236 | rem = event_size - len; | ||
237 | if (len > event_size) { | ||
238 | rem = event_size - (len % event_size); | ||
239 | if (len % event_size == 0) | ||
240 | rem = 0; | ||
241 | } | ||
242 | |||
243 | kevent->name = kmalloc(len + rem, GFP_KERNEL); | ||
244 | if (unlikely(!kevent->name)) { | ||
245 | kmem_cache_free(event_cachep, kevent); | ||
246 | return NULL; | ||
247 | } | ||
248 | memcpy(kevent->name, name, len); | ||
249 | if (rem) | ||
250 | memset(kevent->name + len, 0, rem); | ||
251 | kevent->event.len = len + rem; | ||
252 | } else { | ||
253 | kevent->event.len = 0; | ||
254 | kevent->name = NULL; | ||
255 | } | ||
256 | |||
257 | return kevent; | ||
258 | } | ||
259 | |||
260 | /* | ||
261 | * inotify_dev_get_event - return the next event in the given dev's queue | ||
262 | * | ||
263 | * Caller must hold dev->mutex. | ||
264 | */ | ||
265 | static inline struct inotify_kernel_event * | ||
266 | inotify_dev_get_event(struct inotify_device *dev) | ||
267 | { | ||
268 | return list_entry(dev->events.next, struct inotify_kernel_event, list); | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * inotify_dev_queue_event - add a new event to the given device | ||
273 | * | ||
274 | * Caller must hold dev->mutex. Can sleep (calls kernel_event()). | ||
275 | */ | ||
276 | static void inotify_dev_queue_event(struct inotify_device *dev, | ||
277 | struct inotify_watch *watch, u32 mask, | ||
278 | u32 cookie, const char *name) | ||
279 | { | ||
280 | struct inotify_kernel_event *kevent, *last; | ||
281 | |||
282 | /* coalescing: drop this event if it is a dupe of the previous */ | ||
283 | last = inotify_dev_get_event(dev); | ||
284 | if (last && last->event.mask == mask && last->event.wd == watch->wd && | ||
285 | last->event.cookie == cookie) { | ||
286 | const char *lastname = last->name; | ||
287 | |||
288 | if (!name && !lastname) | ||
289 | return; | ||
290 | if (name && lastname && !strcmp(lastname, name)) | ||
291 | return; | ||
292 | } | ||
293 | |||
294 | /* the queue overflowed and we already sent the Q_OVERFLOW event */ | ||
295 | if (unlikely(dev->event_count > dev->max_events)) | ||
296 | return; | ||
297 | |||
298 | /* if the queue overflows, we need to notify user space */ | ||
299 | if (unlikely(dev->event_count == dev->max_events)) | ||
300 | kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL); | ||
301 | else | ||
302 | kevent = kernel_event(watch->wd, mask, cookie, name); | ||
303 | |||
304 | if (unlikely(!kevent)) | ||
305 | return; | ||
306 | |||
307 | /* queue the event and wake up anyone waiting */ | ||
308 | dev->event_count++; | ||
309 | dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; | ||
310 | list_add_tail(&kevent->list, &dev->events); | ||
311 | wake_up_interruptible(&dev->wq); | ||
312 | } | ||
313 | |||
314 | /* | ||
315 | * remove_kevent - cleans up and ultimately frees the given kevent | ||
316 | * | ||
317 | * Caller must hold dev->mutex. | ||
318 | */ | ||
319 | static void remove_kevent(struct inotify_device *dev, | ||
320 | struct inotify_kernel_event *kevent) | ||
321 | { | ||
322 | list_del(&kevent->list); | ||
323 | |||
324 | dev->event_count--; | ||
325 | dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; | ||
326 | |||
327 | kfree(kevent->name); | ||
328 | kmem_cache_free(event_cachep, kevent); | ||
329 | } | ||
330 | 118 | ||
331 | /* | 119 | iput(watch->inode); |
332 | * inotify_dev_event_dequeue - destroy an event on the given device | 120 | ih->in_ops->destroy_watch(watch); |
333 | * | 121 | put_inotify_handle(ih); |
334 | * Caller must hold dev->mutex. | ||
335 | */ | ||
336 | static void inotify_dev_event_dequeue(struct inotify_device *dev) | ||
337 | { | ||
338 | if (!list_empty(&dev->events)) { | ||
339 | struct inotify_kernel_event *kevent; | ||
340 | kevent = inotify_dev_get_event(dev); | ||
341 | remove_kevent(dev, kevent); | ||
342 | } | 122 | } |
343 | } | 123 | } |
124 | EXPORT_SYMBOL_GPL(put_inotify_watch); | ||
344 | 125 | ||
345 | /* | 126 | /* |
346 | * inotify_dev_get_wd - returns the next WD for use by the given dev | 127 | * inotify_handle_get_wd - returns the next WD for use by the given handle |
347 | * | 128 | * |
348 | * Callers must hold dev->mutex. This function can sleep. | 129 | * Callers must hold ih->mutex. This function can sleep. |
349 | */ | 130 | */ |
350 | static int inotify_dev_get_wd(struct inotify_device *dev, | 131 | static int inotify_handle_get_wd(struct inotify_handle *ih, |
351 | struct inotify_watch *watch) | 132 | struct inotify_watch *watch) |
352 | { | 133 | { |
353 | int ret; | 134 | int ret; |
354 | 135 | ||
355 | do { | 136 | do { |
356 | if (unlikely(!idr_pre_get(&dev->idr, GFP_KERNEL))) | 137 | if (unlikely(!idr_pre_get(&ih->idr, GFP_KERNEL))) |
357 | return -ENOSPC; | 138 | return -ENOSPC; |
358 | ret = idr_get_new_above(&dev->idr, watch, dev->last_wd+1, &watch->wd); | 139 | ret = idr_get_new_above(&ih->idr, watch, ih->last_wd+1, &watch->wd); |
359 | } while (ret == -EAGAIN); | 140 | } while (ret == -EAGAIN); |
360 | 141 | ||
361 | return ret; | 142 | if (likely(!ret)) |
362 | } | 143 | ih->last_wd = watch->wd; |
363 | 144 | ||
364 | /* | 145 | return ret; |
365 | * find_inode - resolve a user-given path to a specific inode and return a nd | ||
366 | */ | ||
367 | static int find_inode(const char __user *dirname, struct nameidata *nd, | ||
368 | unsigned flags) | ||
369 | { | ||
370 | int error; | ||
371 | |||
372 | error = __user_walk(dirname, flags, nd); | ||
373 | if (error) | ||
374 | return error; | ||
375 | /* you can only watch an inode if you have read permissions on it */ | ||
376 | error = vfs_permission(nd, MAY_READ); | ||
377 | if (error) | ||
378 | path_release(nd); | ||
379 | return error; | ||
380 | } | 146 | } |
381 | 147 | ||
382 | /* | 148 | /* |
@@ -422,67 +188,18 @@ static void set_dentry_child_flags(struct inode *inode, int watched) | |||
422 | } | 188 | } |
423 | 189 | ||
424 | /* | 190 | /* |
425 | * create_watch - creates a watch on the given device. | 191 | * inotify_find_handle - find the watch associated with the given inode and |
426 | * | 192 | * handle |
427 | * Callers must hold dev->mutex. Calls inotify_dev_get_wd() so may sleep. | ||
428 | * Both 'dev' and 'inode' (by way of nameidata) need to be pinned. | ||
429 | */ | ||
430 | static struct inotify_watch *create_watch(struct inotify_device *dev, | ||
431 | u32 mask, struct inode *inode) | ||
432 | { | ||
433 | struct inotify_watch *watch; | ||
434 | int ret; | ||
435 | |||
436 | if (atomic_read(&dev->user->inotify_watches) >= | ||
437 | inotify_max_user_watches) | ||
438 | return ERR_PTR(-ENOSPC); | ||
439 | |||
440 | watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); | ||
441 | if (unlikely(!watch)) | ||
442 | return ERR_PTR(-ENOMEM); | ||
443 | |||
444 | ret = inotify_dev_get_wd(dev, watch); | ||
445 | if (unlikely(ret)) { | ||
446 | kmem_cache_free(watch_cachep, watch); | ||
447 | return ERR_PTR(ret); | ||
448 | } | ||
449 | |||
450 | dev->last_wd = watch->wd; | ||
451 | watch->mask = mask; | ||
452 | atomic_set(&watch->count, 0); | ||
453 | INIT_LIST_HEAD(&watch->d_list); | ||
454 | INIT_LIST_HEAD(&watch->i_list); | ||
455 | |||
456 | /* save a reference to device and bump the count to make it official */ | ||
457 | get_inotify_dev(dev); | ||
458 | watch->dev = dev; | ||
459 | |||
460 | /* | ||
461 | * Save a reference to the inode and bump the ref count to make it | ||
462 | * official. We hold a reference to nameidata, which makes this safe. | ||
463 | */ | ||
464 | watch->inode = igrab(inode); | ||
465 | |||
466 | /* bump our own count, corresponding to our entry in dev->watches */ | ||
467 | get_inotify_watch(watch); | ||
468 | |||
469 | atomic_inc(&dev->user->inotify_watches); | ||
470 | |||
471 | return watch; | ||
472 | } | ||
473 | |||
474 | /* | ||
475 | * inotify_find_dev - find the watch associated with the given inode and dev | ||
476 | * | 193 | * |
477 | * Callers must hold inode->inotify_mutex. | 194 | * Callers must hold inode->inotify_mutex. |
478 | */ | 195 | */ |
479 | static struct inotify_watch *inode_find_dev(struct inode *inode, | 196 | static struct inotify_watch *inode_find_handle(struct inode *inode, |
480 | struct inotify_device *dev) | 197 | struct inotify_handle *ih) |
481 | { | 198 | { |
482 | struct inotify_watch *watch; | 199 | struct inotify_watch *watch; |
483 | 200 | ||
484 | list_for_each_entry(watch, &inode->inotify_watches, i_list) { | 201 | list_for_each_entry(watch, &inode->inotify_watches, i_list) { |
485 | if (watch->dev == dev) | 202 | if (watch->ih == ih) |
486 | return watch; | 203 | return watch; |
487 | } | 204 | } |
488 | 205 | ||
@@ -490,40 +207,40 @@ static struct inotify_watch *inode_find_dev(struct inode *inode, | |||
490 | } | 207 | } |
491 | 208 | ||
492 | /* | 209 | /* |
493 | * remove_watch_no_event - remove_watch() without the IN_IGNORED event. | 210 | * remove_watch_no_event - remove watch without the IN_IGNORED event. |
211 | * | ||
212 | * Callers must hold both inode->inotify_mutex and ih->mutex. | ||
494 | */ | 213 | */ |
495 | static void remove_watch_no_event(struct inotify_watch *watch, | 214 | static void remove_watch_no_event(struct inotify_watch *watch, |
496 | struct inotify_device *dev) | 215 | struct inotify_handle *ih) |
497 | { | 216 | { |
498 | list_del(&watch->i_list); | 217 | list_del(&watch->i_list); |
499 | list_del(&watch->d_list); | 218 | list_del(&watch->h_list); |
500 | 219 | ||
501 | if (!inotify_inode_watched(watch->inode)) | 220 | if (!inotify_inode_watched(watch->inode)) |
502 | set_dentry_child_flags(watch->inode, 0); | 221 | set_dentry_child_flags(watch->inode, 0); |
503 | 222 | ||
504 | atomic_dec(&dev->user->inotify_watches); | 223 | idr_remove(&ih->idr, watch->wd); |
505 | idr_remove(&dev->idr, watch->wd); | ||
506 | put_inotify_watch(watch); | ||
507 | } | 224 | } |
508 | 225 | ||
509 | /* | 226 | /** |
510 | * remove_watch - Remove a watch from both the device and the inode. Sends | 227 | * inotify_remove_watch_locked - Remove a watch from both the handle and the |
511 | * the IN_IGNORED event to the given device signifying that the inode is no | 228 | * inode. Sends the IN_IGNORED event signifying that the inode is no longer |
512 | * longer watched. | 229 | * watched. May be invoked from a caller's event handler. |
513 | * | 230 | * @ih: inotify handle associated with watch |
514 | * Callers must hold both inode->inotify_mutex and dev->mutex. We drop a | 231 | * @watch: watch to remove |
515 | * reference to the inode before returning. | ||
516 | * | 232 | * |
517 | * The inode is not iput() so as to remain atomic. If the inode needs to be | 233 | * Callers must hold both inode->inotify_mutex and ih->mutex. |
518 | * iput(), the call returns one. Otherwise, it returns zero. | ||
519 | */ | 234 | */ |
520 | static void remove_watch(struct inotify_watch *watch,struct inotify_device *dev) | 235 | void inotify_remove_watch_locked(struct inotify_handle *ih, |
236 | struct inotify_watch *watch) | ||
521 | { | 237 | { |
522 | inotify_dev_queue_event(dev, watch, IN_IGNORED, 0, NULL); | 238 | remove_watch_no_event(watch, ih); |
523 | remove_watch_no_event(watch, dev); | 239 | ih->in_ops->handle_event(watch, watch->wd, IN_IGNORED, 0, NULL, NULL); |
524 | } | 240 | } |
241 | EXPORT_SYMBOL_GPL(inotify_remove_watch_locked); | ||
525 | 242 | ||
526 | /* Kernel API */ | 243 | /* Kernel API for producing events */ |
527 | 244 | ||
528 | /* | 245 | /* |
529 | * inotify_d_instantiate - instantiate dcache entry for inode | 246 | * inotify_d_instantiate - instantiate dcache entry for inode |
@@ -563,9 +280,10 @@ void inotify_d_move(struct dentry *entry) | |||
563 | * @mask: event mask describing this event | 280 | * @mask: event mask describing this event |
564 | * @cookie: cookie for synchronization, or zero | 281 | * @cookie: cookie for synchronization, or zero |
565 | * @name: filename, if any | 282 | * @name: filename, if any |
283 | * @n_inode: inode associated with name | ||
566 | */ | 284 | */ |
567 | void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, | 285 | void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, |
568 | const char *name) | 286 | const char *name, struct inode *n_inode) |
569 | { | 287 | { |
570 | struct inotify_watch *watch, *next; | 288 | struct inotify_watch *watch, *next; |
571 | 289 | ||
@@ -576,14 +294,13 @@ void inotify_inode_queue_event(struct inode *inode, u32 mask, u32 cookie, | |||
576 | list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { | 294 | list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { |
577 | u32 watch_mask = watch->mask; | 295 | u32 watch_mask = watch->mask; |
578 | if (watch_mask & mask) { | 296 | if (watch_mask & mask) { |
579 | struct inotify_device *dev = watch->dev; | 297 | struct inotify_handle *ih= watch->ih; |
580 | get_inotify_watch(watch); | 298 | mutex_lock(&ih->mutex); |
581 | mutex_lock(&dev->mutex); | ||
582 | inotify_dev_queue_event(dev, watch, mask, cookie, name); | ||
583 | if (watch_mask & IN_ONESHOT) | 299 | if (watch_mask & IN_ONESHOT) |
584 | remove_watch_no_event(watch, dev); | 300 | remove_watch_no_event(watch, ih); |
585 | mutex_unlock(&dev->mutex); | 301 | ih->in_ops->handle_event(watch, watch->wd, mask, cookie, |
586 | put_inotify_watch(watch); | 302 | name, n_inode); |
303 | mutex_unlock(&ih->mutex); | ||
587 | } | 304 | } |
588 | } | 305 | } |
589 | mutex_unlock(&inode->inotify_mutex); | 306 | mutex_unlock(&inode->inotify_mutex); |
@@ -613,7 +330,8 @@ void inotify_dentry_parent_queue_event(struct dentry *dentry, u32 mask, | |||
613 | if (inotify_inode_watched(inode)) { | 330 | if (inotify_inode_watched(inode)) { |
614 | dget(parent); | 331 | dget(parent); |
615 | spin_unlock(&dentry->d_lock); | 332 | spin_unlock(&dentry->d_lock); |
616 | inotify_inode_queue_event(inode, mask, cookie, name); | 333 | inotify_inode_queue_event(inode, mask, cookie, name, |
334 | dentry->d_inode); | ||
617 | dput(parent); | 335 | dput(parent); |
618 | } else | 336 | } else |
619 | spin_unlock(&dentry->d_lock); | 337 | spin_unlock(&dentry->d_lock); |
@@ -665,7 +383,7 @@ void inotify_unmount_inodes(struct list_head *list) | |||
665 | 383 | ||
666 | need_iput_tmp = need_iput; | 384 | need_iput_tmp = need_iput; |
667 | need_iput = NULL; | 385 | need_iput = NULL; |
668 | /* In case the remove_watch() drops a reference. */ | 386 | /* In case inotify_remove_watch_locked() drops a reference. */ |
669 | if (inode != need_iput_tmp) | 387 | if (inode != need_iput_tmp) |
670 | __iget(inode); | 388 | __iget(inode); |
671 | else | 389 | else |
@@ -694,11 +412,12 @@ void inotify_unmount_inodes(struct list_head *list) | |||
694 | mutex_lock(&inode->inotify_mutex); | 412 | mutex_lock(&inode->inotify_mutex); |
695 | watches = &inode->inotify_watches; | 413 | watches = &inode->inotify_watches; |
696 | list_for_each_entry_safe(watch, next_w, watches, i_list) { | 414 | list_for_each_entry_safe(watch, next_w, watches, i_list) { |
697 | struct inotify_device *dev = watch->dev; | 415 | struct inotify_handle *ih= watch->ih; |
698 | mutex_lock(&dev->mutex); | 416 | mutex_lock(&ih->mutex); |
699 | inotify_dev_queue_event(dev, watch, IN_UNMOUNT,0,NULL); | 417 | ih->in_ops->handle_event(watch, watch->wd, IN_UNMOUNT, 0, |
700 | remove_watch(watch, dev); | 418 | NULL, NULL); |
701 | mutex_unlock(&dev->mutex); | 419 | inotify_remove_watch_locked(ih, watch); |
420 | mutex_unlock(&ih->mutex); | ||
702 | } | 421 | } |
703 | mutex_unlock(&inode->inotify_mutex); | 422 | mutex_unlock(&inode->inotify_mutex); |
704 | iput(inode); | 423 | iput(inode); |
@@ -718,432 +437,292 @@ void inotify_inode_is_dead(struct inode *inode) | |||
718 | 437 | ||
719 | mutex_lock(&inode->inotify_mutex); | 438 | mutex_lock(&inode->inotify_mutex); |
720 | list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { | 439 | list_for_each_entry_safe(watch, next, &inode->inotify_watches, i_list) { |
721 | struct inotify_device *dev = watch->dev; | 440 | struct inotify_handle *ih = watch->ih; |
722 | mutex_lock(&dev->mutex); | 441 | mutex_lock(&ih->mutex); |
723 | remove_watch(watch, dev); | 442 | inotify_remove_watch_locked(ih, watch); |
724 | mutex_unlock(&dev->mutex); | 443 | mutex_unlock(&ih->mutex); |
725 | } | 444 | } |
726 | mutex_unlock(&inode->inotify_mutex); | 445 | mutex_unlock(&inode->inotify_mutex); |
727 | } | 446 | } |
728 | EXPORT_SYMBOL_GPL(inotify_inode_is_dead); | 447 | EXPORT_SYMBOL_GPL(inotify_inode_is_dead); |
729 | 448 | ||
730 | /* Device Interface */ | 449 | /* Kernel Consumer API */ |
731 | 450 | ||
732 | static unsigned int inotify_poll(struct file *file, poll_table *wait) | 451 | /** |
452 | * inotify_init - allocate and initialize an inotify instance | ||
453 | * @ops: caller's inotify operations | ||
454 | */ | ||
455 | struct inotify_handle *inotify_init(const struct inotify_operations *ops) | ||
733 | { | 456 | { |
734 | struct inotify_device *dev = file->private_data; | 457 | struct inotify_handle *ih; |
735 | int ret = 0; | ||
736 | 458 | ||
737 | poll_wait(file, &dev->wq, wait); | 459 | ih = kmalloc(sizeof(struct inotify_handle), GFP_KERNEL); |
738 | mutex_lock(&dev->mutex); | 460 | if (unlikely(!ih)) |
739 | if (!list_empty(&dev->events)) | 461 | return ERR_PTR(-ENOMEM); |
740 | ret = POLLIN | POLLRDNORM; | ||
741 | mutex_unlock(&dev->mutex); | ||
742 | 462 | ||
743 | return ret; | 463 | idr_init(&ih->idr); |
464 | INIT_LIST_HEAD(&ih->watches); | ||
465 | mutex_init(&ih->mutex); | ||
466 | ih->last_wd = 0; | ||
467 | ih->in_ops = ops; | ||
468 | atomic_set(&ih->count, 0); | ||
469 | get_inotify_handle(ih); | ||
470 | |||
471 | return ih; | ||
744 | } | 472 | } |
473 | EXPORT_SYMBOL_GPL(inotify_init); | ||
745 | 474 | ||
746 | static ssize_t inotify_read(struct file *file, char __user *buf, | 475 | /** |
747 | size_t count, loff_t *pos) | 476 | * inotify_init_watch - initialize an inotify watch |
477 | * @watch: watch to initialize | ||
478 | */ | ||
479 | void inotify_init_watch(struct inotify_watch *watch) | ||
748 | { | 480 | { |
749 | size_t event_size = sizeof (struct inotify_event); | 481 | INIT_LIST_HEAD(&watch->h_list); |
750 | struct inotify_device *dev; | 482 | INIT_LIST_HEAD(&watch->i_list); |
751 | char __user *start; | 483 | atomic_set(&watch->count, 0); |
752 | int ret; | 484 | get_inotify_watch(watch); /* initial get */ |
753 | DEFINE_WAIT(wait); | ||
754 | |||
755 | start = buf; | ||
756 | dev = file->private_data; | ||
757 | |||
758 | while (1) { | ||
759 | int events; | ||
760 | |||
761 | prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); | ||
762 | |||
763 | mutex_lock(&dev->mutex); | ||
764 | events = !list_empty(&dev->events); | ||
765 | mutex_unlock(&dev->mutex); | ||
766 | if (events) { | ||
767 | ret = 0; | ||
768 | break; | ||
769 | } | ||
770 | |||
771 | if (file->f_flags & O_NONBLOCK) { | ||
772 | ret = -EAGAIN; | ||
773 | break; | ||
774 | } | ||
775 | |||
776 | if (signal_pending(current)) { | ||
777 | ret = -EINTR; | ||
778 | break; | ||
779 | } | ||
780 | |||
781 | schedule(); | ||
782 | } | ||
783 | |||
784 | finish_wait(&dev->wq, &wait); | ||
785 | if (ret) | ||
786 | return ret; | ||
787 | |||
788 | mutex_lock(&dev->mutex); | ||
789 | while (1) { | ||
790 | struct inotify_kernel_event *kevent; | ||
791 | |||
792 | ret = buf - start; | ||
793 | if (list_empty(&dev->events)) | ||
794 | break; | ||
795 | |||
796 | kevent = inotify_dev_get_event(dev); | ||
797 | if (event_size + kevent->event.len > count) | ||
798 | break; | ||
799 | |||
800 | if (copy_to_user(buf, &kevent->event, event_size)) { | ||
801 | ret = -EFAULT; | ||
802 | break; | ||
803 | } | ||
804 | buf += event_size; | ||
805 | count -= event_size; | ||
806 | |||
807 | if (kevent->name) { | ||
808 | if (copy_to_user(buf, kevent->name, kevent->event.len)){ | ||
809 | ret = -EFAULT; | ||
810 | break; | ||
811 | } | ||
812 | buf += kevent->event.len; | ||
813 | count -= kevent->event.len; | ||
814 | } | ||
815 | |||
816 | remove_kevent(dev, kevent); | ||
817 | } | ||
818 | mutex_unlock(&dev->mutex); | ||
819 | |||
820 | return ret; | ||
821 | } | 485 | } |
486 | EXPORT_SYMBOL_GPL(inotify_init_watch); | ||
822 | 487 | ||
823 | static int inotify_release(struct inode *ignored, struct file *file) | 488 | /** |
489 | * inotify_destroy - clean up and destroy an inotify instance | ||
490 | * @ih: inotify handle | ||
491 | */ | ||
492 | void inotify_destroy(struct inotify_handle *ih) | ||
824 | { | 493 | { |
825 | struct inotify_device *dev = file->private_data; | ||
826 | |||
827 | /* | 494 | /* |
828 | * Destroy all of the watches on this device. Unfortunately, not very | 495 | * Destroy all of the watches for this handle. Unfortunately, not very |
829 | * pretty. We cannot do a simple iteration over the list, because we | 496 | * pretty. We cannot do a simple iteration over the list, because we |
830 | * do not know the inode until we iterate to the watch. But we need to | 497 | * do not know the inode until we iterate to the watch. But we need to |
831 | * hold inode->inotify_mutex before dev->mutex. The following works. | 498 | * hold inode->inotify_mutex before ih->mutex. The following works. |
832 | */ | 499 | */ |
833 | while (1) { | 500 | while (1) { |
834 | struct inotify_watch *watch; | 501 | struct inotify_watch *watch; |
835 | struct list_head *watches; | 502 | struct list_head *watches; |
836 | struct inode *inode; | 503 | struct inode *inode; |
837 | 504 | ||
838 | mutex_lock(&dev->mutex); | 505 | mutex_lock(&ih->mutex); |
839 | watches = &dev->watches; | 506 | watches = &ih->watches; |
840 | if (list_empty(watches)) { | 507 | if (list_empty(watches)) { |
841 | mutex_unlock(&dev->mutex); | 508 | mutex_unlock(&ih->mutex); |
842 | break; | 509 | break; |
843 | } | 510 | } |
844 | watch = list_entry(watches->next, struct inotify_watch, d_list); | 511 | watch = list_entry(watches->next, struct inotify_watch, h_list); |
845 | get_inotify_watch(watch); | 512 | get_inotify_watch(watch); |
846 | mutex_unlock(&dev->mutex); | 513 | mutex_unlock(&ih->mutex); |
847 | 514 | ||
848 | inode = watch->inode; | 515 | inode = watch->inode; |
849 | mutex_lock(&inode->inotify_mutex); | 516 | mutex_lock(&inode->inotify_mutex); |
850 | mutex_lock(&dev->mutex); | 517 | mutex_lock(&ih->mutex); |
851 | 518 | ||
852 | /* make sure we didn't race with another list removal */ | 519 | /* make sure we didn't race with another list removal */ |
853 | if (likely(idr_find(&dev->idr, watch->wd))) | 520 | if (likely(idr_find(&ih->idr, watch->wd))) { |
854 | remove_watch_no_event(watch, dev); | 521 | remove_watch_no_event(watch, ih); |
522 | put_inotify_watch(watch); | ||
523 | } | ||
855 | 524 | ||
856 | mutex_unlock(&dev->mutex); | 525 | mutex_unlock(&ih->mutex); |
857 | mutex_unlock(&inode->inotify_mutex); | 526 | mutex_unlock(&inode->inotify_mutex); |
858 | put_inotify_watch(watch); | 527 | put_inotify_watch(watch); |
859 | } | 528 | } |
860 | 529 | ||
861 | /* destroy all of the events on this device */ | 530 | /* free this handle: the put matching the get in inotify_init() */ |
862 | mutex_lock(&dev->mutex); | 531 | put_inotify_handle(ih); |
863 | while (!list_empty(&dev->events)) | ||
864 | inotify_dev_event_dequeue(dev); | ||
865 | mutex_unlock(&dev->mutex); | ||
866 | |||
867 | /* free this device: the put matching the get in inotify_init() */ | ||
868 | put_inotify_dev(dev); | ||
869 | |||
870 | return 0; | ||
871 | } | 532 | } |
533 | EXPORT_SYMBOL_GPL(inotify_destroy); | ||
872 | 534 | ||
873 | /* | 535 | /** |
874 | * inotify_ignore - remove a given wd from this inotify instance. | 536 | * inotify_find_watch - find an existing watch for an (ih,inode) pair |
537 | * @ih: inotify handle | ||
538 | * @inode: inode to watch | ||
539 | * @watchp: pointer to existing inotify_watch | ||
875 | * | 540 | * |
876 | * Can sleep. | 541 | * Caller must pin given inode (via nameidata). |
877 | */ | 542 | */ |
878 | static int inotify_ignore(struct inotify_device *dev, s32 wd) | 543 | s32 inotify_find_watch(struct inotify_handle *ih, struct inode *inode, |
544 | struct inotify_watch **watchp) | ||
879 | { | 545 | { |
880 | struct inotify_watch *watch; | 546 | struct inotify_watch *old; |
881 | struct inode *inode; | 547 | int ret = -ENOENT; |
882 | |||
883 | mutex_lock(&dev->mutex); | ||
884 | watch = idr_find(&dev->idr, wd); | ||
885 | if (unlikely(!watch)) { | ||
886 | mutex_unlock(&dev->mutex); | ||
887 | return -EINVAL; | ||
888 | } | ||
889 | get_inotify_watch(watch); | ||
890 | inode = watch->inode; | ||
891 | mutex_unlock(&dev->mutex); | ||
892 | 548 | ||
893 | mutex_lock(&inode->inotify_mutex); | 549 | mutex_lock(&inode->inotify_mutex); |
894 | mutex_lock(&dev->mutex); | 550 | mutex_lock(&ih->mutex); |
895 | 551 | ||
896 | /* make sure that we did not race */ | 552 | old = inode_find_handle(inode, ih); |
897 | if (likely(idr_find(&dev->idr, wd) == watch)) | 553 | if (unlikely(old)) { |
898 | remove_watch(watch, dev); | 554 | get_inotify_watch(old); /* caller must put watch */ |
555 | *watchp = old; | ||
556 | ret = old->wd; | ||
557 | } | ||
899 | 558 | ||
900 | mutex_unlock(&dev->mutex); | 559 | mutex_unlock(&ih->mutex); |
901 | mutex_unlock(&inode->inotify_mutex); | 560 | mutex_unlock(&inode->inotify_mutex); |
902 | put_inotify_watch(watch); | ||
903 | 561 | ||
904 | return 0; | 562 | return ret; |
905 | } | 563 | } |
564 | EXPORT_SYMBOL_GPL(inotify_find_watch); | ||
906 | 565 | ||
907 | static long inotify_ioctl(struct file *file, unsigned int cmd, | 566 | /** |
908 | unsigned long arg) | 567 | * inotify_find_update_watch - find and update the mask of an existing watch |
568 | * @ih: inotify handle | ||
569 | * @inode: inode's watch to update | ||
570 | * @mask: mask of events to watch | ||
571 | * | ||
572 | * Caller must pin given inode (via nameidata). | ||
573 | */ | ||
574 | s32 inotify_find_update_watch(struct inotify_handle *ih, struct inode *inode, | ||
575 | u32 mask) | ||
909 | { | 576 | { |
910 | struct inotify_device *dev; | 577 | struct inotify_watch *old; |
911 | void __user *p; | 578 | int mask_add = 0; |
912 | int ret = -ENOTTY; | 579 | int ret; |
913 | |||
914 | dev = file->private_data; | ||
915 | p = (void __user *) arg; | ||
916 | |||
917 | switch (cmd) { | ||
918 | case FIONREAD: | ||
919 | ret = put_user(dev->queue_size, (int __user *) p); | ||
920 | break; | ||
921 | } | ||
922 | |||
923 | return ret; | ||
924 | } | ||
925 | 580 | ||
926 | static const struct file_operations inotify_fops = { | 581 | if (mask & IN_MASK_ADD) |
927 | .poll = inotify_poll, | 582 | mask_add = 1; |
928 | .read = inotify_read, | ||
929 | .release = inotify_release, | ||
930 | .unlocked_ioctl = inotify_ioctl, | ||
931 | .compat_ioctl = inotify_ioctl, | ||
932 | }; | ||
933 | 583 | ||
934 | asmlinkage long sys_inotify_init(void) | 584 | /* don't allow invalid bits: we don't want flags set */ |
935 | { | 585 | mask &= IN_ALL_EVENTS | IN_ONESHOT; |
936 | struct inotify_device *dev; | 586 | if (unlikely(!mask)) |
937 | struct user_struct *user; | 587 | return -EINVAL; |
938 | struct file *filp; | ||
939 | int fd, ret; | ||
940 | |||
941 | fd = get_unused_fd(); | ||
942 | if (fd < 0) | ||
943 | return fd; | ||
944 | |||
945 | filp = get_empty_filp(); | ||
946 | if (!filp) { | ||
947 | ret = -ENFILE; | ||
948 | goto out_put_fd; | ||
949 | } | ||
950 | 588 | ||
951 | user = get_uid(current->user); | 589 | mutex_lock(&inode->inotify_mutex); |
952 | if (unlikely(atomic_read(&user->inotify_devs) >= | 590 | mutex_lock(&ih->mutex); |
953 | inotify_max_user_instances)) { | ||
954 | ret = -EMFILE; | ||
955 | goto out_free_uid; | ||
956 | } | ||
957 | 591 | ||
958 | dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL); | 592 | /* |
959 | if (unlikely(!dev)) { | 593 | * Handle the case of re-adding a watch on an (inode,ih) pair that we |
960 | ret = -ENOMEM; | 594 | * are already watching. We just update the mask and return its wd. |
961 | goto out_free_uid; | 595 | */ |
596 | old = inode_find_handle(inode, ih); | ||
597 | if (unlikely(!old)) { | ||
598 | ret = -ENOENT; | ||
599 | goto out; | ||
962 | } | 600 | } |
963 | 601 | ||
964 | filp->f_op = &inotify_fops; | 602 | if (mask_add) |
965 | filp->f_vfsmnt = mntget(inotify_mnt); | 603 | old->mask |= mask; |
966 | filp->f_dentry = dget(inotify_mnt->mnt_root); | 604 | else |
967 | filp->f_mapping = filp->f_dentry->d_inode->i_mapping; | 605 | old->mask = mask; |
968 | filp->f_mode = FMODE_READ; | 606 | ret = old->wd; |
969 | filp->f_flags = O_RDONLY; | 607 | out: |
970 | filp->private_data = dev; | 608 | mutex_unlock(&ih->mutex); |
971 | 609 | mutex_unlock(&inode->inotify_mutex); | |
972 | idr_init(&dev->idr); | ||
973 | INIT_LIST_HEAD(&dev->events); | ||
974 | INIT_LIST_HEAD(&dev->watches); | ||
975 | init_waitqueue_head(&dev->wq); | ||
976 | mutex_init(&dev->mutex); | ||
977 | dev->event_count = 0; | ||
978 | dev->queue_size = 0; | ||
979 | dev->max_events = inotify_max_queued_events; | ||
980 | dev->user = user; | ||
981 | dev->last_wd = 0; | ||
982 | atomic_set(&dev->count, 0); | ||
983 | |||
984 | get_inotify_dev(dev); | ||
985 | atomic_inc(&user->inotify_devs); | ||
986 | fd_install(fd, filp); | ||
987 | |||
988 | return fd; | ||
989 | out_free_uid: | ||
990 | free_uid(user); | ||
991 | put_filp(filp); | ||
992 | out_put_fd: | ||
993 | put_unused_fd(fd); | ||
994 | return ret; | 610 | return ret; |
995 | } | 611 | } |
612 | EXPORT_SYMBOL_GPL(inotify_find_update_watch); | ||
996 | 613 | ||
997 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | 614 | /** |
615 | * inotify_add_watch - add a watch to an inotify instance | ||
616 | * @ih: inotify handle | ||
617 | * @watch: caller allocated watch structure | ||
618 | * @inode: inode to watch | ||
619 | * @mask: mask of events to watch | ||
620 | * | ||
621 | * Caller must pin given inode (via nameidata). | ||
622 | * Caller must ensure it only calls inotify_add_watch() once per watch. | ||
623 | * Calls inotify_handle_get_wd() so may sleep. | ||
624 | */ | ||
625 | s32 inotify_add_watch(struct inotify_handle *ih, struct inotify_watch *watch, | ||
626 | struct inode *inode, u32 mask) | ||
998 | { | 627 | { |
999 | struct inotify_watch *watch, *old; | 628 | int ret = 0; |
1000 | struct inode *inode; | ||
1001 | struct inotify_device *dev; | ||
1002 | struct nameidata nd; | ||
1003 | struct file *filp; | ||
1004 | int ret, fput_needed; | ||
1005 | int mask_add = 0; | ||
1006 | unsigned flags = 0; | ||
1007 | |||
1008 | filp = fget_light(fd, &fput_needed); | ||
1009 | if (unlikely(!filp)) | ||
1010 | return -EBADF; | ||
1011 | |||
1012 | /* verify that this is indeed an inotify instance */ | ||
1013 | if (unlikely(filp->f_op != &inotify_fops)) { | ||
1014 | ret = -EINVAL; | ||
1015 | goto fput_and_out; | ||
1016 | } | ||
1017 | |||
1018 | if (!(mask & IN_DONT_FOLLOW)) | ||
1019 | flags |= LOOKUP_FOLLOW; | ||
1020 | if (mask & IN_ONLYDIR) | ||
1021 | flags |= LOOKUP_DIRECTORY; | ||
1022 | |||
1023 | ret = find_inode(path, &nd, flags); | ||
1024 | if (unlikely(ret)) | ||
1025 | goto fput_and_out; | ||
1026 | 629 | ||
1027 | /* inode held in place by reference to nd; dev by fget on fd */ | 630 | /* don't allow invalid bits: we don't want flags set */ |
1028 | inode = nd.dentry->d_inode; | 631 | mask &= IN_ALL_EVENTS | IN_ONESHOT; |
1029 | dev = filp->private_data; | 632 | if (unlikely(!mask)) |
633 | return -EINVAL; | ||
634 | watch->mask = mask; | ||
1030 | 635 | ||
1031 | mutex_lock(&inode->inotify_mutex); | 636 | mutex_lock(&inode->inotify_mutex); |
1032 | mutex_lock(&dev->mutex); | 637 | mutex_lock(&ih->mutex); |
1033 | |||
1034 | if (mask & IN_MASK_ADD) | ||
1035 | mask_add = 1; | ||
1036 | 638 | ||
1037 | /* don't let user-space set invalid bits: we don't want flags set */ | 639 | /* Initialize a new watch */ |
1038 | mask &= IN_ALL_EVENTS | IN_ONESHOT; | 640 | ret = inotify_handle_get_wd(ih, watch); |
1039 | if (unlikely(!mask)) { | 641 | if (unlikely(ret)) |
1040 | ret = -EINVAL; | ||
1041 | goto out; | 642 | goto out; |
1042 | } | 643 | ret = watch->wd; |
644 | |||
645 | /* save a reference to handle and bump the count to make it official */ | ||
646 | get_inotify_handle(ih); | ||
647 | watch->ih = ih; | ||
1043 | 648 | ||
1044 | /* | 649 | /* |
1045 | * Handle the case of re-adding a watch on an (inode,dev) pair that we | 650 | * Save a reference to the inode and bump the ref count to make it |
1046 | * are already watching. We just update the mask and return its wd. | 651 | * official. We hold a reference to nameidata, which makes this safe. |
1047 | */ | 652 | */ |
1048 | old = inode_find_dev(inode, dev); | 653 | watch->inode = igrab(inode); |
1049 | if (unlikely(old)) { | ||
1050 | if (mask_add) | ||
1051 | old->mask |= mask; | ||
1052 | else | ||
1053 | old->mask = mask; | ||
1054 | ret = old->wd; | ||
1055 | goto out; | ||
1056 | } | ||
1057 | |||
1058 | watch = create_watch(dev, mask, inode); | ||
1059 | if (unlikely(IS_ERR(watch))) { | ||
1060 | ret = PTR_ERR(watch); | ||
1061 | goto out; | ||
1062 | } | ||
1063 | 654 | ||
1064 | if (!inotify_inode_watched(inode)) | 655 | if (!inotify_inode_watched(inode)) |
1065 | set_dentry_child_flags(inode, 1); | 656 | set_dentry_child_flags(inode, 1); |
1066 | 657 | ||
1067 | /* Add the watch to the device's and the inode's list */ | 658 | /* Add the watch to the handle's and the inode's list */ |
1068 | list_add(&watch->d_list, &dev->watches); | 659 | list_add(&watch->h_list, &ih->watches); |
1069 | list_add(&watch->i_list, &inode->inotify_watches); | 660 | list_add(&watch->i_list, &inode->inotify_watches); |
1070 | ret = watch->wd; | ||
1071 | out: | 661 | out: |
1072 | mutex_unlock(&dev->mutex); | 662 | mutex_unlock(&ih->mutex); |
1073 | mutex_unlock(&inode->inotify_mutex); | 663 | mutex_unlock(&inode->inotify_mutex); |
1074 | path_release(&nd); | ||
1075 | fput_and_out: | ||
1076 | fput_light(filp, fput_needed); | ||
1077 | return ret; | 664 | return ret; |
1078 | } | 665 | } |
666 | EXPORT_SYMBOL_GPL(inotify_add_watch); | ||
1079 | 667 | ||
1080 | asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) | 668 | /** |
669 | * inotify_rm_wd - remove a watch from an inotify instance | ||
670 | * @ih: inotify handle | ||
671 | * @wd: watch descriptor to remove | ||
672 | * | ||
673 | * Can sleep. | ||
674 | */ | ||
675 | int inotify_rm_wd(struct inotify_handle *ih, u32 wd) | ||
1081 | { | 676 | { |
1082 | struct file *filp; | 677 | struct inotify_watch *watch; |
1083 | struct inotify_device *dev; | 678 | struct inode *inode; |
1084 | int ret, fput_needed; | ||
1085 | |||
1086 | filp = fget_light(fd, &fput_needed); | ||
1087 | if (unlikely(!filp)) | ||
1088 | return -EBADF; | ||
1089 | 679 | ||
1090 | /* verify that this is indeed an inotify instance */ | 680 | mutex_lock(&ih->mutex); |
1091 | if (unlikely(filp->f_op != &inotify_fops)) { | 681 | watch = idr_find(&ih->idr, wd); |
1092 | ret = -EINVAL; | 682 | if (unlikely(!watch)) { |
1093 | goto out; | 683 | mutex_unlock(&ih->mutex); |
684 | return -EINVAL; | ||
1094 | } | 685 | } |
686 | get_inotify_watch(watch); | ||
687 | inode = watch->inode; | ||
688 | mutex_unlock(&ih->mutex); | ||
1095 | 689 | ||
1096 | dev = filp->private_data; | 690 | mutex_lock(&inode->inotify_mutex); |
1097 | ret = inotify_ignore(dev, wd); | 691 | mutex_lock(&ih->mutex); |
1098 | 692 | ||
1099 | out: | 693 | /* make sure that we did not race */ |
1100 | fput_light(filp, fput_needed); | 694 | if (likely(idr_find(&ih->idr, wd) == watch)) |
1101 | return ret; | 695 | inotify_remove_watch_locked(ih, watch); |
696 | |||
697 | mutex_unlock(&ih->mutex); | ||
698 | mutex_unlock(&inode->inotify_mutex); | ||
699 | put_inotify_watch(watch); | ||
700 | |||
701 | return 0; | ||
1102 | } | 702 | } |
703 | EXPORT_SYMBOL_GPL(inotify_rm_wd); | ||
1103 | 704 | ||
1104 | static struct super_block * | 705 | /** |
1105 | inotify_get_sb(struct file_system_type *fs_type, int flags, | 706 | * inotify_rm_watch - remove a watch from an inotify instance |
1106 | const char *dev_name, void *data) | 707 | * @ih: inotify handle |
708 | * @watch: watch to remove | ||
709 | * | ||
710 | * Can sleep. | ||
711 | */ | ||
712 | int inotify_rm_watch(struct inotify_handle *ih, | ||
713 | struct inotify_watch *watch) | ||
1107 | { | 714 | { |
1108 | return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA); | 715 | return inotify_rm_wd(ih, watch->wd); |
1109 | } | 716 | } |
1110 | 717 | EXPORT_SYMBOL_GPL(inotify_rm_watch); | |
1111 | static struct file_system_type inotify_fs_type = { | ||
1112 | .name = "inotifyfs", | ||
1113 | .get_sb = inotify_get_sb, | ||
1114 | .kill_sb = kill_anon_super, | ||
1115 | }; | ||
1116 | 718 | ||
1117 | /* | 719 | /* |
1118 | * inotify_setup - Our initialization function. Note that we cannnot return | 720 | * inotify_setup - core initialization function |
1119 | * error because we have compiled-in VFS hooks. So an (unlikely) failure here | ||
1120 | * must result in panic(). | ||
1121 | */ | 721 | */ |
1122 | static int __init inotify_setup(void) | 722 | static int __init inotify_setup(void) |
1123 | { | 723 | { |
1124 | int ret; | ||
1125 | |||
1126 | ret = register_filesystem(&inotify_fs_type); | ||
1127 | if (unlikely(ret)) | ||
1128 | panic("inotify: register_filesystem returned %d!\n", ret); | ||
1129 | |||
1130 | inotify_mnt = kern_mount(&inotify_fs_type); | ||
1131 | if (IS_ERR(inotify_mnt)) | ||
1132 | panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt)); | ||
1133 | |||
1134 | inotify_max_queued_events = 16384; | ||
1135 | inotify_max_user_instances = 128; | ||
1136 | inotify_max_user_watches = 8192; | ||
1137 | |||
1138 | atomic_set(&inotify_cookie, 0); | 724 | atomic_set(&inotify_cookie, 0); |
1139 | 725 | ||
1140 | watch_cachep = kmem_cache_create("inotify_watch_cache", | ||
1141 | sizeof(struct inotify_watch), | ||
1142 | 0, SLAB_PANIC, NULL, NULL); | ||
1143 | event_cachep = kmem_cache_create("inotify_event_cache", | ||
1144 | sizeof(struct inotify_kernel_event), | ||
1145 | 0, SLAB_PANIC, NULL, NULL); | ||
1146 | |||
1147 | return 0; | 726 | return 0; |
1148 | } | 727 | } |
1149 | 728 | ||
diff --git a/fs/inotify_user.c b/fs/inotify_user.c new file mode 100644 index 000000000000..f2386442adee --- /dev/null +++ b/fs/inotify_user.c | |||
@@ -0,0 +1,719 @@ | |||
1 | /* | ||
2 | * fs/inotify_user.c - inotify support for userspace | ||
3 | * | ||
4 | * Authors: | ||
5 | * John McCutchan <ttb@tentacle.dhs.org> | ||
6 | * Robert Love <rml@novell.com> | ||
7 | * | ||
8 | * Copyright (C) 2005 John McCutchan | ||
9 | * Copyright 2006 Hewlett-Packard Development Company, L.P. | ||
10 | * | ||
11 | * This program is free software; you can redistribute it and/or modify it | ||
12 | * under the terms of the GNU General Public License as published by the | ||
13 | * Free Software Foundation; either version 2, or (at your option) any | ||
14 | * later version. | ||
15 | * | ||
16 | * This program is distributed in the hope that it will be useful, but | ||
17 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
19 | * General Public License for more details. | ||
20 | */ | ||
21 | |||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/sched.h> | ||
24 | #include <linux/slab.h> | ||
25 | #include <linux/fs.h> | ||
26 | #include <linux/file.h> | ||
27 | #include <linux/mount.h> | ||
28 | #include <linux/namei.h> | ||
29 | #include <linux/poll.h> | ||
30 | #include <linux/init.h> | ||
31 | #include <linux/list.h> | ||
32 | #include <linux/inotify.h> | ||
33 | #include <linux/syscalls.h> | ||
34 | |||
35 | #include <asm/ioctls.h> | ||
36 | |||
37 | static kmem_cache_t *watch_cachep __read_mostly; | ||
38 | static kmem_cache_t *event_cachep __read_mostly; | ||
39 | |||
40 | static struct vfsmount *inotify_mnt __read_mostly; | ||
41 | |||
42 | /* these are configurable via /proc/sys/fs/inotify/ */ | ||
43 | int inotify_max_user_instances __read_mostly; | ||
44 | int inotify_max_user_watches __read_mostly; | ||
45 | int inotify_max_queued_events __read_mostly; | ||
46 | |||
47 | /* | ||
48 | * Lock ordering: | ||
49 | * | ||
50 | * inotify_dev->up_mutex (ensures we don't re-add the same watch) | ||
51 | * inode->inotify_mutex (protects inode's watch list) | ||
52 | * inotify_handle->mutex (protects inotify_handle's watch list) | ||
53 | * inotify_dev->ev_mutex (protects device's event queue) | ||
54 | */ | ||
55 | |||
56 | /* | ||
57 | * Lifetimes of the main data structures: | ||
58 | * | ||
59 | * inotify_device: Lifetime is managed by reference count, from | ||
60 | * sys_inotify_init() until release. Additional references can bump the count | ||
61 | * via get_inotify_dev() and drop the count via put_inotify_dev(). | ||
62 | * | ||
63 | * inotify_user_watch: Lifetime is from create_watch() to the receipt of an | ||
64 | * IN_IGNORED event from inotify, or when using IN_ONESHOT, to receipt of the | ||
65 | * first event, or to inotify_destroy(). | ||
66 | */ | ||
67 | |||
68 | /* | ||
69 | * struct inotify_device - represents an inotify instance | ||
70 | * | ||
71 | * This structure is protected by the mutex 'mutex'. | ||
72 | */ | ||
73 | struct inotify_device { | ||
74 | wait_queue_head_t wq; /* wait queue for i/o */ | ||
75 | struct mutex ev_mutex; /* protects event queue */ | ||
76 | struct mutex up_mutex; /* synchronizes watch updates */ | ||
77 | struct list_head events; /* list of queued events */ | ||
78 | atomic_t count; /* reference count */ | ||
79 | struct user_struct *user; /* user who opened this dev */ | ||
80 | struct inotify_handle *ih; /* inotify handle */ | ||
81 | unsigned int queue_size; /* size of the queue (bytes) */ | ||
82 | unsigned int event_count; /* number of pending events */ | ||
83 | unsigned int max_events; /* maximum number of events */ | ||
84 | }; | ||
85 | |||
86 | /* | ||
87 | * struct inotify_kernel_event - An inotify event, originating from a watch and | ||
88 | * queued for user-space. A list of these is attached to each instance of the | ||
89 | * device. In read(), this list is walked and all events that can fit in the | ||
90 | * buffer are returned. | ||
91 | * | ||
92 | * Protected by dev->ev_mutex of the device in which we are queued. | ||
93 | */ | ||
94 | struct inotify_kernel_event { | ||
95 | struct inotify_event event; /* the user-space event */ | ||
96 | struct list_head list; /* entry in inotify_device's list */ | ||
97 | char *name; /* filename, if any */ | ||
98 | }; | ||
99 | |||
100 | /* | ||
101 | * struct inotify_user_watch - our version of an inotify_watch, we add | ||
102 | * a reference to the associated inotify_device. | ||
103 | */ | ||
104 | struct inotify_user_watch { | ||
105 | struct inotify_device *dev; /* associated device */ | ||
106 | struct inotify_watch wdata; /* inotify watch data */ | ||
107 | }; | ||
108 | |||
109 | #ifdef CONFIG_SYSCTL | ||
110 | |||
111 | #include <linux/sysctl.h> | ||
112 | |||
113 | static int zero; | ||
114 | |||
115 | ctl_table inotify_table[] = { | ||
116 | { | ||
117 | .ctl_name = INOTIFY_MAX_USER_INSTANCES, | ||
118 | .procname = "max_user_instances", | ||
119 | .data = &inotify_max_user_instances, | ||
120 | .maxlen = sizeof(int), | ||
121 | .mode = 0644, | ||
122 | .proc_handler = &proc_dointvec_minmax, | ||
123 | .strategy = &sysctl_intvec, | ||
124 | .extra1 = &zero, | ||
125 | }, | ||
126 | { | ||
127 | .ctl_name = INOTIFY_MAX_USER_WATCHES, | ||
128 | .procname = "max_user_watches", | ||
129 | .data = &inotify_max_user_watches, | ||
130 | .maxlen = sizeof(int), | ||
131 | .mode = 0644, | ||
132 | .proc_handler = &proc_dointvec_minmax, | ||
133 | .strategy = &sysctl_intvec, | ||
134 | .extra1 = &zero, | ||
135 | }, | ||
136 | { | ||
137 | .ctl_name = INOTIFY_MAX_QUEUED_EVENTS, | ||
138 | .procname = "max_queued_events", | ||
139 | .data = &inotify_max_queued_events, | ||
140 | .maxlen = sizeof(int), | ||
141 | .mode = 0644, | ||
142 | .proc_handler = &proc_dointvec_minmax, | ||
143 | .strategy = &sysctl_intvec, | ||
144 | .extra1 = &zero | ||
145 | }, | ||
146 | { .ctl_name = 0 } | ||
147 | }; | ||
148 | #endif /* CONFIG_SYSCTL */ | ||
149 | |||
150 | static inline void get_inotify_dev(struct inotify_device *dev) | ||
151 | { | ||
152 | atomic_inc(&dev->count); | ||
153 | } | ||
154 | |||
155 | static inline void put_inotify_dev(struct inotify_device *dev) | ||
156 | { | ||
157 | if (atomic_dec_and_test(&dev->count)) { | ||
158 | atomic_dec(&dev->user->inotify_devs); | ||
159 | free_uid(dev->user); | ||
160 | kfree(dev); | ||
161 | } | ||
162 | } | ||
163 | |||
164 | /* | ||
165 | * free_inotify_user_watch - cleans up the watch and its references | ||
166 | */ | ||
167 | static void free_inotify_user_watch(struct inotify_watch *w) | ||
168 | { | ||
169 | struct inotify_user_watch *watch; | ||
170 | struct inotify_device *dev; | ||
171 | |||
172 | watch = container_of(w, struct inotify_user_watch, wdata); | ||
173 | dev = watch->dev; | ||
174 | |||
175 | atomic_dec(&dev->user->inotify_watches); | ||
176 | put_inotify_dev(dev); | ||
177 | kmem_cache_free(watch_cachep, watch); | ||
178 | } | ||
179 | |||
180 | /* | ||
181 | * kernel_event - create a new kernel event with the given parameters | ||
182 | * | ||
183 | * This function can sleep. | ||
184 | */ | ||
185 | static struct inotify_kernel_event * kernel_event(s32 wd, u32 mask, u32 cookie, | ||
186 | const char *name) | ||
187 | { | ||
188 | struct inotify_kernel_event *kevent; | ||
189 | |||
190 | kevent = kmem_cache_alloc(event_cachep, GFP_KERNEL); | ||
191 | if (unlikely(!kevent)) | ||
192 | return NULL; | ||
193 | |||
194 | /* we hand this out to user-space, so zero it just in case */ | ||
195 | memset(&kevent->event, 0, sizeof(struct inotify_event)); | ||
196 | |||
197 | kevent->event.wd = wd; | ||
198 | kevent->event.mask = mask; | ||
199 | kevent->event.cookie = cookie; | ||
200 | |||
201 | INIT_LIST_HEAD(&kevent->list); | ||
202 | |||
203 | if (name) { | ||
204 | size_t len, rem, event_size = sizeof(struct inotify_event); | ||
205 | |||
206 | /* | ||
207 | * We need to pad the filename so as to properly align an | ||
208 | * array of inotify_event structures. Because the structure is | ||
209 | * small and the common case is a small filename, we just round | ||
210 | * up to the next multiple of the structure's sizeof. This is | ||
211 | * simple and safe for all architectures. | ||
212 | */ | ||
213 | len = strlen(name) + 1; | ||
214 | rem = event_size - len; | ||
215 | if (len > event_size) { | ||
216 | rem = event_size - (len % event_size); | ||
217 | if (len % event_size == 0) | ||
218 | rem = 0; | ||
219 | } | ||
220 | |||
221 | kevent->name = kmalloc(len + rem, GFP_KERNEL); | ||
222 | if (unlikely(!kevent->name)) { | ||
223 | kmem_cache_free(event_cachep, kevent); | ||
224 | return NULL; | ||
225 | } | ||
226 | memcpy(kevent->name, name, len); | ||
227 | if (rem) | ||
228 | memset(kevent->name + len, 0, rem); | ||
229 | kevent->event.len = len + rem; | ||
230 | } else { | ||
231 | kevent->event.len = 0; | ||
232 | kevent->name = NULL; | ||
233 | } | ||
234 | |||
235 | return kevent; | ||
236 | } | ||
237 | |||
238 | /* | ||
239 | * inotify_dev_get_event - return the next event in the given dev's queue | ||
240 | * | ||
241 | * Caller must hold dev->ev_mutex. | ||
242 | */ | ||
243 | static inline struct inotify_kernel_event * | ||
244 | inotify_dev_get_event(struct inotify_device *dev) | ||
245 | { | ||
246 | return list_entry(dev->events.next, struct inotify_kernel_event, list); | ||
247 | } | ||
248 | |||
249 | /* | ||
250 | * inotify_dev_queue_event - event handler registered with core inotify, adds | ||
251 | * a new event to the given device | ||
252 | * | ||
253 | * Can sleep (calls kernel_event()). | ||
254 | */ | ||
255 | static void inotify_dev_queue_event(struct inotify_watch *w, u32 wd, u32 mask, | ||
256 | u32 cookie, const char *name, | ||
257 | struct inode *ignored) | ||
258 | { | ||
259 | struct inotify_user_watch *watch; | ||
260 | struct inotify_device *dev; | ||
261 | struct inotify_kernel_event *kevent, *last; | ||
262 | |||
263 | watch = container_of(w, struct inotify_user_watch, wdata); | ||
264 | dev = watch->dev; | ||
265 | |||
266 | mutex_lock(&dev->ev_mutex); | ||
267 | |||
268 | /* we can safely put the watch as we don't reference it while | ||
269 | * generating the event | ||
270 | */ | ||
271 | if (mask & IN_IGNORED || mask & IN_ONESHOT) | ||
272 | put_inotify_watch(w); /* final put */ | ||
273 | |||
274 | /* coalescing: drop this event if it is a dupe of the previous */ | ||
275 | last = inotify_dev_get_event(dev); | ||
276 | if (last && last->event.mask == mask && last->event.wd == wd && | ||
277 | last->event.cookie == cookie) { | ||
278 | const char *lastname = last->name; | ||
279 | |||
280 | if (!name && !lastname) | ||
281 | goto out; | ||
282 | if (name && lastname && !strcmp(lastname, name)) | ||
283 | goto out; | ||
284 | } | ||
285 | |||
286 | /* the queue overflowed and we already sent the Q_OVERFLOW event */ | ||
287 | if (unlikely(dev->event_count > dev->max_events)) | ||
288 | goto out; | ||
289 | |||
290 | /* if the queue overflows, we need to notify user space */ | ||
291 | if (unlikely(dev->event_count == dev->max_events)) | ||
292 | kevent = kernel_event(-1, IN_Q_OVERFLOW, cookie, NULL); | ||
293 | else | ||
294 | kevent = kernel_event(wd, mask, cookie, name); | ||
295 | |||
296 | if (unlikely(!kevent)) | ||
297 | goto out; | ||
298 | |||
299 | /* queue the event and wake up anyone waiting */ | ||
300 | dev->event_count++; | ||
301 | dev->queue_size += sizeof(struct inotify_event) + kevent->event.len; | ||
302 | list_add_tail(&kevent->list, &dev->events); | ||
303 | wake_up_interruptible(&dev->wq); | ||
304 | |||
305 | out: | ||
306 | mutex_unlock(&dev->ev_mutex); | ||
307 | } | ||
308 | |||
309 | /* | ||
310 | * remove_kevent - cleans up and ultimately frees the given kevent | ||
311 | * | ||
312 | * Caller must hold dev->ev_mutex. | ||
313 | */ | ||
314 | static void remove_kevent(struct inotify_device *dev, | ||
315 | struct inotify_kernel_event *kevent) | ||
316 | { | ||
317 | list_del(&kevent->list); | ||
318 | |||
319 | dev->event_count--; | ||
320 | dev->queue_size -= sizeof(struct inotify_event) + kevent->event.len; | ||
321 | |||
322 | kfree(kevent->name); | ||
323 | kmem_cache_free(event_cachep, kevent); | ||
324 | } | ||
325 | |||
326 | /* | ||
327 | * inotify_dev_event_dequeue - destroy an event on the given device | ||
328 | * | ||
329 | * Caller must hold dev->ev_mutex. | ||
330 | */ | ||
331 | static void inotify_dev_event_dequeue(struct inotify_device *dev) | ||
332 | { | ||
333 | if (!list_empty(&dev->events)) { | ||
334 | struct inotify_kernel_event *kevent; | ||
335 | kevent = inotify_dev_get_event(dev); | ||
336 | remove_kevent(dev, kevent); | ||
337 | } | ||
338 | } | ||
339 | |||
340 | /* | ||
341 | * find_inode - resolve a user-given path to a specific inode and return a nd | ||
342 | */ | ||
343 | static int find_inode(const char __user *dirname, struct nameidata *nd, | ||
344 | unsigned flags) | ||
345 | { | ||
346 | int error; | ||
347 | |||
348 | error = __user_walk(dirname, flags, nd); | ||
349 | if (error) | ||
350 | return error; | ||
351 | /* you can only watch an inode if you have read permissions on it */ | ||
352 | error = vfs_permission(nd, MAY_READ); | ||
353 | if (error) | ||
354 | path_release(nd); | ||
355 | return error; | ||
356 | } | ||
357 | |||
358 | /* | ||
359 | * create_watch - creates a watch on the given device. | ||
360 | * | ||
361 | * Callers must hold dev->up_mutex. | ||
362 | */ | ||
363 | static int create_watch(struct inotify_device *dev, struct inode *inode, | ||
364 | u32 mask) | ||
365 | { | ||
366 | struct inotify_user_watch *watch; | ||
367 | int ret; | ||
368 | |||
369 | if (atomic_read(&dev->user->inotify_watches) >= | ||
370 | inotify_max_user_watches) | ||
371 | return -ENOSPC; | ||
372 | |||
373 | watch = kmem_cache_alloc(watch_cachep, GFP_KERNEL); | ||
374 | if (unlikely(!watch)) | ||
375 | return -ENOMEM; | ||
376 | |||
377 | /* save a reference to device and bump the count to make it official */ | ||
378 | get_inotify_dev(dev); | ||
379 | watch->dev = dev; | ||
380 | |||
381 | atomic_inc(&dev->user->inotify_watches); | ||
382 | |||
383 | inotify_init_watch(&watch->wdata); | ||
384 | ret = inotify_add_watch(dev->ih, &watch->wdata, inode, mask); | ||
385 | if (ret < 0) | ||
386 | free_inotify_user_watch(&watch->wdata); | ||
387 | |||
388 | return ret; | ||
389 | } | ||
390 | |||
391 | /* Device Interface */ | ||
392 | |||
393 | static unsigned int inotify_poll(struct file *file, poll_table *wait) | ||
394 | { | ||
395 | struct inotify_device *dev = file->private_data; | ||
396 | int ret = 0; | ||
397 | |||
398 | poll_wait(file, &dev->wq, wait); | ||
399 | mutex_lock(&dev->ev_mutex); | ||
400 | if (!list_empty(&dev->events)) | ||
401 | ret = POLLIN | POLLRDNORM; | ||
402 | mutex_unlock(&dev->ev_mutex); | ||
403 | |||
404 | return ret; | ||
405 | } | ||
406 | |||
407 | static ssize_t inotify_read(struct file *file, char __user *buf, | ||
408 | size_t count, loff_t *pos) | ||
409 | { | ||
410 | size_t event_size = sizeof (struct inotify_event); | ||
411 | struct inotify_device *dev; | ||
412 | char __user *start; | ||
413 | int ret; | ||
414 | DEFINE_WAIT(wait); | ||
415 | |||
416 | start = buf; | ||
417 | dev = file->private_data; | ||
418 | |||
419 | while (1) { | ||
420 | int events; | ||
421 | |||
422 | prepare_to_wait(&dev->wq, &wait, TASK_INTERRUPTIBLE); | ||
423 | |||
424 | mutex_lock(&dev->ev_mutex); | ||
425 | events = !list_empty(&dev->events); | ||
426 | mutex_unlock(&dev->ev_mutex); | ||
427 | if (events) { | ||
428 | ret = 0; | ||
429 | break; | ||
430 | } | ||
431 | |||
432 | if (file->f_flags & O_NONBLOCK) { | ||
433 | ret = -EAGAIN; | ||
434 | break; | ||
435 | } | ||
436 | |||
437 | if (signal_pending(current)) { | ||
438 | ret = -EINTR; | ||
439 | break; | ||
440 | } | ||
441 | |||
442 | schedule(); | ||
443 | } | ||
444 | |||
445 | finish_wait(&dev->wq, &wait); | ||
446 | if (ret) | ||
447 | return ret; | ||
448 | |||
449 | mutex_lock(&dev->ev_mutex); | ||
450 | while (1) { | ||
451 | struct inotify_kernel_event *kevent; | ||
452 | |||
453 | ret = buf - start; | ||
454 | if (list_empty(&dev->events)) | ||
455 | break; | ||
456 | |||
457 | kevent = inotify_dev_get_event(dev); | ||
458 | if (event_size + kevent->event.len > count) | ||
459 | break; | ||
460 | |||
461 | if (copy_to_user(buf, &kevent->event, event_size)) { | ||
462 | ret = -EFAULT; | ||
463 | break; | ||
464 | } | ||
465 | buf += event_size; | ||
466 | count -= event_size; | ||
467 | |||
468 | if (kevent->name) { | ||
469 | if (copy_to_user(buf, kevent->name, kevent->event.len)){ | ||
470 | ret = -EFAULT; | ||
471 | break; | ||
472 | } | ||
473 | buf += kevent->event.len; | ||
474 | count -= kevent->event.len; | ||
475 | } | ||
476 | |||
477 | remove_kevent(dev, kevent); | ||
478 | } | ||
479 | mutex_unlock(&dev->ev_mutex); | ||
480 | |||
481 | return ret; | ||
482 | } | ||
483 | |||
484 | static int inotify_release(struct inode *ignored, struct file *file) | ||
485 | { | ||
486 | struct inotify_device *dev = file->private_data; | ||
487 | |||
488 | inotify_destroy(dev->ih); | ||
489 | |||
490 | /* destroy all of the events on this device */ | ||
491 | mutex_lock(&dev->ev_mutex); | ||
492 | while (!list_empty(&dev->events)) | ||
493 | inotify_dev_event_dequeue(dev); | ||
494 | mutex_unlock(&dev->ev_mutex); | ||
495 | |||
496 | /* free this device: the put matching the get in inotify_init() */ | ||
497 | put_inotify_dev(dev); | ||
498 | |||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static long inotify_ioctl(struct file *file, unsigned int cmd, | ||
503 | unsigned long arg) | ||
504 | { | ||
505 | struct inotify_device *dev; | ||
506 | void __user *p; | ||
507 | int ret = -ENOTTY; | ||
508 | |||
509 | dev = file->private_data; | ||
510 | p = (void __user *) arg; | ||
511 | |||
512 | switch (cmd) { | ||
513 | case FIONREAD: | ||
514 | ret = put_user(dev->queue_size, (int __user *) p); | ||
515 | break; | ||
516 | } | ||
517 | |||
518 | return ret; | ||
519 | } | ||
520 | |||
521 | static const struct file_operations inotify_fops = { | ||
522 | .poll = inotify_poll, | ||
523 | .read = inotify_read, | ||
524 | .release = inotify_release, | ||
525 | .unlocked_ioctl = inotify_ioctl, | ||
526 | .compat_ioctl = inotify_ioctl, | ||
527 | }; | ||
528 | |||
529 | static const struct inotify_operations inotify_user_ops = { | ||
530 | .handle_event = inotify_dev_queue_event, | ||
531 | .destroy_watch = free_inotify_user_watch, | ||
532 | }; | ||
533 | |||
534 | asmlinkage long sys_inotify_init(void) | ||
535 | { | ||
536 | struct inotify_device *dev; | ||
537 | struct inotify_handle *ih; | ||
538 | struct user_struct *user; | ||
539 | struct file *filp; | ||
540 | int fd, ret; | ||
541 | |||
542 | fd = get_unused_fd(); | ||
543 | if (fd < 0) | ||
544 | return fd; | ||
545 | |||
546 | filp = get_empty_filp(); | ||
547 | if (!filp) { | ||
548 | ret = -ENFILE; | ||
549 | goto out_put_fd; | ||
550 | } | ||
551 | |||
552 | user = get_uid(current->user); | ||
553 | if (unlikely(atomic_read(&user->inotify_devs) >= | ||
554 | inotify_max_user_instances)) { | ||
555 | ret = -EMFILE; | ||
556 | goto out_free_uid; | ||
557 | } | ||
558 | |||
559 | dev = kmalloc(sizeof(struct inotify_device), GFP_KERNEL); | ||
560 | if (unlikely(!dev)) { | ||
561 | ret = -ENOMEM; | ||
562 | goto out_free_uid; | ||
563 | } | ||
564 | |||
565 | ih = inotify_init(&inotify_user_ops); | ||
566 | if (unlikely(IS_ERR(ih))) { | ||
567 | ret = PTR_ERR(ih); | ||
568 | goto out_free_dev; | ||
569 | } | ||
570 | dev->ih = ih; | ||
571 | |||
572 | filp->f_op = &inotify_fops; | ||
573 | filp->f_vfsmnt = mntget(inotify_mnt); | ||
574 | filp->f_dentry = dget(inotify_mnt->mnt_root); | ||
575 | filp->f_mapping = filp->f_dentry->d_inode->i_mapping; | ||
576 | filp->f_mode = FMODE_READ; | ||
577 | filp->f_flags = O_RDONLY; | ||
578 | filp->private_data = dev; | ||
579 | |||
580 | INIT_LIST_HEAD(&dev->events); | ||
581 | init_waitqueue_head(&dev->wq); | ||
582 | mutex_init(&dev->ev_mutex); | ||
583 | mutex_init(&dev->up_mutex); | ||
584 | dev->event_count = 0; | ||
585 | dev->queue_size = 0; | ||
586 | dev->max_events = inotify_max_queued_events; | ||
587 | dev->user = user; | ||
588 | atomic_set(&dev->count, 0); | ||
589 | |||
590 | get_inotify_dev(dev); | ||
591 | atomic_inc(&user->inotify_devs); | ||
592 | fd_install(fd, filp); | ||
593 | |||
594 | return fd; | ||
595 | out_free_dev: | ||
596 | kfree(dev); | ||
597 | out_free_uid: | ||
598 | free_uid(user); | ||
599 | put_filp(filp); | ||
600 | out_put_fd: | ||
601 | put_unused_fd(fd); | ||
602 | return ret; | ||
603 | } | ||
604 | |||
605 | asmlinkage long sys_inotify_add_watch(int fd, const char __user *path, u32 mask) | ||
606 | { | ||
607 | struct inode *inode; | ||
608 | struct inotify_device *dev; | ||
609 | struct nameidata nd; | ||
610 | struct file *filp; | ||
611 | int ret, fput_needed; | ||
612 | unsigned flags = 0; | ||
613 | |||
614 | filp = fget_light(fd, &fput_needed); | ||
615 | if (unlikely(!filp)) | ||
616 | return -EBADF; | ||
617 | |||
618 | /* verify that this is indeed an inotify instance */ | ||
619 | if (unlikely(filp->f_op != &inotify_fops)) { | ||
620 | ret = -EINVAL; | ||
621 | goto fput_and_out; | ||
622 | } | ||
623 | |||
624 | if (!(mask & IN_DONT_FOLLOW)) | ||
625 | flags |= LOOKUP_FOLLOW; | ||
626 | if (mask & IN_ONLYDIR) | ||
627 | flags |= LOOKUP_DIRECTORY; | ||
628 | |||
629 | ret = find_inode(path, &nd, flags); | ||
630 | if (unlikely(ret)) | ||
631 | goto fput_and_out; | ||
632 | |||
633 | /* inode held in place by reference to nd; dev by fget on fd */ | ||
634 | inode = nd.dentry->d_inode; | ||
635 | dev = filp->private_data; | ||
636 | |||
637 | mutex_lock(&dev->up_mutex); | ||
638 | ret = inotify_find_update_watch(dev->ih, inode, mask); | ||
639 | if (ret == -ENOENT) | ||
640 | ret = create_watch(dev, inode, mask); | ||
641 | mutex_unlock(&dev->up_mutex); | ||
642 | |||
643 | path_release(&nd); | ||
644 | fput_and_out: | ||
645 | fput_light(filp, fput_needed); | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | asmlinkage long sys_inotify_rm_watch(int fd, u32 wd) | ||
650 | { | ||
651 | struct file *filp; | ||
652 | struct inotify_device *dev; | ||
653 | int ret, fput_needed; | ||
654 | |||
655 | filp = fget_light(fd, &fput_needed); | ||
656 | if (unlikely(!filp)) | ||
657 | return -EBADF; | ||
658 | |||
659 | /* verify that this is indeed an inotify instance */ | ||
660 | if (unlikely(filp->f_op != &inotify_fops)) { | ||
661 | ret = -EINVAL; | ||
662 | goto out; | ||
663 | } | ||
664 | |||
665 | dev = filp->private_data; | ||
666 | |||
667 | /* we free our watch data when we get IN_IGNORED */ | ||
668 | ret = inotify_rm_wd(dev->ih, wd); | ||
669 | |||
670 | out: | ||
671 | fput_light(filp, fput_needed); | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static int | ||
676 | inotify_get_sb(struct file_system_type *fs_type, int flags, | ||
677 | const char *dev_name, void *data, struct vfsmount *mnt) | ||
678 | { | ||
679 | return get_sb_pseudo(fs_type, "inotify", NULL, 0xBAD1DEA, mnt); | ||
680 | } | ||
681 | |||
682 | static struct file_system_type inotify_fs_type = { | ||
683 | .name = "inotifyfs", | ||
684 | .get_sb = inotify_get_sb, | ||
685 | .kill_sb = kill_anon_super, | ||
686 | }; | ||
687 | |||
688 | /* | ||
689 | * inotify_user_setup - Our initialization function. Note that we cannnot return | ||
690 | * error because we have compiled-in VFS hooks. So an (unlikely) failure here | ||
691 | * must result in panic(). | ||
692 | */ | ||
693 | static int __init inotify_user_setup(void) | ||
694 | { | ||
695 | int ret; | ||
696 | |||
697 | ret = register_filesystem(&inotify_fs_type); | ||
698 | if (unlikely(ret)) | ||
699 | panic("inotify: register_filesystem returned %d!\n", ret); | ||
700 | |||
701 | inotify_mnt = kern_mount(&inotify_fs_type); | ||
702 | if (IS_ERR(inotify_mnt)) | ||
703 | panic("inotify: kern_mount ret %ld!\n", PTR_ERR(inotify_mnt)); | ||
704 | |||
705 | inotify_max_queued_events = 16384; | ||
706 | inotify_max_user_instances = 128; | ||
707 | inotify_max_user_watches = 8192; | ||
708 | |||
709 | watch_cachep = kmem_cache_create("inotify_watch_cache", | ||
710 | sizeof(struct inotify_user_watch), | ||
711 | 0, SLAB_PANIC, NULL, NULL); | ||
712 | event_cachep = kmem_cache_create("inotify_event_cache", | ||
713 | sizeof(struct inotify_kernel_event), | ||
714 | 0, SLAB_PANIC, NULL, NULL); | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | module_init(inotify_user_setup); | ||
diff --git a/fs/ioprio.c b/fs/ioprio.c index ca77008146c0..7fa76ed53c10 100644 --- a/fs/ioprio.c +++ b/fs/ioprio.c | |||
@@ -24,15 +24,21 @@ | |||
24 | #include <linux/blkdev.h> | 24 | #include <linux/blkdev.h> |
25 | #include <linux/capability.h> | 25 | #include <linux/capability.h> |
26 | #include <linux/syscalls.h> | 26 | #include <linux/syscalls.h> |
27 | #include <linux/security.h> | ||
27 | 28 | ||
28 | static int set_task_ioprio(struct task_struct *task, int ioprio) | 29 | static int set_task_ioprio(struct task_struct *task, int ioprio) |
29 | { | 30 | { |
31 | int err; | ||
30 | struct io_context *ioc; | 32 | struct io_context *ioc; |
31 | 33 | ||
32 | if (task->uid != current->euid && | 34 | if (task->uid != current->euid && |
33 | task->uid != current->uid && !capable(CAP_SYS_NICE)) | 35 | task->uid != current->uid && !capable(CAP_SYS_NICE)) |
34 | return -EPERM; | 36 | return -EPERM; |
35 | 37 | ||
38 | err = security_task_setioprio(task, ioprio); | ||
39 | if (err) | ||
40 | return err; | ||
41 | |||
36 | task_lock(task); | 42 | task_lock(task); |
37 | 43 | ||
38 | task->ioprio = ioprio; | 44 | task->ioprio = ioprio; |
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 70adbb98bad1..3f9c8ba1fa1f 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
@@ -56,7 +56,7 @@ static void isofs_put_super(struct super_block *sb) | |||
56 | } | 56 | } |
57 | 57 | ||
58 | static void isofs_read_inode(struct inode *); | 58 | static void isofs_read_inode(struct inode *); |
59 | static int isofs_statfs (struct super_block *, struct kstatfs *); | 59 | static int isofs_statfs (struct dentry *, struct kstatfs *); |
60 | 60 | ||
61 | static kmem_cache_t *isofs_inode_cachep; | 61 | static kmem_cache_t *isofs_inode_cachep; |
62 | 62 | ||
@@ -901,8 +901,10 @@ out_freesbi: | |||
901 | return -EINVAL; | 901 | return -EINVAL; |
902 | } | 902 | } |
903 | 903 | ||
904 | static int isofs_statfs (struct super_block *sb, struct kstatfs *buf) | 904 | static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) |
905 | { | 905 | { |
906 | struct super_block *sb = dentry->d_sb; | ||
907 | |||
906 | buf->f_type = ISOFS_SUPER_MAGIC; | 908 | buf->f_type = ISOFS_SUPER_MAGIC; |
907 | buf->f_bsize = sb->s_blocksize; | 909 | buf->f_bsize = sb->s_blocksize; |
908 | buf->f_blocks = (ISOFS_SB(sb)->s_nzones | 910 | buf->f_blocks = (ISOFS_SB(sb)->s_nzones |
@@ -1399,10 +1401,11 @@ struct inode *isofs_iget(struct super_block *sb, | |||
1399 | return inode; | 1401 | return inode; |
1400 | } | 1402 | } |
1401 | 1403 | ||
1402 | static struct super_block *isofs_get_sb(struct file_system_type *fs_type, | 1404 | static int isofs_get_sb(struct file_system_type *fs_type, |
1403 | int flags, const char *dev_name, void *data) | 1405 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1404 | { | 1406 | { |
1405 | return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super); | 1407 | return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, |
1408 | mnt); | ||
1406 | } | 1409 | } |
1407 | 1410 | ||
1408 | static struct file_system_type iso9660_fs_type = { | 1411 | static struct file_system_type iso9660_fs_type = { |
diff --git a/fs/jbd/checkpoint.c b/fs/jbd/checkpoint.c index 3f5102b069db..47678a26c13b 100644 --- a/fs/jbd/checkpoint.c +++ b/fs/jbd/checkpoint.c | |||
@@ -24,29 +24,67 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * Unlink a buffer from a transaction. | 27 | * Unlink a buffer from a transaction checkpoint list. |
28 | * | 28 | * |
29 | * Called with j_list_lock held. | 29 | * Called with j_list_lock held. |
30 | */ | 30 | */ |
31 | 31 | static inline void __buffer_unlink_first(struct journal_head *jh) | |
32 | static inline void __buffer_unlink(struct journal_head *jh) | ||
33 | { | 32 | { |
34 | transaction_t *transaction; | 33 | transaction_t *transaction = jh->b_cp_transaction; |
35 | |||
36 | transaction = jh->b_cp_transaction; | ||
37 | jh->b_cp_transaction = NULL; | ||
38 | 34 | ||
39 | jh->b_cpnext->b_cpprev = jh->b_cpprev; | 35 | jh->b_cpnext->b_cpprev = jh->b_cpprev; |
40 | jh->b_cpprev->b_cpnext = jh->b_cpnext; | 36 | jh->b_cpprev->b_cpnext = jh->b_cpnext; |
41 | if (transaction->t_checkpoint_list == jh) | 37 | if (transaction->t_checkpoint_list == jh) { |
42 | transaction->t_checkpoint_list = jh->b_cpnext; | 38 | transaction->t_checkpoint_list = jh->b_cpnext; |
43 | if (transaction->t_checkpoint_list == jh) | 39 | if (transaction->t_checkpoint_list == jh) |
44 | transaction->t_checkpoint_list = NULL; | 40 | transaction->t_checkpoint_list = NULL; |
41 | } | ||
42 | } | ||
43 | |||
44 | /* | ||
45 | * Unlink a buffer from a transaction checkpoint(io) list. | ||
46 | * | ||
47 | * Called with j_list_lock held. | ||
48 | */ | ||
49 | static inline void __buffer_unlink(struct journal_head *jh) | ||
50 | { | ||
51 | transaction_t *transaction = jh->b_cp_transaction; | ||
52 | |||
53 | __buffer_unlink_first(jh); | ||
54 | if (transaction->t_checkpoint_io_list == jh) { | ||
55 | transaction->t_checkpoint_io_list = jh->b_cpnext; | ||
56 | if (transaction->t_checkpoint_io_list == jh) | ||
57 | transaction->t_checkpoint_io_list = NULL; | ||
58 | } | ||
59 | } | ||
60 | |||
61 | /* | ||
62 | * Move a buffer from the checkpoint list to the checkpoint io list | ||
63 | * | ||
64 | * Called with j_list_lock held | ||
65 | */ | ||
66 | static inline void __buffer_relink_io(struct journal_head *jh) | ||
67 | { | ||
68 | transaction_t *transaction = jh->b_cp_transaction; | ||
69 | |||
70 | __buffer_unlink_first(jh); | ||
71 | |||
72 | if (!transaction->t_checkpoint_io_list) { | ||
73 | jh->b_cpnext = jh->b_cpprev = jh; | ||
74 | } else { | ||
75 | jh->b_cpnext = transaction->t_checkpoint_io_list; | ||
76 | jh->b_cpprev = transaction->t_checkpoint_io_list->b_cpprev; | ||
77 | jh->b_cpprev->b_cpnext = jh; | ||
78 | jh->b_cpnext->b_cpprev = jh; | ||
79 | } | ||
80 | transaction->t_checkpoint_io_list = jh; | ||
45 | } | 81 | } |
46 | 82 | ||
47 | /* | 83 | /* |
48 | * Try to release a checkpointed buffer from its transaction. | 84 | * Try to release a checkpointed buffer from its transaction. |
49 | * Returns 1 if we released it. | 85 | * Returns 1 if we released it and 2 if we also released the |
86 | * whole transaction. | ||
87 | * | ||
50 | * Requires j_list_lock | 88 | * Requires j_list_lock |
51 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it | 89 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it |
52 | */ | 90 | */ |
@@ -57,12 +95,11 @@ static int __try_to_free_cp_buf(struct journal_head *jh) | |||
57 | 95 | ||
58 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { | 96 | if (jh->b_jlist == BJ_None && !buffer_locked(bh) && !buffer_dirty(bh)) { |
59 | JBUFFER_TRACE(jh, "remove from checkpoint list"); | 97 | JBUFFER_TRACE(jh, "remove from checkpoint list"); |
60 | __journal_remove_checkpoint(jh); | 98 | ret = __journal_remove_checkpoint(jh) + 1; |
61 | jbd_unlock_bh_state(bh); | 99 | jbd_unlock_bh_state(bh); |
62 | journal_remove_journal_head(bh); | 100 | journal_remove_journal_head(bh); |
63 | BUFFER_TRACE(bh, "release"); | 101 | BUFFER_TRACE(bh, "release"); |
64 | __brelse(bh); | 102 | __brelse(bh); |
65 | ret = 1; | ||
66 | } else { | 103 | } else { |
67 | jbd_unlock_bh_state(bh); | 104 | jbd_unlock_bh_state(bh); |
68 | } | 105 | } |
@@ -117,83 +154,54 @@ static void jbd_sync_bh(journal_t *journal, struct buffer_head *bh) | |||
117 | } | 154 | } |
118 | 155 | ||
119 | /* | 156 | /* |
120 | * Clean up a transaction's checkpoint list. | 157 | * Clean up transaction's list of buffers submitted for io. |
121 | * | 158 | * We wait for any pending IO to complete and remove any clean |
122 | * We wait for any pending IO to complete and make sure any clean | 159 | * buffers. Note that we take the buffers in the opposite ordering |
123 | * buffers are removed from the transaction. | 160 | * from the one in which they were submitted for IO. |
124 | * | ||
125 | * Return 1 if we performed any actions which might have destroyed the | ||
126 | * checkpoint. (journal_remove_checkpoint() deletes the transaction when | ||
127 | * the last checkpoint buffer is cleansed) | ||
128 | * | 161 | * |
129 | * Called with j_list_lock held. | 162 | * Called with j_list_lock held. |
130 | */ | 163 | */ |
131 | static int __cleanup_transaction(journal_t *journal, transaction_t *transaction) | 164 | static void __wait_cp_io(journal_t *journal, transaction_t *transaction) |
132 | { | 165 | { |
133 | struct journal_head *jh, *next_jh, *last_jh; | 166 | struct journal_head *jh; |
134 | struct buffer_head *bh; | 167 | struct buffer_head *bh; |
135 | int ret = 0; | 168 | tid_t this_tid; |
136 | 169 | int released = 0; | |
137 | assert_spin_locked(&journal->j_list_lock); | 170 | |
138 | jh = transaction->t_checkpoint_list; | 171 | this_tid = transaction->t_tid; |
139 | if (!jh) | 172 | restart: |
140 | return 0; | 173 | /* Did somebody clean up the transaction in the meanwhile? */ |
141 | 174 | if (journal->j_checkpoint_transactions != transaction || | |
142 | last_jh = jh->b_cpprev; | 175 | transaction->t_tid != this_tid) |
143 | next_jh = jh; | 176 | return; |
144 | do { | 177 | while (!released && transaction->t_checkpoint_io_list) { |
145 | jh = next_jh; | 178 | jh = transaction->t_checkpoint_io_list; |
146 | bh = jh2bh(jh); | 179 | bh = jh2bh(jh); |
180 | if (!jbd_trylock_bh_state(bh)) { | ||
181 | jbd_sync_bh(journal, bh); | ||
182 | spin_lock(&journal->j_list_lock); | ||
183 | goto restart; | ||
184 | } | ||
147 | if (buffer_locked(bh)) { | 185 | if (buffer_locked(bh)) { |
148 | atomic_inc(&bh->b_count); | 186 | atomic_inc(&bh->b_count); |
149 | spin_unlock(&journal->j_list_lock); | 187 | spin_unlock(&journal->j_list_lock); |
188 | jbd_unlock_bh_state(bh); | ||
150 | wait_on_buffer(bh); | 189 | wait_on_buffer(bh); |
151 | /* the journal_head may have gone by now */ | 190 | /* the journal_head may have gone by now */ |
152 | BUFFER_TRACE(bh, "brelse"); | 191 | BUFFER_TRACE(bh, "brelse"); |
153 | __brelse(bh); | 192 | __brelse(bh); |
154 | goto out_return_1; | 193 | spin_lock(&journal->j_list_lock); |
194 | goto restart; | ||
155 | } | 195 | } |
156 | |||
157 | /* | 196 | /* |
158 | * This is foul | 197 | * Now in whatever state the buffer currently is, we know that |
198 | * it has been written out and so we can drop it from the list | ||
159 | */ | 199 | */ |
160 | if (!jbd_trylock_bh_state(bh)) { | 200 | released = __journal_remove_checkpoint(jh); |
161 | jbd_sync_bh(journal, bh); | 201 | jbd_unlock_bh_state(bh); |
162 | goto out_return_1; | 202 | journal_remove_journal_head(bh); |
163 | } | 203 | __brelse(bh); |
164 | 204 | } | |
165 | if (jh->b_transaction != NULL) { | ||
166 | transaction_t *t = jh->b_transaction; | ||
167 | tid_t tid = t->t_tid; | ||
168 | |||
169 | spin_unlock(&journal->j_list_lock); | ||
170 | jbd_unlock_bh_state(bh); | ||
171 | log_start_commit(journal, tid); | ||
172 | log_wait_commit(journal, tid); | ||
173 | goto out_return_1; | ||
174 | } | ||
175 | |||
176 | /* | ||
177 | * AKPM: I think the buffer_jbddirty test is redundant - it | ||
178 | * shouldn't have NULL b_transaction? | ||
179 | */ | ||
180 | next_jh = jh->b_cpnext; | ||
181 | if (!buffer_dirty(bh) && !buffer_jbddirty(bh)) { | ||
182 | BUFFER_TRACE(bh, "remove from checkpoint"); | ||
183 | __journal_remove_checkpoint(jh); | ||
184 | jbd_unlock_bh_state(bh); | ||
185 | journal_remove_journal_head(bh); | ||
186 | __brelse(bh); | ||
187 | ret = 1; | ||
188 | } else { | ||
189 | jbd_unlock_bh_state(bh); | ||
190 | } | ||
191 | } while (jh != last_jh); | ||
192 | |||
193 | return ret; | ||
194 | out_return_1: | ||
195 | spin_lock(&journal->j_list_lock); | ||
196 | return 1; | ||
197 | } | 205 | } |
198 | 206 | ||
199 | #define NR_BATCH 64 | 207 | #define NR_BATCH 64 |
@@ -203,9 +211,7 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) | |||
203 | { | 211 | { |
204 | int i; | 212 | int i; |
205 | 213 | ||
206 | spin_unlock(&journal->j_list_lock); | ||
207 | ll_rw_block(SWRITE, *batch_count, bhs); | 214 | ll_rw_block(SWRITE, *batch_count, bhs); |
208 | spin_lock(&journal->j_list_lock); | ||
209 | for (i = 0; i < *batch_count; i++) { | 215 | for (i = 0; i < *batch_count; i++) { |
210 | struct buffer_head *bh = bhs[i]; | 216 | struct buffer_head *bh = bhs[i]; |
211 | clear_buffer_jwrite(bh); | 217 | clear_buffer_jwrite(bh); |
@@ -221,19 +227,43 @@ __flush_batch(journal_t *journal, struct buffer_head **bhs, int *batch_count) | |||
221 | * Return 1 if something happened which requires us to abort the current | 227 | * Return 1 if something happened which requires us to abort the current |
222 | * scan of the checkpoint list. | 228 | * scan of the checkpoint list. |
223 | * | 229 | * |
224 | * Called with j_list_lock held. | 230 | * Called with j_list_lock held and drops it if 1 is returned |
225 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it | 231 | * Called under jbd_lock_bh_state(jh2bh(jh)), and drops it |
226 | */ | 232 | */ |
227 | static int __flush_buffer(journal_t *journal, struct journal_head *jh, | 233 | static int __process_buffer(journal_t *journal, struct journal_head *jh, |
228 | struct buffer_head **bhs, int *batch_count, | 234 | struct buffer_head **bhs, int *batch_count) |
229 | int *drop_count) | ||
230 | { | 235 | { |
231 | struct buffer_head *bh = jh2bh(jh); | 236 | struct buffer_head *bh = jh2bh(jh); |
232 | int ret = 0; | 237 | int ret = 0; |
233 | 238 | ||
234 | if (buffer_dirty(bh) && !buffer_locked(bh) && jh->b_jlist == BJ_None) { | 239 | if (buffer_locked(bh)) { |
235 | J_ASSERT_JH(jh, jh->b_transaction == NULL); | 240 | atomic_inc(&bh->b_count); |
241 | spin_unlock(&journal->j_list_lock); | ||
242 | jbd_unlock_bh_state(bh); | ||
243 | wait_on_buffer(bh); | ||
244 | /* the journal_head may have gone by now */ | ||
245 | BUFFER_TRACE(bh, "brelse"); | ||
246 | __brelse(bh); | ||
247 | ret = 1; | ||
248 | } else if (jh->b_transaction != NULL) { | ||
249 | transaction_t *t = jh->b_transaction; | ||
250 | tid_t tid = t->t_tid; | ||
236 | 251 | ||
252 | spin_unlock(&journal->j_list_lock); | ||
253 | jbd_unlock_bh_state(bh); | ||
254 | log_start_commit(journal, tid); | ||
255 | log_wait_commit(journal, tid); | ||
256 | ret = 1; | ||
257 | } else if (!buffer_dirty(bh)) { | ||
258 | J_ASSERT_JH(jh, !buffer_jbddirty(bh)); | ||
259 | BUFFER_TRACE(bh, "remove from checkpoint"); | ||
260 | __journal_remove_checkpoint(jh); | ||
261 | spin_unlock(&journal->j_list_lock); | ||
262 | jbd_unlock_bh_state(bh); | ||
263 | journal_remove_journal_head(bh); | ||
264 | __brelse(bh); | ||
265 | ret = 1; | ||
266 | } else { | ||
237 | /* | 267 | /* |
238 | * Important: we are about to write the buffer, and | 268 | * Important: we are about to write the buffer, and |
239 | * possibly block, while still holding the journal lock. | 269 | * possibly block, while still holding the journal lock. |
@@ -246,45 +276,30 @@ static int __flush_buffer(journal_t *journal, struct journal_head *jh, | |||
246 | J_ASSERT_BH(bh, !buffer_jwrite(bh)); | 276 | J_ASSERT_BH(bh, !buffer_jwrite(bh)); |
247 | set_buffer_jwrite(bh); | 277 | set_buffer_jwrite(bh); |
248 | bhs[*batch_count] = bh; | 278 | bhs[*batch_count] = bh; |
279 | __buffer_relink_io(jh); | ||
249 | jbd_unlock_bh_state(bh); | 280 | jbd_unlock_bh_state(bh); |
250 | (*batch_count)++; | 281 | (*batch_count)++; |
251 | if (*batch_count == NR_BATCH) { | 282 | if (*batch_count == NR_BATCH) { |
283 | spin_unlock(&journal->j_list_lock); | ||
252 | __flush_batch(journal, bhs, batch_count); | 284 | __flush_batch(journal, bhs, batch_count); |
253 | ret = 1; | 285 | ret = 1; |
254 | } | 286 | } |
255 | } else { | ||
256 | int last_buffer = 0; | ||
257 | if (jh->b_cpnext == jh) { | ||
258 | /* We may be about to drop the transaction. Tell the | ||
259 | * caller that the lists have changed. | ||
260 | */ | ||
261 | last_buffer = 1; | ||
262 | } | ||
263 | if (__try_to_free_cp_buf(jh)) { | ||
264 | (*drop_count)++; | ||
265 | ret = last_buffer; | ||
266 | } | ||
267 | } | 287 | } |
268 | return ret; | 288 | return ret; |
269 | } | 289 | } |
270 | 290 | ||
271 | /* | 291 | /* |
272 | * Perform an actual checkpoint. We don't write out only enough to | 292 | * Perform an actual checkpoint. We take the first transaction on the |
273 | * satisfy the current blocked requests: rather we submit a reasonably | 293 | * list of transactions to be checkpointed and send all its buffers |
274 | * sized chunk of the outstanding data to disk at once for | 294 | * to disk. We submit larger chunks of data at once. |
275 | * efficiency. __log_wait_for_space() will retry if we didn't free enough. | ||
276 | * | 295 | * |
277 | * However, we _do_ take into account the amount requested so that once | ||
278 | * the IO has been queued, we can return as soon as enough of it has | ||
279 | * completed to disk. | ||
280 | * | ||
281 | * The journal should be locked before calling this function. | 296 | * The journal should be locked before calling this function. |
282 | */ | 297 | */ |
283 | int log_do_checkpoint(journal_t *journal) | 298 | int log_do_checkpoint(journal_t *journal) |
284 | { | 299 | { |
300 | transaction_t *transaction; | ||
301 | tid_t this_tid; | ||
285 | int result; | 302 | int result; |
286 | int batch_count = 0; | ||
287 | struct buffer_head *bhs[NR_BATCH]; | ||
288 | 303 | ||
289 | jbd_debug(1, "Start checkpoint\n"); | 304 | jbd_debug(1, "Start checkpoint\n"); |
290 | 305 | ||
@@ -299,79 +314,68 @@ int log_do_checkpoint(journal_t *journal) | |||
299 | return result; | 314 | return result; |
300 | 315 | ||
301 | /* | 316 | /* |
302 | * OK, we need to start writing disk blocks. Try to free up a | 317 | * OK, we need to start writing disk blocks. Take one transaction |
303 | * quarter of the log in a single checkpoint if we can. | 318 | * and write it. |
304 | */ | 319 | */ |
320 | spin_lock(&journal->j_list_lock); | ||
321 | if (!journal->j_checkpoint_transactions) | ||
322 | goto out; | ||
323 | transaction = journal->j_checkpoint_transactions; | ||
324 | this_tid = transaction->t_tid; | ||
325 | restart: | ||
305 | /* | 326 | /* |
306 | * AKPM: check this code. I had a feeling a while back that it | 327 | * If someone cleaned up this transaction while we slept, we're |
307 | * degenerates into a busy loop at unmount time. | 328 | * done (maybe it's a new transaction, but it fell at the same |
329 | * address). | ||
308 | */ | 330 | */ |
309 | spin_lock(&journal->j_list_lock); | 331 | if (journal->j_checkpoint_transactions == transaction && |
310 | while (journal->j_checkpoint_transactions) { | 332 | transaction->t_tid == this_tid) { |
311 | transaction_t *transaction; | 333 | int batch_count = 0; |
312 | struct journal_head *jh, *last_jh, *next_jh; | 334 | struct buffer_head *bhs[NR_BATCH]; |
313 | int drop_count = 0; | 335 | struct journal_head *jh; |
314 | int cleanup_ret, retry = 0; | 336 | int retry = 0; |
315 | tid_t this_tid; | 337 | |
316 | 338 | while (!retry && transaction->t_checkpoint_list) { | |
317 | transaction = journal->j_checkpoint_transactions; | ||
318 | this_tid = transaction->t_tid; | ||
319 | jh = transaction->t_checkpoint_list; | ||
320 | last_jh = jh->b_cpprev; | ||
321 | next_jh = jh; | ||
322 | do { | ||
323 | struct buffer_head *bh; | 339 | struct buffer_head *bh; |
324 | 340 | ||
325 | jh = next_jh; | 341 | jh = transaction->t_checkpoint_list; |
326 | next_jh = jh->b_cpnext; | ||
327 | bh = jh2bh(jh); | 342 | bh = jh2bh(jh); |
328 | if (!jbd_trylock_bh_state(bh)) { | 343 | if (!jbd_trylock_bh_state(bh)) { |
329 | jbd_sync_bh(journal, bh); | 344 | jbd_sync_bh(journal, bh); |
330 | spin_lock(&journal->j_list_lock); | ||
331 | retry = 1; | 345 | retry = 1; |
332 | break; | 346 | break; |
333 | } | 347 | } |
334 | retry = __flush_buffer(journal, jh, bhs, &batch_count, &drop_count); | 348 | retry = __process_buffer(journal, jh, bhs,&batch_count); |
335 | if (cond_resched_lock(&journal->j_list_lock)) { | 349 | if (!retry && lock_need_resched(&journal->j_list_lock)){ |
350 | spin_unlock(&journal->j_list_lock); | ||
336 | retry = 1; | 351 | retry = 1; |
337 | break; | 352 | break; |
338 | } | 353 | } |
339 | } while (jh != last_jh && !retry); | 354 | } |
340 | 355 | ||
341 | if (batch_count) { | 356 | if (batch_count) { |
357 | if (!retry) { | ||
358 | spin_unlock(&journal->j_list_lock); | ||
359 | retry = 1; | ||
360 | } | ||
342 | __flush_batch(journal, bhs, &batch_count); | 361 | __flush_batch(journal, bhs, &batch_count); |
343 | retry = 1; | ||
344 | } | 362 | } |
345 | 363 | ||
364 | if (retry) { | ||
365 | spin_lock(&journal->j_list_lock); | ||
366 | goto restart; | ||
367 | } | ||
346 | /* | 368 | /* |
347 | * If someone cleaned up this transaction while we slept, we're | 369 | * Now we have cleaned up the first transaction's checkpoint |
348 | * done | 370 | * list. Let's clean up the second one |
349 | */ | ||
350 | if (journal->j_checkpoint_transactions != transaction) | ||
351 | break; | ||
352 | if (retry) | ||
353 | continue; | ||
354 | /* | ||
355 | * Maybe it's a new transaction, but it fell at the same | ||
356 | * address | ||
357 | */ | ||
358 | if (transaction->t_tid != this_tid) | ||
359 | continue; | ||
360 | /* | ||
361 | * We have walked the whole transaction list without | ||
362 | * finding anything to write to disk. We had better be | ||
363 | * able to make some progress or we are in trouble. | ||
364 | */ | 371 | */ |
365 | cleanup_ret = __cleanup_transaction(journal, transaction); | 372 | __wait_cp_io(journal, transaction); |
366 | J_ASSERT(drop_count != 0 || cleanup_ret != 0); | ||
367 | if (journal->j_checkpoint_transactions != transaction) | ||
368 | break; | ||
369 | } | 373 | } |
374 | out: | ||
370 | spin_unlock(&journal->j_list_lock); | 375 | spin_unlock(&journal->j_list_lock); |
371 | result = cleanup_journal_tail(journal); | 376 | result = cleanup_journal_tail(journal); |
372 | if (result < 0) | 377 | if (result < 0) |
373 | return result; | 378 | return result; |
374 | |||
375 | return 0; | 379 | return 0; |
376 | } | 380 | } |
377 | 381 | ||
@@ -456,52 +460,98 @@ int cleanup_journal_tail(journal_t *journal) | |||
456 | /* Checkpoint list management */ | 460 | /* Checkpoint list management */ |
457 | 461 | ||
458 | /* | 462 | /* |
463 | * journal_clean_one_cp_list | ||
464 | * | ||
465 | * Find all the written-back checkpoint buffers in the given list and release them. | ||
466 | * | ||
467 | * Called with the journal locked. | ||
468 | * Called with j_list_lock held. | ||
469 | * Returns number of bufers reaped (for debug) | ||
470 | */ | ||
471 | |||
472 | static int journal_clean_one_cp_list(struct journal_head *jh, int *released) | ||
473 | { | ||
474 | struct journal_head *last_jh; | ||
475 | struct journal_head *next_jh = jh; | ||
476 | int ret, freed = 0; | ||
477 | |||
478 | *released = 0; | ||
479 | if (!jh) | ||
480 | return 0; | ||
481 | |||
482 | last_jh = jh->b_cpprev; | ||
483 | do { | ||
484 | jh = next_jh; | ||
485 | next_jh = jh->b_cpnext; | ||
486 | /* Use trylock because of the ranking */ | ||
487 | if (jbd_trylock_bh_state(jh2bh(jh))) { | ||
488 | ret = __try_to_free_cp_buf(jh); | ||
489 | if (ret) { | ||
490 | freed++; | ||
491 | if (ret == 2) { | ||
492 | *released = 1; | ||
493 | return freed; | ||
494 | } | ||
495 | } | ||
496 | } | ||
497 | /* | ||
498 | * This function only frees up some memory | ||
499 | * if possible so we dont have an obligation | ||
500 | * to finish processing. Bail out if preemption | ||
501 | * requested: | ||
502 | */ | ||
503 | if (need_resched()) | ||
504 | return freed; | ||
505 | } while (jh != last_jh); | ||
506 | |||
507 | return freed; | ||
508 | } | ||
509 | |||
510 | /* | ||
459 | * journal_clean_checkpoint_list | 511 | * journal_clean_checkpoint_list |
460 | * | 512 | * |
461 | * Find all the written-back checkpoint buffers in the journal and release them. | 513 | * Find all the written-back checkpoint buffers in the journal and release them. |
462 | * | 514 | * |
463 | * Called with the journal locked. | 515 | * Called with the journal locked. |
464 | * Called with j_list_lock held. | 516 | * Called with j_list_lock held. |
465 | * Returns number of bufers reaped (for debug) | 517 | * Returns number of buffers reaped (for debug) |
466 | */ | 518 | */ |
467 | 519 | ||
468 | int __journal_clean_checkpoint_list(journal_t *journal) | 520 | int __journal_clean_checkpoint_list(journal_t *journal) |
469 | { | 521 | { |
470 | transaction_t *transaction, *last_transaction, *next_transaction; | 522 | transaction_t *transaction, *last_transaction, *next_transaction; |
471 | int ret = 0; | 523 | int ret = 0; |
524 | int released; | ||
472 | 525 | ||
473 | transaction = journal->j_checkpoint_transactions; | 526 | transaction = journal->j_checkpoint_transactions; |
474 | if (transaction == 0) | 527 | if (!transaction) |
475 | goto out; | 528 | goto out; |
476 | 529 | ||
477 | last_transaction = transaction->t_cpprev; | 530 | last_transaction = transaction->t_cpprev; |
478 | next_transaction = transaction; | 531 | next_transaction = transaction; |
479 | do { | 532 | do { |
480 | struct journal_head *jh; | ||
481 | |||
482 | transaction = next_transaction; | 533 | transaction = next_transaction; |
483 | next_transaction = transaction->t_cpnext; | 534 | next_transaction = transaction->t_cpnext; |
484 | jh = transaction->t_checkpoint_list; | 535 | ret += journal_clean_one_cp_list(transaction-> |
485 | if (jh) { | 536 | t_checkpoint_list, &released); |
486 | struct journal_head *last_jh = jh->b_cpprev; | 537 | /* |
487 | struct journal_head *next_jh = jh; | 538 | * This function only frees up some memory if possible so we |
488 | 539 | * dont have an obligation to finish processing. Bail out if | |
489 | do { | 540 | * preemption requested: |
490 | jh = next_jh; | 541 | */ |
491 | next_jh = jh->b_cpnext; | 542 | if (need_resched()) |
492 | /* Use trylock because of the ranknig */ | 543 | goto out; |
493 | if (jbd_trylock_bh_state(jh2bh(jh))) | 544 | if (released) |
494 | ret += __try_to_free_cp_buf(jh); | 545 | continue; |
495 | /* | 546 | /* |
496 | * This function only frees up some memory | 547 | * It is essential that we are as careful as in the case of |
497 | * if possible so we dont have an obligation | 548 | * t_checkpoint_list with removing the buffer from the list as |
498 | * to finish processing. Bail out if preemption | 549 | * we can possibly see not yet submitted buffers on io_list |
499 | * requested: | 550 | */ |
500 | */ | 551 | ret += journal_clean_one_cp_list(transaction-> |
501 | if (need_resched()) | 552 | t_checkpoint_io_list, &released); |
502 | goto out; | 553 | if (need_resched()) |
503 | } while (jh != last_jh); | 554 | goto out; |
504 | } | ||
505 | } while (transaction != last_transaction); | 555 | } while (transaction != last_transaction); |
506 | out: | 556 | out: |
507 | return ret; | 557 | return ret; |
@@ -516,18 +566,22 @@ out: | |||
516 | * buffer updates committed in that transaction have safely been stored | 566 | * buffer updates committed in that transaction have safely been stored |
517 | * elsewhere on disk. To achieve this, all of the buffers in a | 567 | * elsewhere on disk. To achieve this, all of the buffers in a |
518 | * transaction need to be maintained on the transaction's checkpoint | 568 | * transaction need to be maintained on the transaction's checkpoint |
519 | * list until they have been rewritten, at which point this function is | 569 | * lists until they have been rewritten, at which point this function is |
520 | * called to remove the buffer from the existing transaction's | 570 | * called to remove the buffer from the existing transaction's |
521 | * checkpoint list. | 571 | * checkpoint lists. |
572 | * | ||
573 | * The function returns 1 if it frees the transaction, 0 otherwise. | ||
522 | * | 574 | * |
523 | * This function is called with the journal locked. | 575 | * This function is called with the journal locked. |
524 | * This function is called with j_list_lock held. | 576 | * This function is called with j_list_lock held. |
577 | * This function is called with jbd_lock_bh_state(jh2bh(jh)) | ||
525 | */ | 578 | */ |
526 | 579 | ||
527 | void __journal_remove_checkpoint(struct journal_head *jh) | 580 | int __journal_remove_checkpoint(struct journal_head *jh) |
528 | { | 581 | { |
529 | transaction_t *transaction; | 582 | transaction_t *transaction; |
530 | journal_t *journal; | 583 | journal_t *journal; |
584 | int ret = 0; | ||
531 | 585 | ||
532 | JBUFFER_TRACE(jh, "entry"); | 586 | JBUFFER_TRACE(jh, "entry"); |
533 | 587 | ||
@@ -538,8 +592,10 @@ void __journal_remove_checkpoint(struct journal_head *jh) | |||
538 | journal = transaction->t_journal; | 592 | journal = transaction->t_journal; |
539 | 593 | ||
540 | __buffer_unlink(jh); | 594 | __buffer_unlink(jh); |
595 | jh->b_cp_transaction = NULL; | ||
541 | 596 | ||
542 | if (transaction->t_checkpoint_list != NULL) | 597 | if (transaction->t_checkpoint_list != NULL || |
598 | transaction->t_checkpoint_io_list != NULL) | ||
543 | goto out; | 599 | goto out; |
544 | JBUFFER_TRACE(jh, "transaction has no more buffers"); | 600 | JBUFFER_TRACE(jh, "transaction has no more buffers"); |
545 | 601 | ||
@@ -565,8 +621,10 @@ void __journal_remove_checkpoint(struct journal_head *jh) | |||
565 | /* Just in case anybody was waiting for more transactions to be | 621 | /* Just in case anybody was waiting for more transactions to be |
566 | checkpointed... */ | 622 | checkpointed... */ |
567 | wake_up(&journal->j_wait_logspace); | 623 | wake_up(&journal->j_wait_logspace); |
624 | ret = 1; | ||
568 | out: | 625 | out: |
569 | JBUFFER_TRACE(jh, "exit"); | 626 | JBUFFER_TRACE(jh, "exit"); |
627 | return ret; | ||
570 | } | 628 | } |
571 | 629 | ||
572 | /* | 630 | /* |
@@ -628,6 +686,7 @@ void __journal_drop_transaction(journal_t *journal, transaction_t *transaction) | |||
628 | J_ASSERT(transaction->t_shadow_list == NULL); | 686 | J_ASSERT(transaction->t_shadow_list == NULL); |
629 | J_ASSERT(transaction->t_log_list == NULL); | 687 | J_ASSERT(transaction->t_log_list == NULL); |
630 | J_ASSERT(transaction->t_checkpoint_list == NULL); | 688 | J_ASSERT(transaction->t_checkpoint_list == NULL); |
689 | J_ASSERT(transaction->t_checkpoint_io_list == NULL); | ||
631 | J_ASSERT(transaction->t_updates == 0); | 690 | J_ASSERT(transaction->t_updates == 0); |
632 | J_ASSERT(journal->j_committing_transaction != transaction); | 691 | J_ASSERT(journal->j_committing_transaction != transaction); |
633 | J_ASSERT(journal->j_running_transaction != transaction); | 692 | J_ASSERT(journal->j_running_transaction != transaction); |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 002ad2bbc769..0971814c38b8 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
@@ -790,11 +790,22 @@ restart_loop: | |||
790 | jbd_unlock_bh_state(bh); | 790 | jbd_unlock_bh_state(bh); |
791 | } else { | 791 | } else { |
792 | J_ASSERT_BH(bh, !buffer_dirty(bh)); | 792 | J_ASSERT_BH(bh, !buffer_dirty(bh)); |
793 | J_ASSERT_JH(jh, jh->b_next_transaction == NULL); | 793 | /* The buffer on BJ_Forget list and not jbddirty means |
794 | __journal_unfile_buffer(jh); | 794 | * it has been freed by this transaction and hence it |
795 | jbd_unlock_bh_state(bh); | 795 | * could not have been reallocated until this |
796 | journal_remove_journal_head(bh); /* needs a brelse */ | 796 | * transaction has committed. *BUT* it could be |
797 | release_buffer_page(bh); | 797 | * reallocated once we have written all the data to |
798 | * disk and before we process the buffer on BJ_Forget | ||
799 | * list. */ | ||
800 | JBUFFER_TRACE(jh, "refile or unfile freed buffer"); | ||
801 | __journal_refile_buffer(jh); | ||
802 | if (!jh->b_transaction) { | ||
803 | jbd_unlock_bh_state(bh); | ||
804 | /* needs a brelse */ | ||
805 | journal_remove_journal_head(bh); | ||
806 | release_buffer_page(bh); | ||
807 | } else | ||
808 | jbd_unlock_bh_state(bh); | ||
798 | } | 809 | } |
799 | cond_resched_lock(&journal->j_list_lock); | 810 | cond_resched_lock(&journal->j_list_lock); |
800 | } | 811 | } |
diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index c609f5034fcd..508b2ea91f43 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c | |||
@@ -227,7 +227,8 @@ repeat_locked: | |||
227 | spin_unlock(&transaction->t_handle_lock); | 227 | spin_unlock(&transaction->t_handle_lock); |
228 | spin_unlock(&journal->j_state_lock); | 228 | spin_unlock(&journal->j_state_lock); |
229 | out: | 229 | out: |
230 | kfree(new_transaction); | 230 | if (unlikely(new_transaction)) /* It's usually NULL */ |
231 | kfree(new_transaction); | ||
231 | return ret; | 232 | return ret; |
232 | } | 233 | } |
233 | 234 | ||
@@ -724,7 +725,8 @@ done: | |||
724 | journal_cancel_revoke(handle, jh); | 725 | journal_cancel_revoke(handle, jh); |
725 | 726 | ||
726 | out: | 727 | out: |
727 | kfree(frozen_buffer); | 728 | if (unlikely(frozen_buffer)) /* It's usually NULL */ |
729 | kfree(frozen_buffer); | ||
728 | 730 | ||
729 | JBUFFER_TRACE(jh, "exit"); | 731 | JBUFFER_TRACE(jh, "exit"); |
730 | return error; | 732 | return error; |
@@ -903,7 +905,8 @@ repeat: | |||
903 | jbd_unlock_bh_state(bh); | 905 | jbd_unlock_bh_state(bh); |
904 | out: | 906 | out: |
905 | journal_put_journal_head(jh); | 907 | journal_put_journal_head(jh); |
906 | kfree(committed_data); | 908 | if (unlikely(committed_data)) |
909 | kfree(committed_data); | ||
907 | return err; | 910 | return err; |
908 | } | 911 | } |
909 | 912 | ||
@@ -2038,7 +2041,8 @@ void __journal_refile_buffer(struct journal_head *jh) | |||
2038 | __journal_temp_unlink_buffer(jh); | 2041 | __journal_temp_unlink_buffer(jh); |
2039 | jh->b_transaction = jh->b_next_transaction; | 2042 | jh->b_transaction = jh->b_next_transaction; |
2040 | jh->b_next_transaction = NULL; | 2043 | jh->b_next_transaction = NULL; |
2041 | __journal_file_buffer(jh, jh->b_transaction, BJ_Metadata); | 2044 | __journal_file_buffer(jh, jh->b_transaction, |
2045 | was_dirty ? BJ_Metadata : BJ_Reserved); | ||
2042 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); | 2046 | J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); |
2043 | 2047 | ||
2044 | if (was_dirty) | 2048 | if (was_dirty) |
diff --git a/fs/jffs/inode-v23.c b/fs/jffs/inode-v23.c index 020cc097c539..9e46ea6da752 100644 --- a/fs/jffs/inode-v23.c +++ b/fs/jffs/inode-v23.c | |||
@@ -377,9 +377,9 @@ jffs_new_inode(const struct inode * dir, struct jffs_raw_inode *raw_inode, | |||
377 | 377 | ||
378 | /* Get statistics of the file system. */ | 378 | /* Get statistics of the file system. */ |
379 | static int | 379 | static int |
380 | jffs_statfs(struct super_block *sb, struct kstatfs *buf) | 380 | jffs_statfs(struct dentry *dentry, struct kstatfs *buf) |
381 | { | 381 | { |
382 | struct jffs_control *c = (struct jffs_control *) sb->s_fs_info; | 382 | struct jffs_control *c = (struct jffs_control *) dentry->d_sb->s_fs_info; |
383 | struct jffs_fmcontrol *fmc; | 383 | struct jffs_fmcontrol *fmc; |
384 | 384 | ||
385 | lock_kernel(); | 385 | lock_kernel(); |
@@ -1785,10 +1785,11 @@ static struct super_operations jffs_ops = | |||
1785 | .remount_fs = jffs_remount, | 1785 | .remount_fs = jffs_remount, |
1786 | }; | 1786 | }; |
1787 | 1787 | ||
1788 | static struct super_block *jffs_get_sb(struct file_system_type *fs_type, | 1788 | static int jffs_get_sb(struct file_system_type *fs_type, |
1789 | int flags, const char *dev_name, void *data) | 1789 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1790 | { | 1790 | { |
1791 | return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super); | 1791 | return get_sb_bdev(fs_type, flags, dev_name, data, jffs_fill_super, |
1792 | mnt); | ||
1792 | } | 1793 | } |
1793 | 1794 | ||
1794 | static struct file_system_type jffs_fs_type = { | 1795 | static struct file_system_type jffs_fs_type = { |
diff --git a/fs/jffs/intrep.c b/fs/jffs/intrep.c index 0ef207dfaf6f..5371a403130a 100644 --- a/fs/jffs/intrep.c +++ b/fs/jffs/intrep.c | |||
@@ -247,7 +247,7 @@ flash_safe_read(struct mtd_info *mtd, loff_t from, | |||
247 | D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n", | 247 | D3(printk(KERN_NOTICE "flash_safe_read(%p, %08x, %p, %08x)\n", |
248 | mtd, (unsigned int) from, buf, count)); | 248 | mtd, (unsigned int) from, buf, count)); |
249 | 249 | ||
250 | res = MTD_READ(mtd, from, count, &retlen, buf); | 250 | res = mtd->read(mtd, from, count, &retlen, buf); |
251 | if (retlen != count) { | 251 | if (retlen != count) { |
252 | panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); | 252 | panic("Didn't read all bytes in flash_safe_read(). Returned %d\n", res); |
253 | } | 253 | } |
@@ -262,7 +262,7 @@ flash_read_u32(struct mtd_info *mtd, loff_t from) | |||
262 | __u32 ret; | 262 | __u32 ret; |
263 | int res; | 263 | int res; |
264 | 264 | ||
265 | res = MTD_READ(mtd, from, 4, &retlen, (unsigned char *)&ret); | 265 | res = mtd->read(mtd, from, 4, &retlen, (unsigned char *)&ret); |
266 | if (retlen != 4) { | 266 | if (retlen != 4) { |
267 | printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res); | 267 | printk("Didn't read all bytes in flash_read_u32(). Returned %d\n", res); |
268 | return 0; | 268 | return 0; |
@@ -282,7 +282,7 @@ flash_safe_write(struct mtd_info *mtd, loff_t to, | |||
282 | D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n", | 282 | D3(printk(KERN_NOTICE "flash_safe_write(%p, %08x, %p, %08x)\n", |
283 | mtd, (unsigned int) to, buf, count)); | 283 | mtd, (unsigned int) to, buf, count)); |
284 | 284 | ||
285 | res = MTD_WRITE(mtd, to, count, &retlen, buf); | 285 | res = mtd->write(mtd, to, count, &retlen, buf); |
286 | if (retlen != count) { | 286 | if (retlen != count) { |
287 | printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res); | 287 | printk("Didn't write all bytes in flash_safe_write(). Returned %d\n", res); |
288 | } | 288 | } |
@@ -300,9 +300,9 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
300 | 300 | ||
301 | D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n", | 301 | D3(printk(KERN_NOTICE "flash_safe_writev(%p, %08x, %p)\n", |
302 | mtd, (unsigned int) to, vecs)); | 302 | mtd, (unsigned int) to, vecs)); |
303 | 303 | ||
304 | if (mtd->writev) { | 304 | if (mtd->writev) { |
305 | res = MTD_WRITEV(mtd, vecs, iovec_cnt, to, &retlen); | 305 | res = mtd->writev(mtd, vecs, iovec_cnt, to, &retlen); |
306 | return res ? res : retlen; | 306 | return res ? res : retlen; |
307 | } | 307 | } |
308 | /* Not implemented writev. Repeatedly use write - on the not so | 308 | /* Not implemented writev. Repeatedly use write - on the not so |
@@ -312,7 +312,8 @@ flash_safe_writev(struct mtd_info *mtd, const struct kvec *vecs, | |||
312 | retlen=0; | 312 | retlen=0; |
313 | 313 | ||
314 | for (i=0; !res && i<iovec_cnt; i++) { | 314 | for (i=0; !res && i<iovec_cnt; i++) { |
315 | res = MTD_WRITE(mtd, to, vecs[i].iov_len, &retlen_a, vecs[i].iov_base); | 315 | res = mtd->write(mtd, to, vecs[i].iov_len, &retlen_a, |
316 | vecs[i].iov_base); | ||
316 | if (retlen_a != vecs[i].iov_len) { | 317 | if (retlen_a != vecs[i].iov_len) { |
317 | printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res); | 318 | printk("Didn't write all bytes in flash_safe_writev(). Returned %d\n", res); |
318 | if (i != iovec_cnt-1) | 319 | if (i != iovec_cnt-1) |
@@ -393,7 +394,7 @@ flash_erase_region(struct mtd_info *mtd, loff_t start, | |||
393 | set_current_state(TASK_UNINTERRUPTIBLE); | 394 | set_current_state(TASK_UNINTERRUPTIBLE); |
394 | add_wait_queue(&wait_q, &wait); | 395 | add_wait_queue(&wait_q, &wait); |
395 | 396 | ||
396 | if (MTD_ERASE(mtd, erase) < 0) { | 397 | if (mtd->erase(mtd, erase) < 0) { |
397 | set_current_state(TASK_RUNNING); | 398 | set_current_state(TASK_RUNNING); |
398 | remove_wait_queue(&wait_q, &wait); | 399 | remove_wait_queue(&wait_q, &wait); |
399 | kfree(erase); | 400 | kfree(erase); |
diff --git a/fs/jffs2/Makefile b/fs/jffs2/Makefile index 77dc5561a04e..7f28ee0bd132 100644 --- a/fs/jffs2/Makefile +++ b/fs/jffs2/Makefile | |||
@@ -12,6 +12,9 @@ jffs2-y += symlink.o build.o erase.o background.o fs.o writev.o | |||
12 | jffs2-y += super.o debug.o | 12 | jffs2-y += super.o debug.o |
13 | 13 | ||
14 | jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o | 14 | jffs2-$(CONFIG_JFFS2_FS_WRITEBUFFER) += wbuf.o |
15 | jffs2-$(CONFIG_JFFS2_FS_XATTR) += xattr.o xattr_trusted.o xattr_user.o | ||
16 | jffs2-$(CONFIG_JFFS2_FS_SECURITY) += security.o | ||
17 | jffs2-$(CONFIG_JFFS2_FS_POSIX_ACL) += acl.o | ||
15 | jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o | 18 | jffs2-$(CONFIG_JFFS2_RUBIN) += compr_rubin.o |
16 | jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o | 19 | jffs2-$(CONFIG_JFFS2_RTIME) += compr_rtime.o |
17 | jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o | 20 | jffs2-$(CONFIG_JFFS2_ZLIB) += compr_zlib.o |
diff --git a/fs/jffs2/README.Locking b/fs/jffs2/README.Locking index b7943439b6ec..c8f0bd64e53e 100644 --- a/fs/jffs2/README.Locking +++ b/fs/jffs2/README.Locking | |||
@@ -150,3 +150,24 @@ the buffer. | |||
150 | 150 | ||
151 | Ordering constraints: | 151 | Ordering constraints: |
152 | Lock wbuf_sem last, after the alloc_sem or and f->sem. | 152 | Lock wbuf_sem last, after the alloc_sem or and f->sem. |
153 | |||
154 | |||
155 | c->xattr_sem | ||
156 | ------------ | ||
157 | |||
158 | This read/write semaphore protects against concurrent access to the | ||
159 | xattr related objects which include stuff in superblock and ic->xref. | ||
160 | In read-only path, write-semaphore is too much exclusion. It's enough | ||
161 | by read-semaphore. But you must hold write-semaphore when updating, | ||
162 | creating or deleting any xattr related object. | ||
163 | |||
164 | Once xattr_sem released, there would be no assurance for the existence | ||
165 | of those objects. Thus, a series of processes is often required to retry, | ||
166 | when updating such a object is necessary under holding read semaphore. | ||
167 | For example, do_jffs2_getxattr() holds read-semaphore to scan xref and | ||
168 | xdatum at first. But it retries this process with holding write-semaphore | ||
169 | after release read-semaphore, if it's necessary to load name/value pair | ||
170 | from medium. | ||
171 | |||
172 | Ordering constraints: | ||
173 | Lock xattr_sem last, after the alloc_sem. | ||
diff --git a/fs/jffs2/acl.c b/fs/jffs2/acl.c new file mode 100644 index 000000000000..320dd48b834e --- /dev/null +++ b/fs/jffs2/acl.c | |||
@@ -0,0 +1,485 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/time.h> | ||
15 | #include <linux/crc32.h> | ||
16 | #include <linux/jffs2.h> | ||
17 | #include <linux/xattr.h> | ||
18 | #include <linux/posix_acl_xattr.h> | ||
19 | #include <linux/mtd/mtd.h> | ||
20 | #include "nodelist.h" | ||
21 | |||
22 | static size_t jffs2_acl_size(int count) | ||
23 | { | ||
24 | if (count <= 4) { | ||
25 | return sizeof(struct jffs2_acl_header) | ||
26 | + count * sizeof(struct jffs2_acl_entry_short); | ||
27 | } else { | ||
28 | return sizeof(struct jffs2_acl_header) | ||
29 | + 4 * sizeof(struct jffs2_acl_entry_short) | ||
30 | + (count - 4) * sizeof(struct jffs2_acl_entry); | ||
31 | } | ||
32 | } | ||
33 | |||
34 | static int jffs2_acl_count(size_t size) | ||
35 | { | ||
36 | size_t s; | ||
37 | |||
38 | size -= sizeof(struct jffs2_acl_header); | ||
39 | s = size - 4 * sizeof(struct jffs2_acl_entry_short); | ||
40 | if (s < 0) { | ||
41 | if (size % sizeof(struct jffs2_acl_entry_short)) | ||
42 | return -1; | ||
43 | return size / sizeof(struct jffs2_acl_entry_short); | ||
44 | } else { | ||
45 | if (s % sizeof(struct jffs2_acl_entry)) | ||
46 | return -1; | ||
47 | return s / sizeof(struct jffs2_acl_entry) + 4; | ||
48 | } | ||
49 | } | ||
50 | |||
51 | static struct posix_acl *jffs2_acl_from_medium(void *value, size_t size) | ||
52 | { | ||
53 | void *end = value + size; | ||
54 | struct jffs2_acl_header *header = value; | ||
55 | struct jffs2_acl_entry *entry; | ||
56 | struct posix_acl *acl; | ||
57 | uint32_t ver; | ||
58 | int i, count; | ||
59 | |||
60 | if (!value) | ||
61 | return NULL; | ||
62 | if (size < sizeof(struct jffs2_acl_header)) | ||
63 | return ERR_PTR(-EINVAL); | ||
64 | ver = je32_to_cpu(header->a_version); | ||
65 | if (ver != JFFS2_ACL_VERSION) { | ||
66 | JFFS2_WARNING("Invalid ACL version. (=%u)\n", ver); | ||
67 | return ERR_PTR(-EINVAL); | ||
68 | } | ||
69 | |||
70 | value += sizeof(struct jffs2_acl_header); | ||
71 | count = jffs2_acl_count(size); | ||
72 | if (count < 0) | ||
73 | return ERR_PTR(-EINVAL); | ||
74 | if (count == 0) | ||
75 | return NULL; | ||
76 | |||
77 | acl = posix_acl_alloc(count, GFP_KERNEL); | ||
78 | if (!acl) | ||
79 | return ERR_PTR(-ENOMEM); | ||
80 | |||
81 | for (i=0; i < count; i++) { | ||
82 | entry = value; | ||
83 | if (value + sizeof(struct jffs2_acl_entry_short) > end) | ||
84 | goto fail; | ||
85 | acl->a_entries[i].e_tag = je16_to_cpu(entry->e_tag); | ||
86 | acl->a_entries[i].e_perm = je16_to_cpu(entry->e_perm); | ||
87 | switch (acl->a_entries[i].e_tag) { | ||
88 | case ACL_USER_OBJ: | ||
89 | case ACL_GROUP_OBJ: | ||
90 | case ACL_MASK: | ||
91 | case ACL_OTHER: | ||
92 | value += sizeof(struct jffs2_acl_entry_short); | ||
93 | acl->a_entries[i].e_id = ACL_UNDEFINED_ID; | ||
94 | break; | ||
95 | |||
96 | case ACL_USER: | ||
97 | case ACL_GROUP: | ||
98 | value += sizeof(struct jffs2_acl_entry); | ||
99 | if (value > end) | ||
100 | goto fail; | ||
101 | acl->a_entries[i].e_id = je32_to_cpu(entry->e_id); | ||
102 | break; | ||
103 | |||
104 | default: | ||
105 | goto fail; | ||
106 | } | ||
107 | } | ||
108 | if (value != end) | ||
109 | goto fail; | ||
110 | return acl; | ||
111 | fail: | ||
112 | posix_acl_release(acl); | ||
113 | return ERR_PTR(-EINVAL); | ||
114 | } | ||
115 | |||
116 | static void *jffs2_acl_to_medium(const struct posix_acl *acl, size_t *size) | ||
117 | { | ||
118 | struct jffs2_acl_header *header; | ||
119 | struct jffs2_acl_entry *entry; | ||
120 | void *e; | ||
121 | size_t i; | ||
122 | |||
123 | *size = jffs2_acl_size(acl->a_count); | ||
124 | header = kmalloc(sizeof(*header) + acl->a_count * sizeof(*entry), GFP_KERNEL); | ||
125 | if (!header) | ||
126 | return ERR_PTR(-ENOMEM); | ||
127 | header->a_version = cpu_to_je32(JFFS2_ACL_VERSION); | ||
128 | e = header + 1; | ||
129 | for (i=0; i < acl->a_count; i++) { | ||
130 | entry = e; | ||
131 | entry->e_tag = cpu_to_je16(acl->a_entries[i].e_tag); | ||
132 | entry->e_perm = cpu_to_je16(acl->a_entries[i].e_perm); | ||
133 | switch(acl->a_entries[i].e_tag) { | ||
134 | case ACL_USER: | ||
135 | case ACL_GROUP: | ||
136 | entry->e_id = cpu_to_je32(acl->a_entries[i].e_id); | ||
137 | e += sizeof(struct jffs2_acl_entry); | ||
138 | break; | ||
139 | |||
140 | case ACL_USER_OBJ: | ||
141 | case ACL_GROUP_OBJ: | ||
142 | case ACL_MASK: | ||
143 | case ACL_OTHER: | ||
144 | e += sizeof(struct jffs2_acl_entry_short); | ||
145 | break; | ||
146 | |||
147 | default: | ||
148 | goto fail; | ||
149 | } | ||
150 | } | ||
151 | return header; | ||
152 | fail: | ||
153 | kfree(header); | ||
154 | return ERR_PTR(-EINVAL); | ||
155 | } | ||
156 | |||
157 | static struct posix_acl *jffs2_iget_acl(struct inode *inode, struct posix_acl **i_acl) | ||
158 | { | ||
159 | struct posix_acl *acl = JFFS2_ACL_NOT_CACHED; | ||
160 | |||
161 | spin_lock(&inode->i_lock); | ||
162 | if (*i_acl != JFFS2_ACL_NOT_CACHED) | ||
163 | acl = posix_acl_dup(*i_acl); | ||
164 | spin_unlock(&inode->i_lock); | ||
165 | return acl; | ||
166 | } | ||
167 | |||
168 | static void jffs2_iset_acl(struct inode *inode, struct posix_acl **i_acl, struct posix_acl *acl) | ||
169 | { | ||
170 | spin_lock(&inode->i_lock); | ||
171 | if (*i_acl != JFFS2_ACL_NOT_CACHED) | ||
172 | posix_acl_release(*i_acl); | ||
173 | *i_acl = posix_acl_dup(acl); | ||
174 | spin_unlock(&inode->i_lock); | ||
175 | } | ||
176 | |||
177 | static struct posix_acl *jffs2_get_acl(struct inode *inode, int type) | ||
178 | { | ||
179 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
180 | struct posix_acl *acl; | ||
181 | char *value = NULL; | ||
182 | int rc, xprefix; | ||
183 | |||
184 | switch (type) { | ||
185 | case ACL_TYPE_ACCESS: | ||
186 | acl = jffs2_iget_acl(inode, &f->i_acl_access); | ||
187 | if (acl != JFFS2_ACL_NOT_CACHED) | ||
188 | return acl; | ||
189 | xprefix = JFFS2_XPREFIX_ACL_ACCESS; | ||
190 | break; | ||
191 | case ACL_TYPE_DEFAULT: | ||
192 | acl = jffs2_iget_acl(inode, &f->i_acl_default); | ||
193 | if (acl != JFFS2_ACL_NOT_CACHED) | ||
194 | return acl; | ||
195 | xprefix = JFFS2_XPREFIX_ACL_DEFAULT; | ||
196 | break; | ||
197 | default: | ||
198 | return ERR_PTR(-EINVAL); | ||
199 | } | ||
200 | rc = do_jffs2_getxattr(inode, xprefix, "", NULL, 0); | ||
201 | if (rc > 0) { | ||
202 | value = kmalloc(rc, GFP_KERNEL); | ||
203 | if (!value) | ||
204 | return ERR_PTR(-ENOMEM); | ||
205 | rc = do_jffs2_getxattr(inode, xprefix, "", value, rc); | ||
206 | } | ||
207 | if (rc > 0) { | ||
208 | acl = jffs2_acl_from_medium(value, rc); | ||
209 | } else if (rc == -ENODATA || rc == -ENOSYS) { | ||
210 | acl = NULL; | ||
211 | } else { | ||
212 | acl = ERR_PTR(rc); | ||
213 | } | ||
214 | if (value) | ||
215 | kfree(value); | ||
216 | if (!IS_ERR(acl)) { | ||
217 | switch (type) { | ||
218 | case ACL_TYPE_ACCESS: | ||
219 | jffs2_iset_acl(inode, &f->i_acl_access, acl); | ||
220 | break; | ||
221 | case ACL_TYPE_DEFAULT: | ||
222 | jffs2_iset_acl(inode, &f->i_acl_default, acl); | ||
223 | break; | ||
224 | } | ||
225 | } | ||
226 | return acl; | ||
227 | } | ||
228 | |||
229 | static int jffs2_set_acl(struct inode *inode, int type, struct posix_acl *acl) | ||
230 | { | ||
231 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
232 | size_t size = 0; | ||
233 | char *value = NULL; | ||
234 | int rc, xprefix; | ||
235 | |||
236 | if (S_ISLNK(inode->i_mode)) | ||
237 | return -EOPNOTSUPP; | ||
238 | |||
239 | switch (type) { | ||
240 | case ACL_TYPE_ACCESS: | ||
241 | xprefix = JFFS2_XPREFIX_ACL_ACCESS; | ||
242 | if (acl) { | ||
243 | mode_t mode = inode->i_mode; | ||
244 | rc = posix_acl_equiv_mode(acl, &mode); | ||
245 | if (rc < 0) | ||
246 | return rc; | ||
247 | if (inode->i_mode != mode) { | ||
248 | inode->i_mode = mode; | ||
249 | jffs2_dirty_inode(inode); | ||
250 | } | ||
251 | if (rc == 0) | ||
252 | acl = NULL; | ||
253 | } | ||
254 | break; | ||
255 | case ACL_TYPE_DEFAULT: | ||
256 | xprefix = JFFS2_XPREFIX_ACL_DEFAULT; | ||
257 | if (!S_ISDIR(inode->i_mode)) | ||
258 | return acl ? -EACCES : 0; | ||
259 | break; | ||
260 | default: | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | if (acl) { | ||
264 | value = jffs2_acl_to_medium(acl, &size); | ||
265 | if (IS_ERR(value)) | ||
266 | return PTR_ERR(value); | ||
267 | } | ||
268 | |||
269 | rc = do_jffs2_setxattr(inode, xprefix, "", value, size, 0); | ||
270 | if (value) | ||
271 | kfree(value); | ||
272 | if (!rc) { | ||
273 | switch(type) { | ||
274 | case ACL_TYPE_ACCESS: | ||
275 | jffs2_iset_acl(inode, &f->i_acl_access, acl); | ||
276 | break; | ||
277 | case ACL_TYPE_DEFAULT: | ||
278 | jffs2_iset_acl(inode, &f->i_acl_default, acl); | ||
279 | break; | ||
280 | } | ||
281 | } | ||
282 | return rc; | ||
283 | } | ||
284 | |||
285 | static int jffs2_check_acl(struct inode *inode, int mask) | ||
286 | { | ||
287 | struct posix_acl *acl; | ||
288 | int rc; | ||
289 | |||
290 | acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); | ||
291 | if (IS_ERR(acl)) | ||
292 | return PTR_ERR(acl); | ||
293 | if (acl) { | ||
294 | rc = posix_acl_permission(inode, acl, mask); | ||
295 | posix_acl_release(acl); | ||
296 | return rc; | ||
297 | } | ||
298 | return -EAGAIN; | ||
299 | } | ||
300 | |||
301 | int jffs2_permission(struct inode *inode, int mask, struct nameidata *nd) | ||
302 | { | ||
303 | return generic_permission(inode, mask, jffs2_check_acl); | ||
304 | } | ||
305 | |||
306 | int jffs2_init_acl(struct inode *inode, struct inode *dir) | ||
307 | { | ||
308 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
309 | struct posix_acl *acl = NULL, *clone; | ||
310 | mode_t mode; | ||
311 | int rc = 0; | ||
312 | |||
313 | f->i_acl_access = JFFS2_ACL_NOT_CACHED; | ||
314 | f->i_acl_default = JFFS2_ACL_NOT_CACHED; | ||
315 | if (!S_ISLNK(inode->i_mode)) { | ||
316 | acl = jffs2_get_acl(dir, ACL_TYPE_DEFAULT); | ||
317 | if (IS_ERR(acl)) | ||
318 | return PTR_ERR(acl); | ||
319 | if (!acl) | ||
320 | inode->i_mode &= ~current->fs->umask; | ||
321 | } | ||
322 | if (acl) { | ||
323 | if (S_ISDIR(inode->i_mode)) { | ||
324 | rc = jffs2_set_acl(inode, ACL_TYPE_DEFAULT, acl); | ||
325 | if (rc) | ||
326 | goto cleanup; | ||
327 | } | ||
328 | clone = posix_acl_clone(acl, GFP_KERNEL); | ||
329 | rc = -ENOMEM; | ||
330 | if (!clone) | ||
331 | goto cleanup; | ||
332 | mode = inode->i_mode; | ||
333 | rc = posix_acl_create_masq(clone, &mode); | ||
334 | if (rc >= 0) { | ||
335 | inode->i_mode = mode; | ||
336 | if (rc > 0) | ||
337 | rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); | ||
338 | } | ||
339 | posix_acl_release(clone); | ||
340 | } | ||
341 | cleanup: | ||
342 | posix_acl_release(acl); | ||
343 | return rc; | ||
344 | } | ||
345 | |||
346 | void jffs2_clear_acl(struct inode *inode) | ||
347 | { | ||
348 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
349 | |||
350 | if (f->i_acl_access && f->i_acl_access != JFFS2_ACL_NOT_CACHED) { | ||
351 | posix_acl_release(f->i_acl_access); | ||
352 | f->i_acl_access = JFFS2_ACL_NOT_CACHED; | ||
353 | } | ||
354 | if (f->i_acl_default && f->i_acl_default != JFFS2_ACL_NOT_CACHED) { | ||
355 | posix_acl_release(f->i_acl_default); | ||
356 | f->i_acl_default = JFFS2_ACL_NOT_CACHED; | ||
357 | } | ||
358 | } | ||
359 | |||
360 | int jffs2_acl_chmod(struct inode *inode) | ||
361 | { | ||
362 | struct posix_acl *acl, *clone; | ||
363 | int rc; | ||
364 | |||
365 | if (S_ISLNK(inode->i_mode)) | ||
366 | return -EOPNOTSUPP; | ||
367 | acl = jffs2_get_acl(inode, ACL_TYPE_ACCESS); | ||
368 | if (IS_ERR(acl) || !acl) | ||
369 | return PTR_ERR(acl); | ||
370 | clone = posix_acl_clone(acl, GFP_KERNEL); | ||
371 | posix_acl_release(acl); | ||
372 | if (!clone) | ||
373 | return -ENOMEM; | ||
374 | rc = posix_acl_chmod_masq(clone, inode->i_mode); | ||
375 | if (!rc) | ||
376 | rc = jffs2_set_acl(inode, ACL_TYPE_ACCESS, clone); | ||
377 | posix_acl_release(clone); | ||
378 | return rc; | ||
379 | } | ||
380 | |||
381 | static size_t jffs2_acl_access_listxattr(struct inode *inode, char *list, size_t list_size, | ||
382 | const char *name, size_t name_len) | ||
383 | { | ||
384 | const int retlen = sizeof(POSIX_ACL_XATTR_ACCESS); | ||
385 | |||
386 | if (list && retlen <= list_size) | ||
387 | strcpy(list, POSIX_ACL_XATTR_ACCESS); | ||
388 | return retlen; | ||
389 | } | ||
390 | |||
391 | static size_t jffs2_acl_default_listxattr(struct inode *inode, char *list, size_t list_size, | ||
392 | const char *name, size_t name_len) | ||
393 | { | ||
394 | const int retlen = sizeof(POSIX_ACL_XATTR_DEFAULT); | ||
395 | |||
396 | if (list && retlen <= list_size) | ||
397 | strcpy(list, POSIX_ACL_XATTR_DEFAULT); | ||
398 | return retlen; | ||
399 | } | ||
400 | |||
401 | static int jffs2_acl_getxattr(struct inode *inode, int type, void *buffer, size_t size) | ||
402 | { | ||
403 | struct posix_acl *acl; | ||
404 | int rc; | ||
405 | |||
406 | acl = jffs2_get_acl(inode, type); | ||
407 | if (IS_ERR(acl)) | ||
408 | return PTR_ERR(acl); | ||
409 | if (!acl) | ||
410 | return -ENODATA; | ||
411 | rc = posix_acl_to_xattr(acl, buffer, size); | ||
412 | posix_acl_release(acl); | ||
413 | |||
414 | return rc; | ||
415 | } | ||
416 | |||
417 | static int jffs2_acl_access_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) | ||
418 | { | ||
419 | if (name[0] != '\0') | ||
420 | return -EINVAL; | ||
421 | return jffs2_acl_getxattr(inode, ACL_TYPE_ACCESS, buffer, size); | ||
422 | } | ||
423 | |||
424 | static int jffs2_acl_default_getxattr(struct inode *inode, const char *name, void *buffer, size_t size) | ||
425 | { | ||
426 | if (name[0] != '\0') | ||
427 | return -EINVAL; | ||
428 | return jffs2_acl_getxattr(inode, ACL_TYPE_DEFAULT, buffer, size); | ||
429 | } | ||
430 | |||
431 | static int jffs2_acl_setxattr(struct inode *inode, int type, const void *value, size_t size) | ||
432 | { | ||
433 | struct posix_acl *acl; | ||
434 | int rc; | ||
435 | |||
436 | if ((current->fsuid != inode->i_uid) && !capable(CAP_FOWNER)) | ||
437 | return -EPERM; | ||
438 | |||
439 | if (value) { | ||
440 | acl = posix_acl_from_xattr(value, size); | ||
441 | if (IS_ERR(acl)) | ||
442 | return PTR_ERR(acl); | ||
443 | if (acl) { | ||
444 | rc = posix_acl_valid(acl); | ||
445 | if (rc) | ||
446 | goto out; | ||
447 | } | ||
448 | } else { | ||
449 | acl = NULL; | ||
450 | } | ||
451 | rc = jffs2_set_acl(inode, type, acl); | ||
452 | out: | ||
453 | posix_acl_release(acl); | ||
454 | return rc; | ||
455 | } | ||
456 | |||
457 | static int jffs2_acl_access_setxattr(struct inode *inode, const char *name, | ||
458 | const void *buffer, size_t size, int flags) | ||
459 | { | ||
460 | if (name[0] != '\0') | ||
461 | return -EINVAL; | ||
462 | return jffs2_acl_setxattr(inode, ACL_TYPE_ACCESS, buffer, size); | ||
463 | } | ||
464 | |||
465 | static int jffs2_acl_default_setxattr(struct inode *inode, const char *name, | ||
466 | const void *buffer, size_t size, int flags) | ||
467 | { | ||
468 | if (name[0] != '\0') | ||
469 | return -EINVAL; | ||
470 | return jffs2_acl_setxattr(inode, ACL_TYPE_DEFAULT, buffer, size); | ||
471 | } | ||
472 | |||
473 | struct xattr_handler jffs2_acl_access_xattr_handler = { | ||
474 | .prefix = POSIX_ACL_XATTR_ACCESS, | ||
475 | .list = jffs2_acl_access_listxattr, | ||
476 | .get = jffs2_acl_access_getxattr, | ||
477 | .set = jffs2_acl_access_setxattr, | ||
478 | }; | ||
479 | |||
480 | struct xattr_handler jffs2_acl_default_xattr_handler = { | ||
481 | .prefix = POSIX_ACL_XATTR_DEFAULT, | ||
482 | .list = jffs2_acl_default_listxattr, | ||
483 | .get = jffs2_acl_default_getxattr, | ||
484 | .set = jffs2_acl_default_setxattr, | ||
485 | }; | ||
diff --git a/fs/jffs2/acl.h b/fs/jffs2/acl.h new file mode 100644 index 000000000000..8893bd1a6ba7 --- /dev/null +++ b/fs/jffs2/acl.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | struct jffs2_acl_entry { | ||
12 | jint16_t e_tag; | ||
13 | jint16_t e_perm; | ||
14 | jint32_t e_id; | ||
15 | }; | ||
16 | |||
17 | struct jffs2_acl_entry_short { | ||
18 | jint16_t e_tag; | ||
19 | jint16_t e_perm; | ||
20 | }; | ||
21 | |||
22 | struct jffs2_acl_header { | ||
23 | jint32_t a_version; | ||
24 | }; | ||
25 | |||
26 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
27 | |||
28 | #define JFFS2_ACL_NOT_CACHED ((void *)-1) | ||
29 | |||
30 | extern int jffs2_permission(struct inode *, int, struct nameidata *); | ||
31 | extern int jffs2_acl_chmod(struct inode *); | ||
32 | extern int jffs2_init_acl(struct inode *, struct inode *); | ||
33 | extern void jffs2_clear_acl(struct inode *); | ||
34 | |||
35 | extern struct xattr_handler jffs2_acl_access_xattr_handler; | ||
36 | extern struct xattr_handler jffs2_acl_default_xattr_handler; | ||
37 | |||
38 | #else | ||
39 | |||
40 | #define jffs2_permission NULL | ||
41 | #define jffs2_acl_chmod(inode) (0) | ||
42 | #define jffs2_init_acl(inode,dir) (0) | ||
43 | #define jffs2_clear_acl(inode) | ||
44 | |||
45 | #endif /* CONFIG_JFFS2_FS_POSIX_ACL */ | ||
diff --git a/fs/jffs2/build.c b/fs/jffs2/build.c index 70f7a896c04a..02826967ab58 100644 --- a/fs/jffs2/build.c +++ b/fs/jffs2/build.c | |||
@@ -160,6 +160,7 @@ static int jffs2_build_filesystem(struct jffs2_sb_info *c) | |||
160 | ic->scan_dents = NULL; | 160 | ic->scan_dents = NULL; |
161 | cond_resched(); | 161 | cond_resched(); |
162 | } | 162 | } |
163 | jffs2_build_xattr_subsystem(c); | ||
163 | c->flags &= ~JFFS2_SB_FLAG_BUILDING; | 164 | c->flags &= ~JFFS2_SB_FLAG_BUILDING; |
164 | 165 | ||
165 | dbg_fsbuild("FS build complete\n"); | 166 | dbg_fsbuild("FS build complete\n"); |
@@ -178,6 +179,7 @@ exit: | |||
178 | jffs2_free_full_dirent(fd); | 179 | jffs2_free_full_dirent(fd); |
179 | } | 180 | } |
180 | } | 181 | } |
182 | jffs2_clear_xattr_subsystem(c); | ||
181 | } | 183 | } |
182 | 184 | ||
183 | return ret; | 185 | return ret; |
diff --git a/fs/jffs2/compr.c b/fs/jffs2/compr.c index e7944e665b9f..7001ba26c067 100644 --- a/fs/jffs2/compr.c +++ b/fs/jffs2/compr.c | |||
@@ -412,7 +412,7 @@ void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig) | |||
412 | kfree(comprbuf); | 412 | kfree(comprbuf); |
413 | } | 413 | } |
414 | 414 | ||
415 | int jffs2_compressors_init(void) | 415 | int __init jffs2_compressors_init(void) |
416 | { | 416 | { |
417 | /* Registering compressors */ | 417 | /* Registering compressors */ |
418 | #ifdef CONFIG_JFFS2_ZLIB | 418 | #ifdef CONFIG_JFFS2_ZLIB |
diff --git a/fs/jffs2/compr.h b/fs/jffs2/compr.h index a77e830d85c5..509b8b1c0811 100644 --- a/fs/jffs2/compr.h +++ b/fs/jffs2/compr.h | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
24 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
25 | #include <linux/jffs2.h> | 25 | #include <linux/jffs2.h> |
26 | #include <linux/jffs2_fs_i.h> | 26 | #include "jffs2_fs_i.h" |
27 | #include <linux/jffs2_fs_sb.h> | 27 | #include "jffs2_fs_sb.h" |
28 | #include "nodelist.h" | 28 | #include "nodelist.h" |
29 | 29 | ||
30 | #define JFFS2_RUBINMIPS_PRIORITY 10 | 30 | #define JFFS2_RUBINMIPS_PRIORITY 10 |
diff --git a/fs/jffs2/debug.c b/fs/jffs2/debug.c index 1fe17de713e8..72b4fc13a106 100644 --- a/fs/jffs2/debug.c +++ b/fs/jffs2/debug.c | |||
@@ -192,13 +192,13 @@ __jffs2_dbg_acct_paranoia_check_nolock(struct jffs2_sb_info *c, | |||
192 | else | 192 | else |
193 | my_dirty_size += totlen; | 193 | my_dirty_size += totlen; |
194 | 194 | ||
195 | if ((!ref2->next_phys) != (ref2 == jeb->last_node)) { | 195 | if ((!ref_next(ref2)) != (ref2 == jeb->last_node)) { |
196 | JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next_phys at %#08x (mem %p), last_node is at %#08x (mem %p).\n", | 196 | JFFS2_ERROR("node_ref for node at %#08x (mem %p) has next at %#08x (mem %p), last_node is at %#08x (mem %p).\n", |
197 | ref_offset(ref2), ref2, ref_offset(ref2->next_phys), ref2->next_phys, | 197 | ref_offset(ref2), ref2, ref_offset(ref_next(ref2)), ref_next(ref2), |
198 | ref_offset(jeb->last_node), jeb->last_node); | 198 | ref_offset(jeb->last_node), jeb->last_node); |
199 | goto error; | 199 | goto error; |
200 | } | 200 | } |
201 | ref2 = ref2->next_phys; | 201 | ref2 = ref_next(ref2); |
202 | } | 202 | } |
203 | 203 | ||
204 | if (my_used_size != jeb->used_size) { | 204 | if (my_used_size != jeb->used_size) { |
@@ -268,9 +268,9 @@ __jffs2_dbg_dump_node_refs_nolock(struct jffs2_sb_info *c, | |||
268 | } | 268 | } |
269 | 269 | ||
270 | printk(JFFS2_DBG); | 270 | printk(JFFS2_DBG); |
271 | for (ref = jeb->first_node; ; ref = ref->next_phys) { | 271 | for (ref = jeb->first_node; ; ref = ref_next(ref)) { |
272 | printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); | 272 | printk("%#08x(%#x)", ref_offset(ref), ref->__totlen); |
273 | if (ref->next_phys) | 273 | if (ref_next(ref)) |
274 | printk("->"); | 274 | printk("->"); |
275 | else | 275 | else |
276 | break; | 276 | break; |
diff --git a/fs/jffs2/debug.h b/fs/jffs2/debug.h index 162af6dfe292..5fa494a792b2 100644 --- a/fs/jffs2/debug.h +++ b/fs/jffs2/debug.h | |||
@@ -171,6 +171,12 @@ | |||
171 | #define dbg_memalloc(fmt, ...) | 171 | #define dbg_memalloc(fmt, ...) |
172 | #endif | 172 | #endif |
173 | 173 | ||
174 | /* Watch the XATTR subsystem */ | ||
175 | #ifdef JFFS2_DBG_XATTR_MESSAGES | ||
176 | #define dbg_xattr(fmt, ...) JFFS2_DEBUG(fmt, ##__VA_ARGS__) | ||
177 | #else | ||
178 | #define dbg_xattr(fmt, ...) | ||
179 | #endif | ||
174 | 180 | ||
175 | /* "Sanity" checks */ | 181 | /* "Sanity" checks */ |
176 | void | 182 | void |
diff --git a/fs/jffs2/dir.c b/fs/jffs2/dir.c index 8bc7a5018e40..edd8371fc6a5 100644 --- a/fs/jffs2/dir.c +++ b/fs/jffs2/dir.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/crc32.h> | 18 | #include <linux/crc32.h> |
19 | #include <linux/jffs2.h> | 19 | #include <linux/jffs2.h> |
20 | #include <linux/jffs2_fs_i.h> | 20 | #include "jffs2_fs_i.h" |
21 | #include <linux/jffs2_fs_sb.h> | 21 | #include "jffs2_fs_sb.h" |
22 | #include <linux/time.h> | 22 | #include <linux/time.h> |
23 | #include "nodelist.h" | 23 | #include "nodelist.h" |
24 | 24 | ||
@@ -57,7 +57,12 @@ struct inode_operations jffs2_dir_inode_operations = | |||
57 | .rmdir = jffs2_rmdir, | 57 | .rmdir = jffs2_rmdir, |
58 | .mknod = jffs2_mknod, | 58 | .mknod = jffs2_mknod, |
59 | .rename = jffs2_rename, | 59 | .rename = jffs2_rename, |
60 | .permission = jffs2_permission, | ||
60 | .setattr = jffs2_setattr, | 61 | .setattr = jffs2_setattr, |
62 | .setxattr = jffs2_setxattr, | ||
63 | .getxattr = jffs2_getxattr, | ||
64 | .listxattr = jffs2_listxattr, | ||
65 | .removexattr = jffs2_removexattr | ||
61 | }; | 66 | }; |
62 | 67 | ||
63 | /***********************************************************************/ | 68 | /***********************************************************************/ |
@@ -78,6 +83,9 @@ static struct dentry *jffs2_lookup(struct inode *dir_i, struct dentry *target, | |||
78 | 83 | ||
79 | D1(printk(KERN_DEBUG "jffs2_lookup()\n")); | 84 | D1(printk(KERN_DEBUG "jffs2_lookup()\n")); |
80 | 85 | ||
86 | if (target->d_name.len > JFFS2_MAX_NAME_LEN) | ||
87 | return ERR_PTR(-ENAMETOOLONG); | ||
88 | |||
81 | dir_f = JFFS2_INODE_INFO(dir_i); | 89 | dir_f = JFFS2_INODE_INFO(dir_i); |
82 | c = JFFS2_SB_INFO(dir_i->i_sb); | 90 | c = JFFS2_SB_INFO(dir_i->i_sb); |
83 | 91 | ||
@@ -206,12 +214,15 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
206 | ret = jffs2_do_create(c, dir_f, f, ri, | 214 | ret = jffs2_do_create(c, dir_f, f, ri, |
207 | dentry->d_name.name, dentry->d_name.len); | 215 | dentry->d_name.name, dentry->d_name.len); |
208 | 216 | ||
209 | if (ret) { | 217 | if (ret) |
210 | make_bad_inode(inode); | 218 | goto fail; |
211 | iput(inode); | 219 | |
212 | jffs2_free_raw_inode(ri); | 220 | ret = jffs2_init_security(inode, dir_i); |
213 | return ret; | 221 | if (ret) |
214 | } | 222 | goto fail; |
223 | ret = jffs2_init_acl(inode, dir_i); | ||
224 | if (ret) | ||
225 | goto fail; | ||
215 | 226 | ||
216 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); | 227 | dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime)); |
217 | 228 | ||
@@ -221,6 +232,12 @@ static int jffs2_create(struct inode *dir_i, struct dentry *dentry, int mode, | |||
221 | D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", | 232 | D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d). nrpages %ld\n", |
222 | inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); | 233 | inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink, inode->i_mapping->nrpages)); |
223 | return 0; | 234 | return 0; |
235 | |||
236 | fail: | ||
237 | make_bad_inode(inode); | ||
238 | iput(inode); | ||
239 | jffs2_free_raw_inode(ri); | ||
240 | return ret; | ||
224 | } | 241 | } |
225 | 242 | ||
226 | /***********************************************************************/ | 243 | /***********************************************************************/ |
@@ -291,7 +308,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
291 | struct jffs2_full_dnode *fn; | 308 | struct jffs2_full_dnode *fn; |
292 | struct jffs2_full_dirent *fd; | 309 | struct jffs2_full_dirent *fd; |
293 | int namelen; | 310 | int namelen; |
294 | uint32_t alloclen, phys_ofs; | 311 | uint32_t alloclen; |
295 | int ret, targetlen = strlen(target); | 312 | int ret, targetlen = strlen(target); |
296 | 313 | ||
297 | /* FIXME: If you care. We'd need to use frags for the target | 314 | /* FIXME: If you care. We'd need to use frags for the target |
@@ -310,8 +327,8 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
310 | * Just the node will do for now, though | 327 | * Just the node will do for now, though |
311 | */ | 328 | */ |
312 | namelen = dentry->d_name.len; | 329 | namelen = dentry->d_name.len; |
313 | ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &phys_ofs, &alloclen, | 330 | ret = jffs2_reserve_space(c, sizeof(*ri) + targetlen, &alloclen, |
314 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); | 331 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
315 | 332 | ||
316 | if (ret) { | 333 | if (ret) { |
317 | jffs2_free_raw_inode(ri); | 334 | jffs2_free_raw_inode(ri); |
@@ -339,7 +356,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
339 | ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); | 356 | ri->data_crc = cpu_to_je32(crc32(0, target, targetlen)); |
340 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 357 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
341 | 358 | ||
342 | fn = jffs2_write_dnode(c, f, ri, target, targetlen, phys_ofs, ALLOC_NORMAL); | 359 | fn = jffs2_write_dnode(c, f, ri, target, targetlen, ALLOC_NORMAL); |
343 | 360 | ||
344 | jffs2_free_raw_inode(ri); | 361 | jffs2_free_raw_inode(ri); |
345 | 362 | ||
@@ -371,8 +388,20 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
371 | up(&f->sem); | 388 | up(&f->sem); |
372 | 389 | ||
373 | jffs2_complete_reservation(c); | 390 | jffs2_complete_reservation(c); |
374 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 391 | |
375 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 392 | ret = jffs2_init_security(inode, dir_i); |
393 | if (ret) { | ||
394 | jffs2_clear_inode(inode); | ||
395 | return ret; | ||
396 | } | ||
397 | ret = jffs2_init_acl(inode, dir_i); | ||
398 | if (ret) { | ||
399 | jffs2_clear_inode(inode); | ||
400 | return ret; | ||
401 | } | ||
402 | |||
403 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | ||
404 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | ||
376 | if (ret) { | 405 | if (ret) { |
377 | /* Eep. */ | 406 | /* Eep. */ |
378 | jffs2_clear_inode(inode); | 407 | jffs2_clear_inode(inode); |
@@ -404,7 +433,7 @@ static int jffs2_symlink (struct inode *dir_i, struct dentry *dentry, const char | |||
404 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 433 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
405 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); | 434 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
406 | 435 | ||
407 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); | 436 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
408 | 437 | ||
409 | if (IS_ERR(fd)) { | 438 | if (IS_ERR(fd)) { |
410 | /* dirent failed to write. Delete the inode normally | 439 | /* dirent failed to write. Delete the inode normally |
@@ -442,7 +471,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
442 | struct jffs2_full_dnode *fn; | 471 | struct jffs2_full_dnode *fn; |
443 | struct jffs2_full_dirent *fd; | 472 | struct jffs2_full_dirent *fd; |
444 | int namelen; | 473 | int namelen; |
445 | uint32_t alloclen, phys_ofs; | 474 | uint32_t alloclen; |
446 | int ret; | 475 | int ret; |
447 | 476 | ||
448 | mode |= S_IFDIR; | 477 | mode |= S_IFDIR; |
@@ -457,8 +486,8 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
457 | * Just the node will do for now, though | 486 | * Just the node will do for now, though |
458 | */ | 487 | */ |
459 | namelen = dentry->d_name.len; | 488 | namelen = dentry->d_name.len; |
460 | ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, | 489 | ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, |
461 | JFFS2_SUMMARY_INODE_SIZE); | 490 | JFFS2_SUMMARY_INODE_SIZE); |
462 | 491 | ||
463 | if (ret) { | 492 | if (ret) { |
464 | jffs2_free_raw_inode(ri); | 493 | jffs2_free_raw_inode(ri); |
@@ -483,7 +512,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
483 | ri->data_crc = cpu_to_je32(0); | 512 | ri->data_crc = cpu_to_je32(0); |
484 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 513 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
485 | 514 | ||
486 | fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); | 515 | fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); |
487 | 516 | ||
488 | jffs2_free_raw_inode(ri); | 517 | jffs2_free_raw_inode(ri); |
489 | 518 | ||
@@ -501,8 +530,20 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
501 | up(&f->sem); | 530 | up(&f->sem); |
502 | 531 | ||
503 | jffs2_complete_reservation(c); | 532 | jffs2_complete_reservation(c); |
504 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 533 | |
505 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 534 | ret = jffs2_init_security(inode, dir_i); |
535 | if (ret) { | ||
536 | jffs2_clear_inode(inode); | ||
537 | return ret; | ||
538 | } | ||
539 | ret = jffs2_init_acl(inode, dir_i); | ||
540 | if (ret) { | ||
541 | jffs2_clear_inode(inode); | ||
542 | return ret; | ||
543 | } | ||
544 | |||
545 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | ||
546 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | ||
506 | if (ret) { | 547 | if (ret) { |
507 | /* Eep. */ | 548 | /* Eep. */ |
508 | jffs2_clear_inode(inode); | 549 | jffs2_clear_inode(inode); |
@@ -534,7 +575,7 @@ static int jffs2_mkdir (struct inode *dir_i, struct dentry *dentry, int mode) | |||
534 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 575 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
535 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); | 576 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
536 | 577 | ||
537 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); | 578 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
538 | 579 | ||
539 | if (IS_ERR(fd)) { | 580 | if (IS_ERR(fd)) { |
540 | /* dirent failed to write. Delete the inode normally | 581 | /* dirent failed to write. Delete the inode normally |
@@ -588,12 +629,12 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
588 | struct jffs2_full_dnode *fn; | 629 | struct jffs2_full_dnode *fn; |
589 | struct jffs2_full_dirent *fd; | 630 | struct jffs2_full_dirent *fd; |
590 | int namelen; | 631 | int namelen; |
591 | jint16_t dev; | 632 | union jffs2_device_node dev; |
592 | int devlen = 0; | 633 | int devlen = 0; |
593 | uint32_t alloclen, phys_ofs; | 634 | uint32_t alloclen; |
594 | int ret; | 635 | int ret; |
595 | 636 | ||
596 | if (!old_valid_dev(rdev)) | 637 | if (!new_valid_dev(rdev)) |
597 | return -EINVAL; | 638 | return -EINVAL; |
598 | 639 | ||
599 | ri = jffs2_alloc_raw_inode(); | 640 | ri = jffs2_alloc_raw_inode(); |
@@ -602,17 +643,15 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
602 | 643 | ||
603 | c = JFFS2_SB_INFO(dir_i->i_sb); | 644 | c = JFFS2_SB_INFO(dir_i->i_sb); |
604 | 645 | ||
605 | if (S_ISBLK(mode) || S_ISCHR(mode)) { | 646 | if (S_ISBLK(mode) || S_ISCHR(mode)) |
606 | dev = cpu_to_je16(old_encode_dev(rdev)); | 647 | devlen = jffs2_encode_dev(&dev, rdev); |
607 | devlen = sizeof(dev); | ||
608 | } | ||
609 | 648 | ||
610 | /* Try to reserve enough space for both node and dirent. | 649 | /* Try to reserve enough space for both node and dirent. |
611 | * Just the node will do for now, though | 650 | * Just the node will do for now, though |
612 | */ | 651 | */ |
613 | namelen = dentry->d_name.len; | 652 | namelen = dentry->d_name.len; |
614 | ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &phys_ofs, &alloclen, | 653 | ret = jffs2_reserve_space(c, sizeof(*ri) + devlen, &alloclen, |
615 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); | 654 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
616 | 655 | ||
617 | if (ret) { | 656 | if (ret) { |
618 | jffs2_free_raw_inode(ri); | 657 | jffs2_free_raw_inode(ri); |
@@ -639,7 +678,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
639 | ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); | 678 | ri->data_crc = cpu_to_je32(crc32(0, &dev, devlen)); |
640 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 679 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
641 | 680 | ||
642 | fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, phys_ofs, ALLOC_NORMAL); | 681 | fn = jffs2_write_dnode(c, f, ri, (char *)&dev, devlen, ALLOC_NORMAL); |
643 | 682 | ||
644 | jffs2_free_raw_inode(ri); | 683 | jffs2_free_raw_inode(ri); |
645 | 684 | ||
@@ -657,8 +696,20 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
657 | up(&f->sem); | 696 | up(&f->sem); |
658 | 697 | ||
659 | jffs2_complete_reservation(c); | 698 | jffs2_complete_reservation(c); |
660 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 699 | |
661 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 700 | ret = jffs2_init_security(inode, dir_i); |
701 | if (ret) { | ||
702 | jffs2_clear_inode(inode); | ||
703 | return ret; | ||
704 | } | ||
705 | ret = jffs2_init_acl(inode, dir_i); | ||
706 | if (ret) { | ||
707 | jffs2_clear_inode(inode); | ||
708 | return ret; | ||
709 | } | ||
710 | |||
711 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, | ||
712 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | ||
662 | if (ret) { | 713 | if (ret) { |
663 | /* Eep. */ | 714 | /* Eep. */ |
664 | jffs2_clear_inode(inode); | 715 | jffs2_clear_inode(inode); |
@@ -693,7 +744,7 @@ static int jffs2_mknod (struct inode *dir_i, struct dentry *dentry, int mode, de | |||
693 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 744 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
694 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); | 745 | rd->name_crc = cpu_to_je32(crc32(0, dentry->d_name.name, namelen)); |
695 | 746 | ||
696 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, phys_ofs, ALLOC_NORMAL); | 747 | fd = jffs2_write_dirent(c, dir_f, rd, dentry->d_name.name, namelen, ALLOC_NORMAL); |
697 | 748 | ||
698 | if (IS_ERR(fd)) { | 749 | if (IS_ERR(fd)) { |
699 | /* dirent failed to write. Delete the inode normally | 750 | /* dirent failed to write. Delete the inode normally |
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c index dad68fdffe9e..1862e8bc101d 100644 --- a/fs/jffs2/erase.c +++ b/fs/jffs2/erase.c | |||
@@ -30,7 +30,6 @@ static void jffs2_erase_callback(struct erase_info *); | |||
30 | #endif | 30 | #endif |
31 | static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); | 31 | static void jffs2_erase_failed(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t bad_offset); |
32 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | 32 | static void jffs2_erase_succeeded(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); |
33 | static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | ||
34 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | 33 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); |
35 | 34 | ||
36 | static void jffs2_erase_block(struct jffs2_sb_info *c, | 35 | static void jffs2_erase_block(struct jffs2_sb_info *c, |
@@ -136,7 +135,7 @@ void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count) | |||
136 | c->used_size -= jeb->used_size; | 135 | c->used_size -= jeb->used_size; |
137 | c->dirty_size -= jeb->dirty_size; | 136 | c->dirty_size -= jeb->dirty_size; |
138 | jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; | 137 | jeb->wasted_size = jeb->used_size = jeb->dirty_size = jeb->free_size = 0; |
139 | jffs2_free_all_node_refs(c, jeb); | 138 | jffs2_free_jeb_node_refs(c, jeb); |
140 | list_add(&jeb->list, &c->erasing_list); | 139 | list_add(&jeb->list, &c->erasing_list); |
141 | spin_unlock(&c->erase_completion_lock); | 140 | spin_unlock(&c->erase_completion_lock); |
142 | 141 | ||
@@ -231,6 +230,7 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, | |||
231 | at the end of the linked list. Stash it and continue | 230 | at the end of the linked list. Stash it and continue |
232 | from the beginning of the list */ | 231 | from the beginning of the list */ |
233 | ic = (struct jffs2_inode_cache *)(*prev); | 232 | ic = (struct jffs2_inode_cache *)(*prev); |
233 | BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE); | ||
234 | prev = &ic->nodes; | 234 | prev = &ic->nodes; |
235 | continue; | 235 | continue; |
236 | } | 236 | } |
@@ -283,22 +283,27 @@ static inline void jffs2_remove_node_refs_from_ino_list(struct jffs2_sb_info *c, | |||
283 | jffs2_del_ino_cache(c, ic); | 283 | jffs2_del_ino_cache(c, ic); |
284 | } | 284 | } |
285 | 285 | ||
286 | static void jffs2_free_all_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 286 | void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) |
287 | { | 287 | { |
288 | struct jffs2_raw_node_ref *ref; | 288 | struct jffs2_raw_node_ref *block, *ref; |
289 | D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); | 289 | D1(printk(KERN_DEBUG "Freeing all node refs for eraseblock offset 0x%08x\n", jeb->offset)); |
290 | while(jeb->first_node) { | ||
291 | ref = jeb->first_node; | ||
292 | jeb->first_node = ref->next_phys; | ||
293 | 290 | ||
294 | /* Remove from the inode-list */ | 291 | block = ref = jeb->first_node; |
295 | if (ref->next_in_ino) | 292 | |
293 | while (ref) { | ||
294 | if (ref->flash_offset == REF_LINK_NODE) { | ||
295 | ref = ref->next_in_ino; | ||
296 | jffs2_free_refblock(block); | ||
297 | block = ref; | ||
298 | continue; | ||
299 | } | ||
300 | if (ref->flash_offset != REF_EMPTY_NODE && ref->next_in_ino) | ||
296 | jffs2_remove_node_refs_from_ino_list(c, ref, jeb); | 301 | jffs2_remove_node_refs_from_ino_list(c, ref, jeb); |
297 | /* else it was a non-inode node or already removed, so don't bother */ | 302 | /* else it was a non-inode node or already removed, so don't bother */ |
298 | 303 | ||
299 | jffs2_free_raw_node_ref(ref); | 304 | ref++; |
300 | } | 305 | } |
301 | jeb->last_node = NULL; | 306 | jeb->first_node = jeb->last_node = NULL; |
302 | } | 307 | } |
303 | 308 | ||
304 | static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) | 309 | static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t *bad_offset) |
@@ -351,7 +356,6 @@ fail: | |||
351 | 356 | ||
352 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 357 | static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) |
353 | { | 358 | { |
354 | struct jffs2_raw_node_ref *marker_ref = NULL; | ||
355 | size_t retlen; | 359 | size_t retlen; |
356 | int ret; | 360 | int ret; |
357 | uint32_t bad_offset; | 361 | uint32_t bad_offset; |
@@ -373,12 +377,8 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
373 | goto filebad; | 377 | goto filebad; |
374 | } | 378 | } |
375 | 379 | ||
376 | jeb->first_node = jeb->last_node = NULL; | 380 | /* Everything else got zeroed before the erase */ |
377 | jeb->free_size = c->sector_size; | 381 | jeb->free_size = c->sector_size; |
378 | jeb->used_size = 0; | ||
379 | jeb->dirty_size = 0; | ||
380 | jeb->wasted_size = 0; | ||
381 | |||
382 | } else { | 382 | } else { |
383 | 383 | ||
384 | struct kvec vecs[1]; | 384 | struct kvec vecs[1]; |
@@ -388,11 +388,7 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
388 | .totlen = cpu_to_je32(c->cleanmarker_size) | 388 | .totlen = cpu_to_je32(c->cleanmarker_size) |
389 | }; | 389 | }; |
390 | 390 | ||
391 | marker_ref = jffs2_alloc_raw_node_ref(); | 391 | jffs2_prealloc_raw_node_refs(c, jeb, 1); |
392 | if (!marker_ref) { | ||
393 | printk(KERN_WARNING "Failed to allocate raw node ref for clean marker. Refiling\n"); | ||
394 | goto refile; | ||
395 | } | ||
396 | 392 | ||
397 | marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); | 393 | marker.hdr_crc = cpu_to_je32(crc32(0, &marker, sizeof(struct jffs2_unknown_node)-4)); |
398 | 394 | ||
@@ -408,21 +404,13 @@ static void jffs2_mark_erased_block(struct jffs2_sb_info *c, struct jffs2_eraseb | |||
408 | printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", | 404 | printk(KERN_WARNING "Short write to newly-erased block at 0x%08x: Wanted %zd, got %zd\n", |
409 | jeb->offset, sizeof(marker), retlen); | 405 | jeb->offset, sizeof(marker), retlen); |
410 | 406 | ||
411 | jffs2_free_raw_node_ref(marker_ref); | ||
412 | goto filebad; | 407 | goto filebad; |
413 | } | 408 | } |
414 | 409 | ||
415 | marker_ref->next_in_ino = NULL; | 410 | /* Everything else got zeroed before the erase */ |
416 | marker_ref->next_phys = NULL; | 411 | jeb->free_size = c->sector_size; |
417 | marker_ref->flash_offset = jeb->offset | REF_NORMAL; | 412 | /* FIXME Special case for cleanmarker in empty block */ |
418 | marker_ref->__totlen = c->cleanmarker_size; | 413 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, c->cleanmarker_size, NULL); |
419 | |||
420 | jeb->first_node = jeb->last_node = marker_ref; | ||
421 | |||
422 | jeb->free_size = c->sector_size - c->cleanmarker_size; | ||
423 | jeb->used_size = c->cleanmarker_size; | ||
424 | jeb->dirty_size = 0; | ||
425 | jeb->wasted_size = 0; | ||
426 | } | 414 | } |
427 | 415 | ||
428 | spin_lock(&c->erase_completion_lock); | 416 | spin_lock(&c->erase_completion_lock); |
diff --git a/fs/jffs2/file.c b/fs/jffs2/file.c index 9f4171213e58..bb8844f40e48 100644 --- a/fs/jffs2/file.c +++ b/fs/jffs2/file.c | |||
@@ -54,7 +54,12 @@ const struct file_operations jffs2_file_operations = | |||
54 | 54 | ||
55 | struct inode_operations jffs2_file_inode_operations = | 55 | struct inode_operations jffs2_file_inode_operations = |
56 | { | 56 | { |
57 | .setattr = jffs2_setattr | 57 | .permission = jffs2_permission, |
58 | .setattr = jffs2_setattr, | ||
59 | .setxattr = jffs2_setxattr, | ||
60 | .getxattr = jffs2_getxattr, | ||
61 | .listxattr = jffs2_listxattr, | ||
62 | .removexattr = jffs2_removexattr | ||
58 | }; | 63 | }; |
59 | 64 | ||
60 | struct address_space_operations jffs2_file_address_operations = | 65 | struct address_space_operations jffs2_file_address_operations = |
@@ -129,13 +134,13 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, | |||
129 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); | 134 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); |
130 | struct jffs2_raw_inode ri; | 135 | struct jffs2_raw_inode ri; |
131 | struct jffs2_full_dnode *fn; | 136 | struct jffs2_full_dnode *fn; |
132 | uint32_t phys_ofs, alloc_len; | 137 | uint32_t alloc_len; |
133 | 138 | ||
134 | D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", | 139 | D1(printk(KERN_DEBUG "Writing new hole frag 0x%x-0x%x between current EOF and new page\n", |
135 | (unsigned int)inode->i_size, pageofs)); | 140 | (unsigned int)inode->i_size, pageofs)); |
136 | 141 | ||
137 | ret = jffs2_reserve_space(c, sizeof(ri), &phys_ofs, &alloc_len, | 142 | ret = jffs2_reserve_space(c, sizeof(ri), &alloc_len, |
138 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); | 143 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
139 | if (ret) | 144 | if (ret) |
140 | return ret; | 145 | return ret; |
141 | 146 | ||
@@ -161,7 +166,7 @@ static int jffs2_prepare_write (struct file *filp, struct page *pg, | |||
161 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); | 166 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); |
162 | ri.data_crc = cpu_to_je32(0); | 167 | ri.data_crc = cpu_to_je32(0); |
163 | 168 | ||
164 | fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_NORMAL); | 169 | fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_NORMAL); |
165 | 170 | ||
166 | if (IS_ERR(fn)) { | 171 | if (IS_ERR(fn)) { |
167 | ret = PTR_ERR(fn); | 172 | ret = PTR_ERR(fn); |
@@ -215,12 +220,20 @@ static int jffs2_commit_write (struct file *filp, struct page *pg, | |||
215 | D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", | 220 | D1(printk(KERN_DEBUG "jffs2_commit_write(): ino #%lu, page at 0x%lx, range %d-%d, flags %lx\n", |
216 | inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); | 221 | inode->i_ino, pg->index << PAGE_CACHE_SHIFT, start, end, pg->flags)); |
217 | 222 | ||
218 | if (!start && end == PAGE_CACHE_SIZE) { | 223 | if (end == PAGE_CACHE_SIZE) { |
219 | /* We need to avoid deadlock with page_cache_read() in | 224 | if (!start) { |
220 | jffs2_garbage_collect_pass(). So we have to mark the | 225 | /* We need to avoid deadlock with page_cache_read() in |
221 | page up to date, to prevent page_cache_read() from | 226 | jffs2_garbage_collect_pass(). So we have to mark the |
222 | trying to re-lock it. */ | 227 | page up to date, to prevent page_cache_read() from |
223 | SetPageUptodate(pg); | 228 | trying to re-lock it. */ |
229 | SetPageUptodate(pg); | ||
230 | } else { | ||
231 | /* When writing out the end of a page, write out the | ||
232 | _whole_ page. This helps to reduce the number of | ||
233 | nodes in files which have many short writes, like | ||
234 | syslog files. */ | ||
235 | start = aligned_start = 0; | ||
236 | } | ||
224 | } | 237 | } |
225 | 238 | ||
226 | ri = jffs2_alloc_raw_inode(); | 239 | ri = jffs2_alloc_raw_inode(); |
diff --git a/fs/jffs2/fs.c b/fs/jffs2/fs.c index 09e5d10b8840..2900ec3ec3af 100644 --- a/fs/jffs2/fs.c +++ b/fs/jffs2/fs.c | |||
@@ -33,11 +33,11 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
33 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | 33 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); |
34 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); | 34 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); |
35 | struct jffs2_raw_inode *ri; | 35 | struct jffs2_raw_inode *ri; |
36 | unsigned short dev; | 36 | union jffs2_device_node dev; |
37 | unsigned char *mdata = NULL; | 37 | unsigned char *mdata = NULL; |
38 | int mdatalen = 0; | 38 | int mdatalen = 0; |
39 | unsigned int ivalid; | 39 | unsigned int ivalid; |
40 | uint32_t phys_ofs, alloclen; | 40 | uint32_t alloclen; |
41 | int ret; | 41 | int ret; |
42 | D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); | 42 | D1(printk(KERN_DEBUG "jffs2_setattr(): ino #%lu\n", inode->i_ino)); |
43 | ret = inode_change_ok(inode, iattr); | 43 | ret = inode_change_ok(inode, iattr); |
@@ -51,20 +51,24 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
51 | it out again with the appropriate data attached */ | 51 | it out again with the appropriate data attached */ |
52 | if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { | 52 | if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) { |
53 | /* For these, we don't actually need to read the old node */ | 53 | /* For these, we don't actually need to read the old node */ |
54 | dev = old_encode_dev(inode->i_rdev); | 54 | mdatalen = jffs2_encode_dev(&dev, inode->i_rdev); |
55 | mdata = (char *)&dev; | 55 | mdata = (char *)&dev; |
56 | mdatalen = sizeof(dev); | ||
57 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); | 56 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of kdev_t\n", mdatalen)); |
58 | } else if (S_ISLNK(inode->i_mode)) { | 57 | } else if (S_ISLNK(inode->i_mode)) { |
58 | down(&f->sem); | ||
59 | mdatalen = f->metadata->size; | 59 | mdatalen = f->metadata->size; |
60 | mdata = kmalloc(f->metadata->size, GFP_USER); | 60 | mdata = kmalloc(f->metadata->size, GFP_USER); |
61 | if (!mdata) | 61 | if (!mdata) { |
62 | up(&f->sem); | ||
62 | return -ENOMEM; | 63 | return -ENOMEM; |
64 | } | ||
63 | ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); | 65 | ret = jffs2_read_dnode(c, f, f->metadata, mdata, 0, mdatalen); |
64 | if (ret) { | 66 | if (ret) { |
67 | up(&f->sem); | ||
65 | kfree(mdata); | 68 | kfree(mdata); |
66 | return ret; | 69 | return ret; |
67 | } | 70 | } |
71 | up(&f->sem); | ||
68 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); | 72 | D1(printk(KERN_DEBUG "jffs2_setattr(): Writing %d bytes of symlink target\n", mdatalen)); |
69 | } | 73 | } |
70 | 74 | ||
@@ -75,8 +79,8 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
75 | return -ENOMEM; | 79 | return -ENOMEM; |
76 | } | 80 | } |
77 | 81 | ||
78 | ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &phys_ofs, &alloclen, | 82 | ret = jffs2_reserve_space(c, sizeof(*ri) + mdatalen, &alloclen, |
79 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); | 83 | ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
80 | if (ret) { | 84 | if (ret) { |
81 | jffs2_free_raw_inode(ri); | 85 | jffs2_free_raw_inode(ri); |
82 | if (S_ISLNK(inode->i_mode & S_IFMT)) | 86 | if (S_ISLNK(inode->i_mode & S_IFMT)) |
@@ -127,7 +131,7 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
127 | else | 131 | else |
128 | ri->data_crc = cpu_to_je32(0); | 132 | ri->data_crc = cpu_to_je32(0); |
129 | 133 | ||
130 | new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, phys_ofs, ALLOC_NORMAL); | 134 | new_metadata = jffs2_write_dnode(c, f, ri, mdata, mdatalen, ALLOC_NORMAL); |
131 | if (S_ISLNK(inode->i_mode)) | 135 | if (S_ISLNK(inode->i_mode)) |
132 | kfree(mdata); | 136 | kfree(mdata); |
133 | 137 | ||
@@ -180,12 +184,17 @@ static int jffs2_do_setattr (struct inode *inode, struct iattr *iattr) | |||
180 | 184 | ||
181 | int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) | 185 | int jffs2_setattr(struct dentry *dentry, struct iattr *iattr) |
182 | { | 186 | { |
183 | return jffs2_do_setattr(dentry->d_inode, iattr); | 187 | int rc; |
188 | |||
189 | rc = jffs2_do_setattr(dentry->d_inode, iattr); | ||
190 | if (!rc && (iattr->ia_valid & ATTR_MODE)) | ||
191 | rc = jffs2_acl_chmod(dentry->d_inode); | ||
192 | return rc; | ||
184 | } | 193 | } |
185 | 194 | ||
186 | int jffs2_statfs(struct super_block *sb, struct kstatfs *buf) | 195 | int jffs2_statfs(struct dentry *dentry, struct kstatfs *buf) |
187 | { | 196 | { |
188 | struct jffs2_sb_info *c = JFFS2_SB_INFO(sb); | 197 | struct jffs2_sb_info *c = JFFS2_SB_INFO(dentry->d_sb); |
189 | unsigned long avail; | 198 | unsigned long avail; |
190 | 199 | ||
191 | buf->f_type = JFFS2_SUPER_MAGIC; | 200 | buf->f_type = JFFS2_SUPER_MAGIC; |
@@ -219,6 +228,7 @@ void jffs2_clear_inode (struct inode *inode) | |||
219 | 228 | ||
220 | D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); | 229 | D1(printk(KERN_DEBUG "jffs2_clear_inode(): ino #%lu mode %o\n", inode->i_ino, inode->i_mode)); |
221 | 230 | ||
231 | jffs2_xattr_delete_inode(c, f->inocache); | ||
222 | jffs2_do_clear_inode(c, f); | 232 | jffs2_do_clear_inode(c, f); |
223 | } | 233 | } |
224 | 234 | ||
@@ -227,6 +237,8 @@ void jffs2_read_inode (struct inode *inode) | |||
227 | struct jffs2_inode_info *f; | 237 | struct jffs2_inode_info *f; |
228 | struct jffs2_sb_info *c; | 238 | struct jffs2_sb_info *c; |
229 | struct jffs2_raw_inode latest_node; | 239 | struct jffs2_raw_inode latest_node; |
240 | union jffs2_device_node jdev; | ||
241 | dev_t rdev = 0; | ||
230 | int ret; | 242 | int ret; |
231 | 243 | ||
232 | D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); | 244 | D1(printk(KERN_DEBUG "jffs2_read_inode(): inode->i_ino == %lu\n", inode->i_ino)); |
@@ -258,7 +270,6 @@ void jffs2_read_inode (struct inode *inode) | |||
258 | inode->i_blocks = (inode->i_size + 511) >> 9; | 270 | inode->i_blocks = (inode->i_size + 511) >> 9; |
259 | 271 | ||
260 | switch (inode->i_mode & S_IFMT) { | 272 | switch (inode->i_mode & S_IFMT) { |
261 | jint16_t rdev; | ||
262 | 273 | ||
263 | case S_IFLNK: | 274 | case S_IFLNK: |
264 | inode->i_op = &jffs2_symlink_inode_operations; | 275 | inode->i_op = &jffs2_symlink_inode_operations; |
@@ -292,8 +303,16 @@ void jffs2_read_inode (struct inode *inode) | |||
292 | case S_IFBLK: | 303 | case S_IFBLK: |
293 | case S_IFCHR: | 304 | case S_IFCHR: |
294 | /* Read the device numbers from the media */ | 305 | /* Read the device numbers from the media */ |
306 | if (f->metadata->size != sizeof(jdev.old) && | ||
307 | f->metadata->size != sizeof(jdev.new)) { | ||
308 | printk(KERN_NOTICE "Device node has strange size %d\n", f->metadata->size); | ||
309 | up(&f->sem); | ||
310 | jffs2_do_clear_inode(c, f); | ||
311 | make_bad_inode(inode); | ||
312 | return; | ||
313 | } | ||
295 | D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); | 314 | D1(printk(KERN_DEBUG "Reading device numbers from flash\n")); |
296 | if (jffs2_read_dnode(c, f, f->metadata, (char *)&rdev, 0, sizeof(rdev)) < 0) { | 315 | if (jffs2_read_dnode(c, f, f->metadata, (char *)&jdev, 0, f->metadata->size) < 0) { |
297 | /* Eep */ | 316 | /* Eep */ |
298 | printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); | 317 | printk(KERN_NOTICE "Read device numbers for inode %lu failed\n", (unsigned long)inode->i_ino); |
299 | up(&f->sem); | 318 | up(&f->sem); |
@@ -301,12 +320,15 @@ void jffs2_read_inode (struct inode *inode) | |||
301 | make_bad_inode(inode); | 320 | make_bad_inode(inode); |
302 | return; | 321 | return; |
303 | } | 322 | } |
323 | if (f->metadata->size == sizeof(jdev.old)) | ||
324 | rdev = old_decode_dev(je16_to_cpu(jdev.old)); | ||
325 | else | ||
326 | rdev = new_decode_dev(je32_to_cpu(jdev.new)); | ||
304 | 327 | ||
305 | case S_IFSOCK: | 328 | case S_IFSOCK: |
306 | case S_IFIFO: | 329 | case S_IFIFO: |
307 | inode->i_op = &jffs2_file_inode_operations; | 330 | inode->i_op = &jffs2_file_inode_operations; |
308 | init_special_inode(inode, inode->i_mode, | 331 | init_special_inode(inode, inode->i_mode, rdev); |
309 | old_decode_dev((je16_to_cpu(rdev)))); | ||
310 | break; | 332 | break; |
311 | 333 | ||
312 | default: | 334 | default: |
@@ -492,6 +514,8 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
492 | } | 514 | } |
493 | memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); | 515 | memset(c->inocache_list, 0, INOCACHE_HASHSIZE * sizeof(struct jffs2_inode_cache *)); |
494 | 516 | ||
517 | jffs2_init_xattr_subsystem(c); | ||
518 | |||
495 | if ((ret = jffs2_do_mount_fs(c))) | 519 | if ((ret = jffs2_do_mount_fs(c))) |
496 | goto out_inohash; | 520 | goto out_inohash; |
497 | 521 | ||
@@ -526,6 +550,7 @@ int jffs2_do_fill_super(struct super_block *sb, void *data, int silent) | |||
526 | else | 550 | else |
527 | kfree(c->blocks); | 551 | kfree(c->blocks); |
528 | out_inohash: | 552 | out_inohash: |
553 | jffs2_clear_xattr_subsystem(c); | ||
529 | kfree(c->inocache_list); | 554 | kfree(c->inocache_list); |
530 | out_wbuf: | 555 | out_wbuf: |
531 | jffs2_flash_cleanup(c); | 556 | jffs2_flash_cleanup(c); |
@@ -639,13 +664,6 @@ static int jffs2_flash_setup(struct jffs2_sb_info *c) { | |||
639 | return ret; | 664 | return ret; |
640 | } | 665 | } |
641 | 666 | ||
642 | /* add setups for other bizarre flashes here... */ | ||
643 | if (jffs2_nor_ecc(c)) { | ||
644 | ret = jffs2_nor_ecc_flash_setup(c); | ||
645 | if (ret) | ||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | /* and Dataflash */ | 667 | /* and Dataflash */ |
650 | if (jffs2_dataflash(c)) { | 668 | if (jffs2_dataflash(c)) { |
651 | ret = jffs2_dataflash_setup(c); | 669 | ret = jffs2_dataflash_setup(c); |
@@ -669,11 +687,6 @@ void jffs2_flash_cleanup(struct jffs2_sb_info *c) { | |||
669 | jffs2_nand_flash_cleanup(c); | 687 | jffs2_nand_flash_cleanup(c); |
670 | } | 688 | } |
671 | 689 | ||
672 | /* add cleanups for other bizarre flashes here... */ | ||
673 | if (jffs2_nor_ecc(c)) { | ||
674 | jffs2_nor_ecc_flash_cleanup(c); | ||
675 | } | ||
676 | |||
677 | /* and DataFlash */ | 690 | /* and DataFlash */ |
678 | if (jffs2_dataflash(c)) { | 691 | if (jffs2_dataflash(c)) { |
679 | jffs2_dataflash_cleanup(c); | 692 | jffs2_dataflash_cleanup(c); |
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c index f9ffece453a3..477c526d638b 100644 --- a/fs/jffs2/gc.c +++ b/fs/jffs2/gc.c | |||
@@ -125,6 +125,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
125 | struct jffs2_eraseblock *jeb; | 125 | struct jffs2_eraseblock *jeb; |
126 | struct jffs2_raw_node_ref *raw; | 126 | struct jffs2_raw_node_ref *raw; |
127 | int ret = 0, inum, nlink; | 127 | int ret = 0, inum, nlink; |
128 | int xattr = 0; | ||
128 | 129 | ||
129 | if (down_interruptible(&c->alloc_sem)) | 130 | if (down_interruptible(&c->alloc_sem)) |
130 | return -EINTR; | 131 | return -EINTR; |
@@ -138,7 +139,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
138 | the node CRCs etc. Do it now. */ | 139 | the node CRCs etc. Do it now. */ |
139 | 140 | ||
140 | /* checked_ino is protected by the alloc_sem */ | 141 | /* checked_ino is protected by the alloc_sem */ |
141 | if (c->checked_ino > c->highest_ino) { | 142 | if (c->checked_ino > c->highest_ino && xattr) { |
142 | printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", | 143 | printk(KERN_CRIT "Checked all inodes but still 0x%x bytes of unchecked space?\n", |
143 | c->unchecked_size); | 144 | c->unchecked_size); |
144 | jffs2_dbg_dump_block_lists_nolock(c); | 145 | jffs2_dbg_dump_block_lists_nolock(c); |
@@ -148,6 +149,9 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
148 | 149 | ||
149 | spin_unlock(&c->erase_completion_lock); | 150 | spin_unlock(&c->erase_completion_lock); |
150 | 151 | ||
152 | if (!xattr) | ||
153 | xattr = jffs2_verify_xattr(c); | ||
154 | |||
151 | spin_lock(&c->inocache_lock); | 155 | spin_lock(&c->inocache_lock); |
152 | 156 | ||
153 | ic = jffs2_get_ino_cache(c, c->checked_ino++); | 157 | ic = jffs2_get_ino_cache(c, c->checked_ino++); |
@@ -181,6 +185,10 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
181 | and trigger the BUG() above while we haven't yet | 185 | and trigger the BUG() above while we haven't yet |
182 | finished checking all its nodes */ | 186 | finished checking all its nodes */ |
183 | D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); | 187 | D1(printk(KERN_DEBUG "Waiting for ino #%u to finish reading\n", ic->ino)); |
188 | /* We need to come back again for the _same_ inode. We've | ||
189 | made no progress in this case, but that should be OK */ | ||
190 | c->checked_ino--; | ||
191 | |||
184 | up(&c->alloc_sem); | 192 | up(&c->alloc_sem); |
185 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); | 193 | sleep_on_spinunlock(&c->inocache_wq, &c->inocache_lock); |
186 | return 0; | 194 | return 0; |
@@ -231,7 +239,7 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
231 | 239 | ||
232 | while(ref_obsolete(raw)) { | 240 | while(ref_obsolete(raw)) { |
233 | D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); | 241 | D1(printk(KERN_DEBUG "Node at 0x%08x is obsolete... skipping\n", ref_offset(raw))); |
234 | raw = raw->next_phys; | 242 | raw = ref_next(raw); |
235 | if (unlikely(!raw)) { | 243 | if (unlikely(!raw)) { |
236 | printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); | 244 | printk(KERN_WARNING "eep. End of raw list while still supposedly nodes to GC\n"); |
237 | printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", | 245 | printk(KERN_WARNING "erase block at 0x%08x. free_size 0x%08x, dirty_size 0x%08x, used_size 0x%08x\n", |
@@ -248,16 +256,37 @@ int jffs2_garbage_collect_pass(struct jffs2_sb_info *c) | |||
248 | 256 | ||
249 | if (!raw->next_in_ino) { | 257 | if (!raw->next_in_ino) { |
250 | /* Inode-less node. Clean marker, snapshot or something like that */ | 258 | /* Inode-less node. Clean marker, snapshot or something like that */ |
251 | /* FIXME: If it's something that needs to be copied, including something | ||
252 | we don't grok that has JFFS2_NODETYPE_RWCOMPAT_COPY, we should do so */ | ||
253 | spin_unlock(&c->erase_completion_lock); | 259 | spin_unlock(&c->erase_completion_lock); |
254 | jffs2_mark_node_obsolete(c, raw); | 260 | if (ref_flags(raw) == REF_PRISTINE) { |
261 | /* It's an unknown node with JFFS2_FEATURE_RWCOMPAT_COPY */ | ||
262 | jffs2_garbage_collect_pristine(c, NULL, raw); | ||
263 | } else { | ||
264 | /* Just mark it obsolete */ | ||
265 | jffs2_mark_node_obsolete(c, raw); | ||
266 | } | ||
255 | up(&c->alloc_sem); | 267 | up(&c->alloc_sem); |
256 | goto eraseit_lock; | 268 | goto eraseit_lock; |
257 | } | 269 | } |
258 | 270 | ||
259 | ic = jffs2_raw_ref_to_ic(raw); | 271 | ic = jffs2_raw_ref_to_ic(raw); |
260 | 272 | ||
273 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
274 | /* When 'ic' refers xattr_datum/xattr_ref, this node is GCed as xattr. | ||
275 | * We can decide whether this node is inode or xattr by ic->class. */ | ||
276 | if (ic->class == RAWNODE_CLASS_XATTR_DATUM | ||
277 | || ic->class == RAWNODE_CLASS_XATTR_REF) { | ||
278 | BUG_ON(raw->next_in_ino != (void *)ic); | ||
279 | spin_unlock(&c->erase_completion_lock); | ||
280 | |||
281 | if (ic->class == RAWNODE_CLASS_XATTR_DATUM) { | ||
282 | ret = jffs2_garbage_collect_xattr_datum(c, (struct jffs2_xattr_datum *)ic); | ||
283 | } else { | ||
284 | ret = jffs2_garbage_collect_xattr_ref(c, (struct jffs2_xattr_ref *)ic); | ||
285 | } | ||
286 | goto release_sem; | ||
287 | } | ||
288 | #endif | ||
289 | |||
261 | /* We need to hold the inocache. Either the erase_completion_lock or | 290 | /* We need to hold the inocache. Either the erase_completion_lock or |
262 | the inocache_lock are sufficient; we trade down since the inocache_lock | 291 | the inocache_lock are sufficient; we trade down since the inocache_lock |
263 | causes less contention. */ | 292 | causes less contention. */ |
@@ -499,7 +528,6 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
499 | struct jffs2_raw_node_ref *raw) | 528 | struct jffs2_raw_node_ref *raw) |
500 | { | 529 | { |
501 | union jffs2_node_union *node; | 530 | union jffs2_node_union *node; |
502 | struct jffs2_raw_node_ref *nraw; | ||
503 | size_t retlen; | 531 | size_t retlen; |
504 | int ret; | 532 | int ret; |
505 | uint32_t phys_ofs, alloclen; | 533 | uint32_t phys_ofs, alloclen; |
@@ -508,15 +536,16 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
508 | 536 | ||
509 | D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); | 537 | D1(printk(KERN_DEBUG "Going to GC REF_PRISTINE node at 0x%08x\n", ref_offset(raw))); |
510 | 538 | ||
511 | rawlen = ref_totlen(c, c->gcblock, raw); | 539 | alloclen = rawlen = ref_totlen(c, c->gcblock, raw); |
512 | 540 | ||
513 | /* Ask for a small amount of space (or the totlen if smaller) because we | 541 | /* Ask for a small amount of space (or the totlen if smaller) because we |
514 | don't want to force wastage of the end of a block if splitting would | 542 | don't want to force wastage of the end of a block if splitting would |
515 | work. */ | 543 | work. */ |
516 | ret = jffs2_reserve_space_gc(c, min_t(uint32_t, sizeof(struct jffs2_raw_inode) + | 544 | if (ic && alloclen > sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN) |
517 | JFFS2_MIN_DATA_LEN, rawlen), &phys_ofs, &alloclen, rawlen); | 545 | alloclen = sizeof(struct jffs2_raw_inode) + JFFS2_MIN_DATA_LEN; |
518 | /* this is not the exact summary size of it, | 546 | |
519 | it is only an upper estimation */ | 547 | ret = jffs2_reserve_space_gc(c, alloclen, &alloclen, rawlen); |
548 | /* 'rawlen' is not the exact summary size; it is only an upper estimation */ | ||
520 | 549 | ||
521 | if (ret) | 550 | if (ret) |
522 | return ret; | 551 | return ret; |
@@ -580,22 +609,17 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
580 | } | 609 | } |
581 | break; | 610 | break; |
582 | default: | 611 | default: |
583 | printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", | 612 | /* If it's inode-less, we don't _know_ what it is. Just copy it intact */ |
584 | ref_offset(raw), je16_to_cpu(node->u.nodetype)); | 613 | if (ic) { |
585 | goto bail; | 614 | printk(KERN_WARNING "Unknown node type for REF_PRISTINE node at 0x%08x: 0x%04x\n", |
586 | } | 615 | ref_offset(raw), je16_to_cpu(node->u.nodetype)); |
587 | 616 | goto bail; | |
588 | nraw = jffs2_alloc_raw_node_ref(); | 617 | } |
589 | if (!nraw) { | ||
590 | ret = -ENOMEM; | ||
591 | goto out_node; | ||
592 | } | 618 | } |
593 | 619 | ||
594 | /* OK, all the CRCs are good; this node can just be copied as-is. */ | 620 | /* OK, all the CRCs are good; this node can just be copied as-is. */ |
595 | retry: | 621 | retry: |
596 | nraw->flash_offset = phys_ofs; | 622 | phys_ofs = write_ofs(c); |
597 | nraw->__totlen = rawlen; | ||
598 | nraw->next_phys = NULL; | ||
599 | 623 | ||
600 | ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); | 624 | ret = jffs2_flash_write(c, phys_ofs, rawlen, &retlen, (char *)node); |
601 | 625 | ||
@@ -603,17 +627,11 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
603 | printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", | 627 | printk(KERN_NOTICE "Write of %d bytes at 0x%08x failed. returned %d, retlen %zd\n", |
604 | rawlen, phys_ofs, ret, retlen); | 628 | rawlen, phys_ofs, ret, retlen); |
605 | if (retlen) { | 629 | if (retlen) { |
606 | /* Doesn't belong to any inode */ | 630 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, rawlen, NULL); |
607 | nraw->next_in_ino = NULL; | ||
608 | |||
609 | nraw->flash_offset |= REF_OBSOLETE; | ||
610 | jffs2_add_physical_node_ref(c, nraw); | ||
611 | jffs2_mark_node_obsolete(c, nraw); | ||
612 | } else { | 631 | } else { |
613 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", nraw->flash_offset); | 632 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", phys_ofs); |
614 | jffs2_free_raw_node_ref(nraw); | ||
615 | } | 633 | } |
616 | if (!retried && (nraw = jffs2_alloc_raw_node_ref())) { | 634 | if (!retried) { |
617 | /* Try to reallocate space and retry */ | 635 | /* Try to reallocate space and retry */ |
618 | uint32_t dummy; | 636 | uint32_t dummy; |
619 | struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; | 637 | struct jffs2_eraseblock *jeb = &c->blocks[phys_ofs / c->sector_size]; |
@@ -625,7 +643,7 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
625 | jffs2_dbg_acct_sanity_check(c,jeb); | 643 | jffs2_dbg_acct_sanity_check(c,jeb); |
626 | jffs2_dbg_acct_paranoia_check(c, jeb); | 644 | jffs2_dbg_acct_paranoia_check(c, jeb); |
627 | 645 | ||
628 | ret = jffs2_reserve_space_gc(c, rawlen, &phys_ofs, &dummy, rawlen); | 646 | ret = jffs2_reserve_space_gc(c, rawlen, &dummy, rawlen); |
629 | /* this is not the exact summary size of it, | 647 | /* this is not the exact summary size of it, |
630 | it is only an upper estimation */ | 648 | it is only an upper estimation */ |
631 | 649 | ||
@@ -638,25 +656,13 @@ static int jffs2_garbage_collect_pristine(struct jffs2_sb_info *c, | |||
638 | goto retry; | 656 | goto retry; |
639 | } | 657 | } |
640 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 658 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
641 | jffs2_free_raw_node_ref(nraw); | ||
642 | } | 659 | } |
643 | 660 | ||
644 | jffs2_free_raw_node_ref(nraw); | ||
645 | if (!ret) | 661 | if (!ret) |
646 | ret = -EIO; | 662 | ret = -EIO; |
647 | goto out_node; | 663 | goto out_node; |
648 | } | 664 | } |
649 | nraw->flash_offset |= REF_PRISTINE; | 665 | jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, rawlen, ic); |
650 | jffs2_add_physical_node_ref(c, nraw); | ||
651 | |||
652 | /* Link into per-inode list. This is safe because of the ic | ||
653 | state being INO_STATE_GC. Note that if we're doing this | ||
654 | for an inode which is in-core, the 'nraw' pointer is then | ||
655 | going to be fetched from ic->nodes by our caller. */ | ||
656 | spin_lock(&c->erase_completion_lock); | ||
657 | nraw->next_in_ino = ic->nodes; | ||
658 | ic->nodes = nraw; | ||
659 | spin_unlock(&c->erase_completion_lock); | ||
660 | 666 | ||
661 | jffs2_mark_node_obsolete(c, raw); | 667 | jffs2_mark_node_obsolete(c, raw); |
662 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); | 668 | D1(printk(KERN_DEBUG "WHEEE! GC REF_PRISTINE node at 0x%08x succeeded\n", ref_offset(raw))); |
@@ -675,19 +681,16 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ | |||
675 | struct jffs2_full_dnode *new_fn; | 681 | struct jffs2_full_dnode *new_fn; |
676 | struct jffs2_raw_inode ri; | 682 | struct jffs2_raw_inode ri; |
677 | struct jffs2_node_frag *last_frag; | 683 | struct jffs2_node_frag *last_frag; |
678 | jint16_t dev; | 684 | union jffs2_device_node dev; |
679 | char *mdata = NULL, mdatalen = 0; | 685 | char *mdata = NULL, mdatalen = 0; |
680 | uint32_t alloclen, phys_ofs, ilen; | 686 | uint32_t alloclen, ilen; |
681 | int ret; | 687 | int ret; |
682 | 688 | ||
683 | if (S_ISBLK(JFFS2_F_I_MODE(f)) || | 689 | if (S_ISBLK(JFFS2_F_I_MODE(f)) || |
684 | S_ISCHR(JFFS2_F_I_MODE(f)) ) { | 690 | S_ISCHR(JFFS2_F_I_MODE(f)) ) { |
685 | /* For these, we don't actually need to read the old node */ | 691 | /* For these, we don't actually need to read the old node */ |
686 | /* FIXME: for minor or major > 255. */ | 692 | mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f)); |
687 | dev = cpu_to_je16(((JFFS2_F_I_RDEV_MAJ(f) << 8) | | ||
688 | JFFS2_F_I_RDEV_MIN(f))); | ||
689 | mdata = (char *)&dev; | 693 | mdata = (char *)&dev; |
690 | mdatalen = sizeof(dev); | ||
691 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); | 694 | D1(printk(KERN_DEBUG "jffs2_garbage_collect_metadata(): Writing %d bytes of kdev_t\n", mdatalen)); |
692 | } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { | 695 | } else if (S_ISLNK(JFFS2_F_I_MODE(f))) { |
693 | mdatalen = fn->size; | 696 | mdatalen = fn->size; |
@@ -706,7 +709,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ | |||
706 | 709 | ||
707 | } | 710 | } |
708 | 711 | ||
709 | ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &phys_ofs, &alloclen, | 712 | ret = jffs2_reserve_space_gc(c, sizeof(ri) + mdatalen, &alloclen, |
710 | JFFS2_SUMMARY_INODE_SIZE); | 713 | JFFS2_SUMMARY_INODE_SIZE); |
711 | if (ret) { | 714 | if (ret) { |
712 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", | 715 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_metadata failed: %d\n", |
@@ -744,7 +747,7 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_ | |||
744 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); | 747 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); |
745 | ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); | 748 | ri.data_crc = cpu_to_je32(crc32(0, mdata, mdatalen)); |
746 | 749 | ||
747 | new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, phys_ofs, ALLOC_GC); | 750 | new_fn = jffs2_write_dnode(c, f, &ri, mdata, mdatalen, ALLOC_GC); |
748 | 751 | ||
749 | if (IS_ERR(new_fn)) { | 752 | if (IS_ERR(new_fn)) { |
750 | printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); | 753 | printk(KERN_WARNING "Error writing new dnode: %ld\n", PTR_ERR(new_fn)); |
@@ -765,7 +768,7 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er | |||
765 | { | 768 | { |
766 | struct jffs2_full_dirent *new_fd; | 769 | struct jffs2_full_dirent *new_fd; |
767 | struct jffs2_raw_dirent rd; | 770 | struct jffs2_raw_dirent rd; |
768 | uint32_t alloclen, phys_ofs; | 771 | uint32_t alloclen; |
769 | int ret; | 772 | int ret; |
770 | 773 | ||
771 | rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 774 | rd.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
@@ -787,14 +790,14 @@ static int jffs2_garbage_collect_dirent(struct jffs2_sb_info *c, struct jffs2_er | |||
787 | rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); | 790 | rd.node_crc = cpu_to_je32(crc32(0, &rd, sizeof(rd)-8)); |
788 | rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); | 791 | rd.name_crc = cpu_to_je32(crc32(0, fd->name, rd.nsize)); |
789 | 792 | ||
790 | ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &phys_ofs, &alloclen, | 793 | ret = jffs2_reserve_space_gc(c, sizeof(rd)+rd.nsize, &alloclen, |
791 | JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); | 794 | JFFS2_SUMMARY_DIRENT_SIZE(rd.nsize)); |
792 | if (ret) { | 795 | if (ret) { |
793 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", | 796 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_dirent failed: %d\n", |
794 | sizeof(rd)+rd.nsize, ret); | 797 | sizeof(rd)+rd.nsize, ret); |
795 | return ret; | 798 | return ret; |
796 | } | 799 | } |
797 | new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, phys_ofs, ALLOC_GC); | 800 | new_fd = jffs2_write_dirent(c, f, &rd, fd->name, rd.nsize, ALLOC_GC); |
798 | 801 | ||
799 | if (IS_ERR(new_fd)) { | 802 | if (IS_ERR(new_fd)) { |
800 | printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); | 803 | printk(KERN_WARNING "jffs2_write_dirent in garbage_collect_dirent failed: %ld\n", PTR_ERR(new_fd)); |
@@ -922,7 +925,7 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras | |||
922 | struct jffs2_raw_inode ri; | 925 | struct jffs2_raw_inode ri; |
923 | struct jffs2_node_frag *frag; | 926 | struct jffs2_node_frag *frag; |
924 | struct jffs2_full_dnode *new_fn; | 927 | struct jffs2_full_dnode *new_fn; |
925 | uint32_t alloclen, phys_ofs, ilen; | 928 | uint32_t alloclen, ilen; |
926 | int ret; | 929 | int ret; |
927 | 930 | ||
928 | D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", | 931 | D1(printk(KERN_DEBUG "Writing replacement hole node for ino #%u from offset 0x%x to 0x%x\n", |
@@ -1001,14 +1004,14 @@ static int jffs2_garbage_collect_hole(struct jffs2_sb_info *c, struct jffs2_eras | |||
1001 | ri.data_crc = cpu_to_je32(0); | 1004 | ri.data_crc = cpu_to_je32(0); |
1002 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); | 1005 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); |
1003 | 1006 | ||
1004 | ret = jffs2_reserve_space_gc(c, sizeof(ri), &phys_ofs, &alloclen, | 1007 | ret = jffs2_reserve_space_gc(c, sizeof(ri), &alloclen, |
1005 | JFFS2_SUMMARY_INODE_SIZE); | 1008 | JFFS2_SUMMARY_INODE_SIZE); |
1006 | if (ret) { | 1009 | if (ret) { |
1007 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", | 1010 | printk(KERN_WARNING "jffs2_reserve_space_gc of %zd bytes for garbage_collect_hole failed: %d\n", |
1008 | sizeof(ri), ret); | 1011 | sizeof(ri), ret); |
1009 | return ret; | 1012 | return ret; |
1010 | } | 1013 | } |
1011 | new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, phys_ofs, ALLOC_GC); | 1014 | new_fn = jffs2_write_dnode(c, f, &ri, NULL, 0, ALLOC_GC); |
1012 | 1015 | ||
1013 | if (IS_ERR(new_fn)) { | 1016 | if (IS_ERR(new_fn)) { |
1014 | printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); | 1017 | printk(KERN_WARNING "Error writing new hole node: %ld\n", PTR_ERR(new_fn)); |
@@ -1070,7 +1073,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era | |||
1070 | { | 1073 | { |
1071 | struct jffs2_full_dnode *new_fn; | 1074 | struct jffs2_full_dnode *new_fn; |
1072 | struct jffs2_raw_inode ri; | 1075 | struct jffs2_raw_inode ri; |
1073 | uint32_t alloclen, phys_ofs, offset, orig_end, orig_start; | 1076 | uint32_t alloclen, offset, orig_end, orig_start; |
1074 | int ret = 0; | 1077 | int ret = 0; |
1075 | unsigned char *comprbuf = NULL, *writebuf; | 1078 | unsigned char *comprbuf = NULL, *writebuf; |
1076 | unsigned long pg; | 1079 | unsigned long pg; |
@@ -1227,7 +1230,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era | |||
1227 | uint32_t cdatalen; | 1230 | uint32_t cdatalen; |
1228 | uint16_t comprtype = JFFS2_COMPR_NONE; | 1231 | uint16_t comprtype = JFFS2_COMPR_NONE; |
1229 | 1232 | ||
1230 | ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, | 1233 | ret = jffs2_reserve_space_gc(c, sizeof(ri) + JFFS2_MIN_DATA_LEN, |
1231 | &alloclen, JFFS2_SUMMARY_INODE_SIZE); | 1234 | &alloclen, JFFS2_SUMMARY_INODE_SIZE); |
1232 | 1235 | ||
1233 | if (ret) { | 1236 | if (ret) { |
@@ -1264,7 +1267,7 @@ static int jffs2_garbage_collect_dnode(struct jffs2_sb_info *c, struct jffs2_era | |||
1264 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); | 1267 | ri.node_crc = cpu_to_je32(crc32(0, &ri, sizeof(ri)-8)); |
1265 | ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); | 1268 | ri.data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); |
1266 | 1269 | ||
1267 | new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, phys_ofs, ALLOC_GC); | 1270 | new_fn = jffs2_write_dnode(c, f, &ri, comprbuf, cdatalen, ALLOC_GC); |
1268 | 1271 | ||
1269 | jffs2_free_comprbuf(comprbuf, writebuf); | 1272 | jffs2_free_comprbuf(comprbuf, writebuf); |
1270 | 1273 | ||
diff --git a/fs/jffs2/histo.h b/fs/jffs2/histo.h deleted file mode 100644 index 22a93a08210c..000000000000 --- a/fs/jffs2/histo.h +++ /dev/null | |||
@@ -1,3 +0,0 @@ | |||
1 | /* This file provides the bit-probabilities for the input file */ | ||
2 | #define BIT_DIVIDER 629 | ||
3 | static int bits[9] = { 179,167,183,165,159,198,178,119,}; /* ia32 .so files */ | ||
diff --git a/fs/jffs2/jffs2_fs_i.h b/fs/jffs2/jffs2_fs_i.h new file mode 100644 index 000000000000..2e0cc8e00b85 --- /dev/null +++ b/fs/jffs2/jffs2_fs_i.h | |||
@@ -0,0 +1,55 @@ | |||
1 | /* $Id: jffs2_fs_i.h,v 1.19 2005/11/07 11:14:52 gleixner Exp $ */ | ||
2 | |||
3 | #ifndef _JFFS2_FS_I | ||
4 | #define _JFFS2_FS_I | ||
5 | |||
6 | #include <linux/version.h> | ||
7 | #include <linux/rbtree.h> | ||
8 | #include <linux/posix_acl.h> | ||
9 | #include <asm/semaphore.h> | ||
10 | |||
11 | struct jffs2_inode_info { | ||
12 | /* We need an internal mutex similar to inode->i_mutex. | ||
13 | Unfortunately, we can't used the existing one, because | ||
14 | either the GC would deadlock, or we'd have to release it | ||
15 | before letting GC proceed. Or we'd have to put ugliness | ||
16 | into the GC code so it didn't attempt to obtain the i_mutex | ||
17 | for the inode(s) which are already locked */ | ||
18 | struct semaphore sem; | ||
19 | |||
20 | /* The highest (datanode) version number used for this ino */ | ||
21 | uint32_t highest_version; | ||
22 | |||
23 | /* List of data fragments which make up the file */ | ||
24 | struct rb_root fragtree; | ||
25 | |||
26 | /* There may be one datanode which isn't referenced by any of the | ||
27 | above fragments, if it contains a metadata update but no actual | ||
28 | data - or if this is a directory inode */ | ||
29 | /* This also holds the _only_ dnode for symlinks/device nodes, | ||
30 | etc. */ | ||
31 | struct jffs2_full_dnode *metadata; | ||
32 | |||
33 | /* Directory entries */ | ||
34 | struct jffs2_full_dirent *dents; | ||
35 | |||
36 | /* The target path if this is the inode of a symlink */ | ||
37 | unsigned char *target; | ||
38 | |||
39 | /* Some stuff we just have to keep in-core at all times, for each inode. */ | ||
40 | struct jffs2_inode_cache *inocache; | ||
41 | |||
42 | uint16_t flags; | ||
43 | uint8_t usercompr; | ||
44 | #if !defined (__ECOS) | ||
45 | #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,2) | ||
46 | struct inode vfs_inode; | ||
47 | #endif | ||
48 | #endif | ||
49 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
50 | struct posix_acl *i_acl_access; | ||
51 | struct posix_acl *i_acl_default; | ||
52 | #endif | ||
53 | }; | ||
54 | |||
55 | #endif /* _JFFS2_FS_I */ | ||
diff --git a/fs/jffs2/jffs2_fs_sb.h b/fs/jffs2/jffs2_fs_sb.h new file mode 100644 index 000000000000..935fec1b1201 --- /dev/null +++ b/fs/jffs2/jffs2_fs_sb.h | |||
@@ -0,0 +1,133 @@ | |||
1 | /* $Id: jffs2_fs_sb.h,v 1.54 2005/09/21 13:37:34 dedekind Exp $ */ | ||
2 | |||
3 | #ifndef _JFFS2_FS_SB | ||
4 | #define _JFFS2_FS_SB | ||
5 | |||
6 | #include <linux/types.h> | ||
7 | #include <linux/spinlock.h> | ||
8 | #include <linux/workqueue.h> | ||
9 | #include <linux/completion.h> | ||
10 | #include <asm/semaphore.h> | ||
11 | #include <linux/timer.h> | ||
12 | #include <linux/wait.h> | ||
13 | #include <linux/list.h> | ||
14 | #include <linux/rwsem.h> | ||
15 | |||
16 | #define JFFS2_SB_FLAG_RO 1 | ||
17 | #define JFFS2_SB_FLAG_SCANNING 2 /* Flash scanning is in progress */ | ||
18 | #define JFFS2_SB_FLAG_BUILDING 4 /* File system building is in progress */ | ||
19 | |||
20 | struct jffs2_inodirty; | ||
21 | |||
22 | /* A struct for the overall file system control. Pointers to | ||
23 | jffs2_sb_info structs are named `c' in the source code. | ||
24 | Nee jffs_control | ||
25 | */ | ||
26 | struct jffs2_sb_info { | ||
27 | struct mtd_info *mtd; | ||
28 | |||
29 | uint32_t highest_ino; | ||
30 | uint32_t checked_ino; | ||
31 | |||
32 | unsigned int flags; | ||
33 | |||
34 | struct task_struct *gc_task; /* GC task struct */ | ||
35 | struct completion gc_thread_start; /* GC thread start completion */ | ||
36 | struct completion gc_thread_exit; /* GC thread exit completion port */ | ||
37 | |||
38 | struct semaphore alloc_sem; /* Used to protect all the following | ||
39 | fields, and also to protect against | ||
40 | out-of-order writing of nodes. And GC. */ | ||
41 | uint32_t cleanmarker_size; /* Size of an _inline_ CLEANMARKER | ||
42 | (i.e. zero for OOB CLEANMARKER */ | ||
43 | |||
44 | uint32_t flash_size; | ||
45 | uint32_t used_size; | ||
46 | uint32_t dirty_size; | ||
47 | uint32_t wasted_size; | ||
48 | uint32_t free_size; | ||
49 | uint32_t erasing_size; | ||
50 | uint32_t bad_size; | ||
51 | uint32_t sector_size; | ||
52 | uint32_t unchecked_size; | ||
53 | |||
54 | uint32_t nr_free_blocks; | ||
55 | uint32_t nr_erasing_blocks; | ||
56 | |||
57 | /* Number of free blocks there must be before we... */ | ||
58 | uint8_t resv_blocks_write; /* ... allow a normal filesystem write */ | ||
59 | uint8_t resv_blocks_deletion; /* ... allow a normal filesystem deletion */ | ||
60 | uint8_t resv_blocks_gctrigger; /* ... wake up the GC thread */ | ||
61 | uint8_t resv_blocks_gcbad; /* ... pick a block from the bad_list to GC */ | ||
62 | uint8_t resv_blocks_gcmerge; /* ... merge pages when garbage collecting */ | ||
63 | |||
64 | uint32_t nospc_dirty_size; | ||
65 | |||
66 | uint32_t nr_blocks; | ||
67 | struct jffs2_eraseblock *blocks; /* The whole array of blocks. Used for getting blocks | ||
68 | * from the offset (blocks[ofs / sector_size]) */ | ||
69 | struct jffs2_eraseblock *nextblock; /* The block we're currently filling */ | ||
70 | |||
71 | struct jffs2_eraseblock *gcblock; /* The block we're currently garbage-collecting */ | ||
72 | |||
73 | struct list_head clean_list; /* Blocks 100% full of clean data */ | ||
74 | struct list_head very_dirty_list; /* Blocks with lots of dirty space */ | ||
75 | struct list_head dirty_list; /* Blocks with some dirty space */ | ||
76 | struct list_head erasable_list; /* Blocks which are completely dirty, and need erasing */ | ||
77 | struct list_head erasable_pending_wbuf_list; /* Blocks which need erasing but only after the current wbuf is flushed */ | ||
78 | struct list_head erasing_list; /* Blocks which are currently erasing */ | ||
79 | struct list_head erase_pending_list; /* Blocks which need erasing now */ | ||
80 | struct list_head erase_complete_list; /* Blocks which are erased and need the clean marker written to them */ | ||
81 | struct list_head free_list; /* Blocks which are free and ready to be used */ | ||
82 | struct list_head bad_list; /* Bad blocks. */ | ||
83 | struct list_head bad_used_list; /* Bad blocks with valid data in. */ | ||
84 | |||
85 | spinlock_t erase_completion_lock; /* Protect free_list and erasing_list | ||
86 | against erase completion handler */ | ||
87 | wait_queue_head_t erase_wait; /* For waiting for erases to complete */ | ||
88 | |||
89 | wait_queue_head_t inocache_wq; | ||
90 | struct jffs2_inode_cache **inocache_list; | ||
91 | spinlock_t inocache_lock; | ||
92 | |||
93 | /* Sem to allow jffs2_garbage_collect_deletion_dirent to | ||
94 | drop the erase_completion_lock while it's holding a pointer | ||
95 | to an obsoleted node. I don't like this. Alternatives welcomed. */ | ||
96 | struct semaphore erase_free_sem; | ||
97 | |||
98 | uint32_t wbuf_pagesize; /* 0 for NOR and other flashes with no wbuf */ | ||
99 | |||
100 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | ||
101 | /* Write-behind buffer for NAND flash */ | ||
102 | unsigned char *wbuf; | ||
103 | unsigned char *oobbuf; | ||
104 | uint32_t wbuf_ofs; | ||
105 | uint32_t wbuf_len; | ||
106 | struct jffs2_inodirty *wbuf_inodes; | ||
107 | |||
108 | struct rw_semaphore wbuf_sem; /* Protects the write buffer */ | ||
109 | |||
110 | /* Information about out-of-band area usage... */ | ||
111 | struct nand_ecclayout *ecclayout; | ||
112 | uint32_t badblock_pos; | ||
113 | uint32_t fsdata_pos; | ||
114 | uint32_t fsdata_len; | ||
115 | #endif | ||
116 | |||
117 | struct jffs2_summary *summary; /* Summary information */ | ||
118 | |||
119 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
120 | #define XATTRINDEX_HASHSIZE (57) | ||
121 | uint32_t highest_xid; | ||
122 | struct list_head xattrindex[XATTRINDEX_HASHSIZE]; | ||
123 | struct list_head xattr_unchecked; | ||
124 | struct jffs2_xattr_ref *xref_temp; | ||
125 | struct rw_semaphore xattr_sem; | ||
126 | uint32_t xdatum_mem_usage; | ||
127 | uint32_t xdatum_mem_threshold; | ||
128 | #endif | ||
129 | /* OS-private pointer for getting back to master superblock info */ | ||
130 | void *os_priv; | ||
131 | }; | ||
132 | |||
133 | #endif /* _JFFS2_FB_SB */ | ||
diff --git a/fs/jffs2/malloc.c b/fs/jffs2/malloc.c index 036cbd11c004..4889d0700c0e 100644 --- a/fs/jffs2/malloc.c +++ b/fs/jffs2/malloc.c | |||
@@ -26,6 +26,10 @@ static kmem_cache_t *tmp_dnode_info_slab; | |||
26 | static kmem_cache_t *raw_node_ref_slab; | 26 | static kmem_cache_t *raw_node_ref_slab; |
27 | static kmem_cache_t *node_frag_slab; | 27 | static kmem_cache_t *node_frag_slab; |
28 | static kmem_cache_t *inode_cache_slab; | 28 | static kmem_cache_t *inode_cache_slab; |
29 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
30 | static kmem_cache_t *xattr_datum_cache; | ||
31 | static kmem_cache_t *xattr_ref_cache; | ||
32 | #endif | ||
29 | 33 | ||
30 | int __init jffs2_create_slab_caches(void) | 34 | int __init jffs2_create_slab_caches(void) |
31 | { | 35 | { |
@@ -53,8 +57,8 @@ int __init jffs2_create_slab_caches(void) | |||
53 | if (!tmp_dnode_info_slab) | 57 | if (!tmp_dnode_info_slab) |
54 | goto err; | 58 | goto err; |
55 | 59 | ||
56 | raw_node_ref_slab = kmem_cache_create("jffs2_raw_node_ref", | 60 | raw_node_ref_slab = kmem_cache_create("jffs2_refblock", |
57 | sizeof(struct jffs2_raw_node_ref), | 61 | sizeof(struct jffs2_raw_node_ref) * (REFS_PER_BLOCK + 1), |
58 | 0, 0, NULL, NULL); | 62 | 0, 0, NULL, NULL); |
59 | if (!raw_node_ref_slab) | 63 | if (!raw_node_ref_slab) |
60 | goto err; | 64 | goto err; |
@@ -68,8 +72,24 @@ int __init jffs2_create_slab_caches(void) | |||
68 | inode_cache_slab = kmem_cache_create("jffs2_inode_cache", | 72 | inode_cache_slab = kmem_cache_create("jffs2_inode_cache", |
69 | sizeof(struct jffs2_inode_cache), | 73 | sizeof(struct jffs2_inode_cache), |
70 | 0, 0, NULL, NULL); | 74 | 0, 0, NULL, NULL); |
71 | if (inode_cache_slab) | 75 | if (!inode_cache_slab) |
72 | return 0; | 76 | goto err; |
77 | |||
78 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
79 | xattr_datum_cache = kmem_cache_create("jffs2_xattr_datum", | ||
80 | sizeof(struct jffs2_xattr_datum), | ||
81 | 0, 0, NULL, NULL); | ||
82 | if (!xattr_datum_cache) | ||
83 | goto err; | ||
84 | |||
85 | xattr_ref_cache = kmem_cache_create("jffs2_xattr_ref", | ||
86 | sizeof(struct jffs2_xattr_ref), | ||
87 | 0, 0, NULL, NULL); | ||
88 | if (!xattr_ref_cache) | ||
89 | goto err; | ||
90 | #endif | ||
91 | |||
92 | return 0; | ||
73 | err: | 93 | err: |
74 | jffs2_destroy_slab_caches(); | 94 | jffs2_destroy_slab_caches(); |
75 | return -ENOMEM; | 95 | return -ENOMEM; |
@@ -91,6 +111,12 @@ void jffs2_destroy_slab_caches(void) | |||
91 | kmem_cache_destroy(node_frag_slab); | 111 | kmem_cache_destroy(node_frag_slab); |
92 | if(inode_cache_slab) | 112 | if(inode_cache_slab) |
93 | kmem_cache_destroy(inode_cache_slab); | 113 | kmem_cache_destroy(inode_cache_slab); |
114 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
115 | if (xattr_datum_cache) | ||
116 | kmem_cache_destroy(xattr_datum_cache); | ||
117 | if (xattr_ref_cache) | ||
118 | kmem_cache_destroy(xattr_ref_cache); | ||
119 | #endif | ||
94 | } | 120 | } |
95 | 121 | ||
96 | struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) | 122 | struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize) |
@@ -164,15 +190,65 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x) | |||
164 | kmem_cache_free(tmp_dnode_info_slab, x); | 190 | kmem_cache_free(tmp_dnode_info_slab, x); |
165 | } | 191 | } |
166 | 192 | ||
167 | struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void) | 193 | struct jffs2_raw_node_ref *jffs2_alloc_refblock(void) |
168 | { | 194 | { |
169 | struct jffs2_raw_node_ref *ret; | 195 | struct jffs2_raw_node_ref *ret; |
196 | |||
170 | ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); | 197 | ret = kmem_cache_alloc(raw_node_ref_slab, GFP_KERNEL); |
171 | dbg_memalloc("%p\n", ret); | 198 | if (ret) { |
199 | int i = 0; | ||
200 | for (i=0; i < REFS_PER_BLOCK; i++) { | ||
201 | ret[i].flash_offset = REF_EMPTY_NODE; | ||
202 | ret[i].next_in_ino = NULL; | ||
203 | } | ||
204 | ret[i].flash_offset = REF_LINK_NODE; | ||
205 | ret[i].next_in_ino = NULL; | ||
206 | } | ||
172 | return ret; | 207 | return ret; |
173 | } | 208 | } |
174 | 209 | ||
175 | void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x) | 210 | int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, |
211 | struct jffs2_eraseblock *jeb, int nr) | ||
212 | { | ||
213 | struct jffs2_raw_node_ref **p, *ref; | ||
214 | int i = nr; | ||
215 | |||
216 | dbg_memalloc("%d\n", nr); | ||
217 | |||
218 | p = &jeb->last_node; | ||
219 | ref = *p; | ||
220 | |||
221 | dbg_memalloc("Reserving %d refs for block @0x%08x\n", nr, jeb->offset); | ||
222 | |||
223 | /* If jeb->last_node is really a valid node then skip over it */ | ||
224 | if (ref && ref->flash_offset != REF_EMPTY_NODE) | ||
225 | ref++; | ||
226 | |||
227 | while (i) { | ||
228 | if (!ref) { | ||
229 | dbg_memalloc("Allocating new refblock linked from %p\n", p); | ||
230 | ref = *p = jffs2_alloc_refblock(); | ||
231 | if (!ref) | ||
232 | return -ENOMEM; | ||
233 | } | ||
234 | if (ref->flash_offset == REF_LINK_NODE) { | ||
235 | p = &ref->next_in_ino; | ||
236 | ref = *p; | ||
237 | continue; | ||
238 | } | ||
239 | i--; | ||
240 | ref++; | ||
241 | } | ||
242 | jeb->allocated_refs = nr; | ||
243 | |||
244 | dbg_memalloc("Reserved %d refs for block @0x%08x, last_node is %p (%08x,%p)\n", | ||
245 | nr, jeb->offset, jeb->last_node, jeb->last_node->flash_offset, | ||
246 | jeb->last_node->next_in_ino); | ||
247 | |||
248 | return 0; | ||
249 | } | ||
250 | |||
251 | void jffs2_free_refblock(struct jffs2_raw_node_ref *x) | ||
176 | { | 252 | { |
177 | dbg_memalloc("%p\n", x); | 253 | dbg_memalloc("%p\n", x); |
178 | kmem_cache_free(raw_node_ref_slab, x); | 254 | kmem_cache_free(raw_node_ref_slab, x); |
@@ -205,3 +281,40 @@ void jffs2_free_inode_cache(struct jffs2_inode_cache *x) | |||
205 | dbg_memalloc("%p\n", x); | 281 | dbg_memalloc("%p\n", x); |
206 | kmem_cache_free(inode_cache_slab, x); | 282 | kmem_cache_free(inode_cache_slab, x); |
207 | } | 283 | } |
284 | |||
285 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
286 | struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void) | ||
287 | { | ||
288 | struct jffs2_xattr_datum *xd; | ||
289 | xd = kmem_cache_alloc(xattr_datum_cache, GFP_KERNEL); | ||
290 | dbg_memalloc("%p\n", xd); | ||
291 | |||
292 | memset(xd, 0, sizeof(struct jffs2_xattr_datum)); | ||
293 | xd->class = RAWNODE_CLASS_XATTR_DATUM; | ||
294 | INIT_LIST_HEAD(&xd->xindex); | ||
295 | return xd; | ||
296 | } | ||
297 | |||
298 | void jffs2_free_xattr_datum(struct jffs2_xattr_datum *xd) | ||
299 | { | ||
300 | dbg_memalloc("%p\n", xd); | ||
301 | kmem_cache_free(xattr_datum_cache, xd); | ||
302 | } | ||
303 | |||
304 | struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void) | ||
305 | { | ||
306 | struct jffs2_xattr_ref *ref; | ||
307 | ref = kmem_cache_alloc(xattr_ref_cache, GFP_KERNEL); | ||
308 | dbg_memalloc("%p\n", ref); | ||
309 | |||
310 | memset(ref, 0, sizeof(struct jffs2_xattr_ref)); | ||
311 | ref->class = RAWNODE_CLASS_XATTR_REF; | ||
312 | return ref; | ||
313 | } | ||
314 | |||
315 | void jffs2_free_xattr_ref(struct jffs2_xattr_ref *ref) | ||
316 | { | ||
317 | dbg_memalloc("%p\n", ref); | ||
318 | kmem_cache_free(xattr_ref_cache, ref); | ||
319 | } | ||
320 | #endif | ||
diff --git a/fs/jffs2/nodelist.c b/fs/jffs2/nodelist.c index 1d46677afd17..927dfe42ba76 100644 --- a/fs/jffs2/nodelist.c +++ b/fs/jffs2/nodelist.c | |||
@@ -438,8 +438,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info | |||
438 | if (c->mtd->point) { | 438 | if (c->mtd->point) { |
439 | err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); | 439 | err = c->mtd->point(c->mtd, ofs, len, &retlen, &buffer); |
440 | if (!err && retlen < tn->csize) { | 440 | if (!err && retlen < tn->csize) { |
441 | JFFS2_WARNING("MTD point returned len too short: %zu " | 441 | JFFS2_WARNING("MTD point returned len too short: %zu instead of %u.\n", retlen, tn->csize); |
442 | "instead of %u.\n", retlen, tn->csize); | ||
443 | c->mtd->unpoint(c->mtd, buffer, ofs, len); | 442 | c->mtd->unpoint(c->mtd, buffer, ofs, len); |
444 | } else if (err) | 443 | } else if (err) |
445 | JFFS2_WARNING("MTD point failed: error code %d.\n", err); | 444 | JFFS2_WARNING("MTD point failed: error code %d.\n", err); |
@@ -462,8 +461,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info | |||
462 | } | 461 | } |
463 | 462 | ||
464 | if (retlen != len) { | 463 | if (retlen != len) { |
465 | JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", | 464 | JFFS2_ERROR("short read at %#08x: %zd instead of %d.\n", ofs, retlen, len); |
466 | ofs, retlen, len); | ||
467 | err = -EIO; | 465 | err = -EIO; |
468 | goto free_out; | 466 | goto free_out; |
469 | } | 467 | } |
@@ -940,6 +938,7 @@ void jffs2_free_ino_caches(struct jffs2_sb_info *c) | |||
940 | this = c->inocache_list[i]; | 938 | this = c->inocache_list[i]; |
941 | while (this) { | 939 | while (this) { |
942 | next = this->next; | 940 | next = this->next; |
941 | jffs2_xattr_free_inode(c, this); | ||
943 | jffs2_free_inode_cache(this); | 942 | jffs2_free_inode_cache(this); |
944 | this = next; | 943 | this = next; |
945 | } | 944 | } |
@@ -954,9 +953,13 @@ void jffs2_free_raw_node_refs(struct jffs2_sb_info *c) | |||
954 | 953 | ||
955 | for (i=0; i<c->nr_blocks; i++) { | 954 | for (i=0; i<c->nr_blocks; i++) { |
956 | this = c->blocks[i].first_node; | 955 | this = c->blocks[i].first_node; |
957 | while(this) { | 956 | while (this) { |
958 | next = this->next_phys; | 957 | if (this[REFS_PER_BLOCK].flash_offset == REF_LINK_NODE) |
959 | jffs2_free_raw_node_ref(this); | 958 | next = this[REFS_PER_BLOCK].next_in_ino; |
959 | else | ||
960 | next = NULL; | ||
961 | |||
962 | jffs2_free_refblock(this); | ||
960 | this = next; | 963 | this = next; |
961 | } | 964 | } |
962 | c->blocks[i].first_node = c->blocks[i].last_node = NULL; | 965 | c->blocks[i].first_node = c->blocks[i].last_node = NULL; |
@@ -1047,3 +1050,169 @@ void jffs2_kill_fragtree(struct rb_root *root, struct jffs2_sb_info *c) | |||
1047 | cond_resched(); | 1050 | cond_resched(); |
1048 | } | 1051 | } |
1049 | } | 1052 | } |
1053 | |||
1054 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, | ||
1055 | struct jffs2_eraseblock *jeb, | ||
1056 | uint32_t ofs, uint32_t len, | ||
1057 | struct jffs2_inode_cache *ic) | ||
1058 | { | ||
1059 | struct jffs2_raw_node_ref *ref; | ||
1060 | |||
1061 | BUG_ON(!jeb->allocated_refs); | ||
1062 | jeb->allocated_refs--; | ||
1063 | |||
1064 | ref = jeb->last_node; | ||
1065 | |||
1066 | dbg_noderef("Last node at %p is (%08x,%p)\n", ref, ref->flash_offset, | ||
1067 | ref->next_in_ino); | ||
1068 | |||
1069 | while (ref->flash_offset != REF_EMPTY_NODE) { | ||
1070 | if (ref->flash_offset == REF_LINK_NODE) | ||
1071 | ref = ref->next_in_ino; | ||
1072 | else | ||
1073 | ref++; | ||
1074 | } | ||
1075 | |||
1076 | dbg_noderef("New ref is %p (%08x becomes %08x,%p) len 0x%x\n", ref, | ||
1077 | ref->flash_offset, ofs, ref->next_in_ino, len); | ||
1078 | |||
1079 | ref->flash_offset = ofs; | ||
1080 | |||
1081 | if (!jeb->first_node) { | ||
1082 | jeb->first_node = ref; | ||
1083 | BUG_ON(ref_offset(ref) != jeb->offset); | ||
1084 | } else if (unlikely(ref_offset(ref) != jeb->offset + c->sector_size - jeb->free_size)) { | ||
1085 | uint32_t last_len = ref_totlen(c, jeb, jeb->last_node); | ||
1086 | |||
1087 | JFFS2_ERROR("Adding new ref %p at (0x%08x-0x%08x) not immediately after previous (0x%08x-0x%08x)\n", | ||
1088 | ref, ref_offset(ref), ref_offset(ref)+len, | ||
1089 | ref_offset(jeb->last_node), | ||
1090 | ref_offset(jeb->last_node)+last_len); | ||
1091 | BUG(); | ||
1092 | } | ||
1093 | jeb->last_node = ref; | ||
1094 | |||
1095 | if (ic) { | ||
1096 | ref->next_in_ino = ic->nodes; | ||
1097 | ic->nodes = ref; | ||
1098 | } else { | ||
1099 | ref->next_in_ino = NULL; | ||
1100 | } | ||
1101 | |||
1102 | switch(ref_flags(ref)) { | ||
1103 | case REF_UNCHECKED: | ||
1104 | c->unchecked_size += len; | ||
1105 | jeb->unchecked_size += len; | ||
1106 | break; | ||
1107 | |||
1108 | case REF_NORMAL: | ||
1109 | case REF_PRISTINE: | ||
1110 | c->used_size += len; | ||
1111 | jeb->used_size += len; | ||
1112 | break; | ||
1113 | |||
1114 | case REF_OBSOLETE: | ||
1115 | c->dirty_size += len; | ||
1116 | jeb->dirty_size += len; | ||
1117 | break; | ||
1118 | } | ||
1119 | c->free_size -= len; | ||
1120 | jeb->free_size -= len; | ||
1121 | |||
1122 | #ifdef TEST_TOTLEN | ||
1123 | /* Set (and test) __totlen field... for now */ | ||
1124 | ref->__totlen = len; | ||
1125 | ref_totlen(c, jeb, ref); | ||
1126 | #endif | ||
1127 | return ref; | ||
1128 | } | ||
1129 | |||
1130 | /* No locking, no reservation of 'ref'. Do not use on a live file system */ | ||
1131 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
1132 | uint32_t size) | ||
1133 | { | ||
1134 | if (!size) | ||
1135 | return 0; | ||
1136 | if (unlikely(size > jeb->free_size)) { | ||
1137 | printk(KERN_CRIT "Dirty space 0x%x larger then free_size 0x%x (wasted 0x%x)\n", | ||
1138 | size, jeb->free_size, jeb->wasted_size); | ||
1139 | BUG(); | ||
1140 | } | ||
1141 | /* REF_EMPTY_NODE is !obsolete, so that works OK */ | ||
1142 | if (jeb->last_node && ref_obsolete(jeb->last_node)) { | ||
1143 | #ifdef TEST_TOTLEN | ||
1144 | jeb->last_node->__totlen += size; | ||
1145 | #endif | ||
1146 | c->dirty_size += size; | ||
1147 | c->free_size -= size; | ||
1148 | jeb->dirty_size += size; | ||
1149 | jeb->free_size -= size; | ||
1150 | } else { | ||
1151 | uint32_t ofs = jeb->offset + c->sector_size - jeb->free_size; | ||
1152 | ofs |= REF_OBSOLETE; | ||
1153 | |||
1154 | jffs2_link_node_ref(c, jeb, ofs, size, NULL); | ||
1155 | } | ||
1156 | |||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | /* Calculate totlen from surrounding nodes or eraseblock */ | ||
1161 | static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, | ||
1162 | struct jffs2_eraseblock *jeb, | ||
1163 | struct jffs2_raw_node_ref *ref) | ||
1164 | { | ||
1165 | uint32_t ref_end; | ||
1166 | struct jffs2_raw_node_ref *next_ref = ref_next(ref); | ||
1167 | |||
1168 | if (next_ref) | ||
1169 | ref_end = ref_offset(next_ref); | ||
1170 | else { | ||
1171 | if (!jeb) | ||
1172 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
1173 | |||
1174 | /* Last node in block. Use free_space */ | ||
1175 | if (unlikely(ref != jeb->last_node)) { | ||
1176 | printk(KERN_CRIT "ref %p @0x%08x is not jeb->last_node (%p @0x%08x)\n", | ||
1177 | ref, ref_offset(ref), jeb->last_node, jeb->last_node?ref_offset(jeb->last_node):0); | ||
1178 | BUG(); | ||
1179 | } | ||
1180 | ref_end = jeb->offset + c->sector_size - jeb->free_size; | ||
1181 | } | ||
1182 | return ref_end - ref_offset(ref); | ||
1183 | } | ||
1184 | |||
1185 | uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
1186 | struct jffs2_raw_node_ref *ref) | ||
1187 | { | ||
1188 | uint32_t ret; | ||
1189 | |||
1190 | ret = __ref_totlen(c, jeb, ref); | ||
1191 | |||
1192 | #ifdef TEST_TOTLEN | ||
1193 | if (unlikely(ret != ref->__totlen)) { | ||
1194 | if (!jeb) | ||
1195 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
1196 | |||
1197 | printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", | ||
1198 | ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, | ||
1199 | ret, ref->__totlen); | ||
1200 | if (ref_next(ref)) { | ||
1201 | printk(KERN_CRIT "next %p (0x%08x-0x%08x)\n", ref_next(ref), ref_offset(ref_next(ref)), | ||
1202 | ref_offset(ref_next(ref))+ref->__totlen); | ||
1203 | } else | ||
1204 | printk(KERN_CRIT "No next ref. jeb->last_node is %p\n", jeb->last_node); | ||
1205 | |||
1206 | printk(KERN_CRIT "jeb->wasted_size %x, dirty_size %x, used_size %x, free_size %x\n", jeb->wasted_size, jeb->dirty_size, jeb->used_size, jeb->free_size); | ||
1207 | |||
1208 | #if defined(JFFS2_DBG_DUMPS) || defined(JFFS2_DBG_PARANOIA_CHECKS) | ||
1209 | __jffs2_dbg_dump_node_refs_nolock(c, jeb); | ||
1210 | #endif | ||
1211 | |||
1212 | WARN_ON(1); | ||
1213 | |||
1214 | ret = ref->__totlen; | ||
1215 | } | ||
1216 | #endif /* TEST_TOTLEN */ | ||
1217 | return ret; | ||
1218 | } | ||
diff --git a/fs/jffs2/nodelist.h b/fs/jffs2/nodelist.h index 23a67bb3052f..b16c60bbcf6e 100644 --- a/fs/jffs2/nodelist.h +++ b/fs/jffs2/nodelist.h | |||
@@ -18,8 +18,10 @@ | |||
18 | #include <linux/fs.h> | 18 | #include <linux/fs.h> |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/jffs2.h> | 20 | #include <linux/jffs2.h> |
21 | #include <linux/jffs2_fs_sb.h> | 21 | #include "jffs2_fs_sb.h" |
22 | #include <linux/jffs2_fs_i.h> | 22 | #include "jffs2_fs_i.h" |
23 | #include "xattr.h" | ||
24 | #include "acl.h" | ||
23 | #include "summary.h" | 25 | #include "summary.h" |
24 | 26 | ||
25 | #ifdef __ECOS | 27 | #ifdef __ECOS |
@@ -75,14 +77,50 @@ | |||
75 | struct jffs2_raw_node_ref | 77 | struct jffs2_raw_node_ref |
76 | { | 78 | { |
77 | struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref | 79 | struct jffs2_raw_node_ref *next_in_ino; /* Points to the next raw_node_ref |
78 | for this inode. If this is the last, it points to the inode_cache | 80 | for this object. If this _is_ the last, it points to the inode_cache, |
79 | for this inode instead. The inode_cache will have NULL in the first | 81 | xattr_ref or xattr_datum instead. The common part of those structures |
80 | word so you know when you've got there :) */ | 82 | has NULL in the first word. See jffs2_raw_ref_to_ic() below */ |
81 | struct jffs2_raw_node_ref *next_phys; | ||
82 | uint32_t flash_offset; | 83 | uint32_t flash_offset; |
84 | #define TEST_TOTLEN | ||
85 | #ifdef TEST_TOTLEN | ||
83 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ | 86 | uint32_t __totlen; /* This may die; use ref_totlen(c, jeb, ) below */ |
87 | #endif | ||
84 | }; | 88 | }; |
85 | 89 | ||
90 | #define REF_LINK_NODE ((int32_t)-1) | ||
91 | #define REF_EMPTY_NODE ((int32_t)-2) | ||
92 | |||
93 | /* Use blocks of about 256 bytes */ | ||
94 | #define REFS_PER_BLOCK ((255/sizeof(struct jffs2_raw_node_ref))-1) | ||
95 | |||
96 | static inline struct jffs2_raw_node_ref *ref_next(struct jffs2_raw_node_ref *ref) | ||
97 | { | ||
98 | ref++; | ||
99 | |||
100 | /* Link to another block of refs */ | ||
101 | if (ref->flash_offset == REF_LINK_NODE) { | ||
102 | ref = ref->next_in_ino; | ||
103 | if (!ref) | ||
104 | return ref; | ||
105 | } | ||
106 | |||
107 | /* End of chain */ | ||
108 | if (ref->flash_offset == REF_EMPTY_NODE) | ||
109 | return NULL; | ||
110 | |||
111 | return ref; | ||
112 | } | ||
113 | |||
114 | static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) | ||
115 | { | ||
116 | while(raw->next_in_ino) | ||
117 | raw = raw->next_in_ino; | ||
118 | |||
119 | /* NB. This can be a jffs2_xattr_datum or jffs2_xattr_ref and | ||
120 | not actually a jffs2_inode_cache. Check ->class */ | ||
121 | return ((struct jffs2_inode_cache *)raw); | ||
122 | } | ||
123 | |||
86 | /* flash_offset & 3 always has to be zero, because nodes are | 124 | /* flash_offset & 3 always has to be zero, because nodes are |
87 | always aligned at 4 bytes. So we have a couple of extra bits | 125 | always aligned at 4 bytes. So we have a couple of extra bits |
88 | to play with, which indicate the node's status; see below: */ | 126 | to play with, which indicate the node's status; see below: */ |
@@ -95,6 +133,11 @@ struct jffs2_raw_node_ref | |||
95 | #define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) | 133 | #define ref_obsolete(ref) (((ref)->flash_offset & 3) == REF_OBSOLETE) |
96 | #define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) | 134 | #define mark_ref_normal(ref) do { (ref)->flash_offset = ref_offset(ref) | REF_NORMAL; } while(0) |
97 | 135 | ||
136 | /* NB: REF_PRISTINE for an inode-less node (ref->next_in_ino == NULL) indicates | ||
137 | it is an unknown node of type JFFS2_NODETYPE_RWCOMPAT_COPY, so it'll get | ||
138 | copied. If you need to do anything different to GC inode-less nodes, then | ||
139 | you need to modify gc.c accordingly. */ | ||
140 | |||
98 | /* For each inode in the filesystem, we need to keep a record of | 141 | /* For each inode in the filesystem, we need to keep a record of |
99 | nlink, because it would be a PITA to scan the whole directory tree | 142 | nlink, because it would be a PITA to scan the whole directory tree |
100 | at read_inode() time to calculate it, and to keep sufficient information | 143 | at read_inode() time to calculate it, and to keep sufficient information |
@@ -103,15 +146,27 @@ struct jffs2_raw_node_ref | |||
103 | a pointer to the first physical node which is part of this inode, too. | 146 | a pointer to the first physical node which is part of this inode, too. |
104 | */ | 147 | */ |
105 | struct jffs2_inode_cache { | 148 | struct jffs2_inode_cache { |
149 | /* First part of structure is shared with other objects which | ||
150 | can terminate the raw node refs' next_in_ino list -- which | ||
151 | currently struct jffs2_xattr_datum and struct jffs2_xattr_ref. */ | ||
152 | |||
106 | struct jffs2_full_dirent *scan_dents; /* Used during scan to hold | 153 | struct jffs2_full_dirent *scan_dents; /* Used during scan to hold |
107 | temporary lists of dirents, and later must be set to | 154 | temporary lists of dirents, and later must be set to |
108 | NULL to mark the end of the raw_node_ref->next_in_ino | 155 | NULL to mark the end of the raw_node_ref->next_in_ino |
109 | chain. */ | 156 | chain. */ |
110 | struct jffs2_inode_cache *next; | ||
111 | struct jffs2_raw_node_ref *nodes; | 157 | struct jffs2_raw_node_ref *nodes; |
158 | uint8_t class; /* It's used for identification */ | ||
159 | |||
160 | /* end of shared structure */ | ||
161 | |||
162 | uint8_t flags; | ||
163 | uint16_t state; | ||
112 | uint32_t ino; | 164 | uint32_t ino; |
165 | struct jffs2_inode_cache *next; | ||
166 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
167 | struct jffs2_xattr_ref *xref; | ||
168 | #endif | ||
113 | int nlink; | 169 | int nlink; |
114 | int state; | ||
115 | }; | 170 | }; |
116 | 171 | ||
117 | /* Inode states for 'state' above. We need the 'GC' state to prevent | 172 | /* Inode states for 'state' above. We need the 'GC' state to prevent |
@@ -125,8 +180,16 @@ struct jffs2_inode_cache { | |||
125 | #define INO_STATE_READING 5 /* In read_inode() */ | 180 | #define INO_STATE_READING 5 /* In read_inode() */ |
126 | #define INO_STATE_CLEARING 6 /* In clear_inode() */ | 181 | #define INO_STATE_CLEARING 6 /* In clear_inode() */ |
127 | 182 | ||
183 | #define INO_FLAGS_XATTR_CHECKED 0x01 /* has no duplicate xattr_ref */ | ||
184 | |||
185 | #define RAWNODE_CLASS_INODE_CACHE 0 | ||
186 | #define RAWNODE_CLASS_XATTR_DATUM 1 | ||
187 | #define RAWNODE_CLASS_XATTR_REF 2 | ||
188 | |||
128 | #define INOCACHE_HASHSIZE 128 | 189 | #define INOCACHE_HASHSIZE 128 |
129 | 190 | ||
191 | #define write_ofs(c) ((c)->nextblock->offset + (c)->sector_size - (c)->nextblock->free_size) | ||
192 | |||
130 | /* | 193 | /* |
131 | Larger representation of a raw node, kept in-core only when the | 194 | Larger representation of a raw node, kept in-core only when the |
132 | struct inode for this particular ino is instantiated. | 195 | struct inode for this particular ino is instantiated. |
@@ -192,6 +255,7 @@ struct jffs2_eraseblock | |||
192 | uint32_t wasted_size; | 255 | uint32_t wasted_size; |
193 | uint32_t free_size; /* Note that sector_size - free_size | 256 | uint32_t free_size; /* Note that sector_size - free_size |
194 | is the address of the first free space */ | 257 | is the address of the first free space */ |
258 | uint32_t allocated_refs; | ||
195 | struct jffs2_raw_node_ref *first_node; | 259 | struct jffs2_raw_node_ref *first_node; |
196 | struct jffs2_raw_node_ref *last_node; | 260 | struct jffs2_raw_node_ref *last_node; |
197 | 261 | ||
@@ -203,57 +267,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c) | |||
203 | return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); | 267 | return ((c->flash_size / c->sector_size) * sizeof (struct jffs2_eraseblock)) > (128 * 1024); |
204 | } | 268 | } |
205 | 269 | ||
206 | /* Calculate totlen from surrounding nodes or eraseblock */ | 270 | #define ref_totlen(a, b, c) __jffs2_ref_totlen((a), (b), (c)) |
207 | static inline uint32_t __ref_totlen(struct jffs2_sb_info *c, | ||
208 | struct jffs2_eraseblock *jeb, | ||
209 | struct jffs2_raw_node_ref *ref) | ||
210 | { | ||
211 | uint32_t ref_end; | ||
212 | |||
213 | if (ref->next_phys) | ||
214 | ref_end = ref_offset(ref->next_phys); | ||
215 | else { | ||
216 | if (!jeb) | ||
217 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
218 | |||
219 | /* Last node in block. Use free_space */ | ||
220 | BUG_ON(ref != jeb->last_node); | ||
221 | ref_end = jeb->offset + c->sector_size - jeb->free_size; | ||
222 | } | ||
223 | return ref_end - ref_offset(ref); | ||
224 | } | ||
225 | |||
226 | static inline uint32_t ref_totlen(struct jffs2_sb_info *c, | ||
227 | struct jffs2_eraseblock *jeb, | ||
228 | struct jffs2_raw_node_ref *ref) | ||
229 | { | ||
230 | uint32_t ret; | ||
231 | |||
232 | #if CONFIG_JFFS2_FS_DEBUG > 0 | ||
233 | if (jeb && jeb != &c->blocks[ref->flash_offset / c->sector_size]) { | ||
234 | printk(KERN_CRIT "ref_totlen called with wrong block -- at 0x%08x instead of 0x%08x; ref 0x%08x\n", | ||
235 | jeb->offset, c->blocks[ref->flash_offset / c->sector_size].offset, ref_offset(ref)); | ||
236 | BUG(); | ||
237 | } | ||
238 | #endif | ||
239 | |||
240 | #if 1 | ||
241 | ret = ref->__totlen; | ||
242 | #else | ||
243 | /* This doesn't actually work yet */ | ||
244 | ret = __ref_totlen(c, jeb, ref); | ||
245 | if (ret != ref->__totlen) { | ||
246 | printk(KERN_CRIT "Totlen for ref at %p (0x%08x-0x%08x) miscalculated as 0x%x instead of %x\n", | ||
247 | ref, ref_offset(ref), ref_offset(ref)+ref->__totlen, | ||
248 | ret, ref->__totlen); | ||
249 | if (!jeb) | ||
250 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
251 | jffs2_dbg_dump_node_refs_nolock(c, jeb); | ||
252 | BUG(); | ||
253 | } | ||
254 | #endif | ||
255 | return ret; | ||
256 | } | ||
257 | 271 | ||
258 | #define ALLOC_NORMAL 0 /* Normal allocation */ | 272 | #define ALLOC_NORMAL 0 /* Normal allocation */ |
259 | #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ | 273 | #define ALLOC_DELETION 1 /* Deletion node. Best to allow it */ |
@@ -268,13 +282,15 @@ static inline uint32_t ref_totlen(struct jffs2_sb_info *c, | |||
268 | 282 | ||
269 | #define PAD(x) (((x)+3)&~3) | 283 | #define PAD(x) (((x)+3)&~3) |
270 | 284 | ||
271 | static inline struct jffs2_inode_cache *jffs2_raw_ref_to_ic(struct jffs2_raw_node_ref *raw) | 285 | static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev) |
272 | { | 286 | { |
273 | while(raw->next_in_ino) { | 287 | if (old_valid_dev(rdev)) { |
274 | raw = raw->next_in_ino; | 288 | jdev->old = cpu_to_je16(old_encode_dev(rdev)); |
289 | return sizeof(jdev->old); | ||
290 | } else { | ||
291 | jdev->new = cpu_to_je32(new_encode_dev(rdev)); | ||
292 | return sizeof(jdev->new); | ||
275 | } | 293 | } |
276 | |||
277 | return ((struct jffs2_inode_cache *)raw); | ||
278 | } | 294 | } |
279 | 295 | ||
280 | static inline struct jffs2_node_frag *frag_first(struct rb_root *root) | 296 | static inline struct jffs2_node_frag *frag_first(struct rb_root *root) |
@@ -299,7 +315,6 @@ static inline struct jffs2_node_frag *frag_last(struct rb_root *root) | |||
299 | return rb_entry(node, struct jffs2_node_frag, rb); | 315 | return rb_entry(node, struct jffs2_node_frag, rb); |
300 | } | 316 | } |
301 | 317 | ||
302 | #define rb_parent(rb) ((rb)->rb_parent) | ||
303 | #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) | 318 | #define frag_next(frag) rb_entry(rb_next(&(frag)->rb), struct jffs2_node_frag, rb) |
304 | #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) | 319 | #define frag_prev(frag) rb_entry(rb_prev(&(frag)->rb), struct jffs2_node_frag, rb) |
305 | #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) | 320 | #define frag_parent(frag) rb_entry(rb_parent(&(frag)->rb), struct jffs2_node_frag, rb) |
@@ -324,28 +339,44 @@ void jffs2_obsolete_node_frag(struct jffs2_sb_info *c, struct jffs2_node_frag *t | |||
324 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); | 339 | int jffs2_add_full_dnode_to_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_full_dnode *fn); |
325 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); | 340 | void jffs2_truncate_fragtree (struct jffs2_sb_info *c, struct rb_root *list, uint32_t size); |
326 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); | 341 | int jffs2_add_older_frag_to_fragtree(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_tmp_dnode_info *tn); |
342 | struct jffs2_raw_node_ref *jffs2_link_node_ref(struct jffs2_sb_info *c, | ||
343 | struct jffs2_eraseblock *jeb, | ||
344 | uint32_t ofs, uint32_t len, | ||
345 | struct jffs2_inode_cache *ic); | ||
346 | extern uint32_t __jffs2_ref_totlen(struct jffs2_sb_info *c, | ||
347 | struct jffs2_eraseblock *jeb, | ||
348 | struct jffs2_raw_node_ref *ref); | ||
327 | 349 | ||
328 | /* nodemgmt.c */ | 350 | /* nodemgmt.c */ |
329 | int jffs2_thread_should_wake(struct jffs2_sb_info *c); | 351 | int jffs2_thread_should_wake(struct jffs2_sb_info *c); |
330 | int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, | 352 | int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, |
331 | uint32_t *len, int prio, uint32_t sumsize); | 353 | uint32_t *len, int prio, uint32_t sumsize); |
332 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, | 354 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, |
333 | uint32_t *len, uint32_t sumsize); | 355 | uint32_t *len, uint32_t sumsize); |
334 | int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new); | 356 | struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, |
357 | uint32_t ofs, uint32_t len, | ||
358 | struct jffs2_inode_cache *ic); | ||
335 | void jffs2_complete_reservation(struct jffs2_sb_info *c); | 359 | void jffs2_complete_reservation(struct jffs2_sb_info *c); |
336 | void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); | 360 | void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *raw); |
337 | 361 | ||
338 | /* write.c */ | 362 | /* write.c */ |
339 | int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); | 363 | int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint32_t mode, struct jffs2_raw_inode *ri); |
340 | 364 | ||
341 | struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode); | 365 | struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
342 | struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode); | 366 | struct jffs2_raw_inode *ri, const unsigned char *data, |
367 | uint32_t datalen, int alloc_mode); | ||
368 | struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | ||
369 | struct jffs2_raw_dirent *rd, const unsigned char *name, | ||
370 | uint32_t namelen, int alloc_mode); | ||
343 | int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | 371 | int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
344 | struct jffs2_raw_inode *ri, unsigned char *buf, | 372 | struct jffs2_raw_inode *ri, unsigned char *buf, |
345 | uint32_t offset, uint32_t writelen, uint32_t *retlen); | 373 | uint32_t offset, uint32_t writelen, uint32_t *retlen); |
346 | int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const char *name, int namelen); | 374 | int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, struct jffs2_inode_info *f, |
347 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, int namelen, struct jffs2_inode_info *dead_f, uint32_t time); | 375 | struct jffs2_raw_inode *ri, const char *name, int namelen); |
348 | int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, uint8_t type, const char *name, int namelen, uint32_t time); | 376 | int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, const char *name, |
377 | int namelen, struct jffs2_inode_info *dead_f, uint32_t time); | ||
378 | int jffs2_do_link(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint32_t ino, | ||
379 | uint8_t type, const char *name, int namelen, uint32_t time); | ||
349 | 380 | ||
350 | 381 | ||
351 | /* readinode.c */ | 382 | /* readinode.c */ |
@@ -368,12 +399,19 @@ struct jffs2_raw_inode *jffs2_alloc_raw_inode(void); | |||
368 | void jffs2_free_raw_inode(struct jffs2_raw_inode *); | 399 | void jffs2_free_raw_inode(struct jffs2_raw_inode *); |
369 | struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); | 400 | struct jffs2_tmp_dnode_info *jffs2_alloc_tmp_dnode_info(void); |
370 | void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); | 401 | void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *); |
371 | struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void); | 402 | int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c, |
372 | void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *); | 403 | struct jffs2_eraseblock *jeb, int nr); |
404 | void jffs2_free_refblock(struct jffs2_raw_node_ref *); | ||
373 | struct jffs2_node_frag *jffs2_alloc_node_frag(void); | 405 | struct jffs2_node_frag *jffs2_alloc_node_frag(void); |
374 | void jffs2_free_node_frag(struct jffs2_node_frag *); | 406 | void jffs2_free_node_frag(struct jffs2_node_frag *); |
375 | struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); | 407 | struct jffs2_inode_cache *jffs2_alloc_inode_cache(void); |
376 | void jffs2_free_inode_cache(struct jffs2_inode_cache *); | 408 | void jffs2_free_inode_cache(struct jffs2_inode_cache *); |
409 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
410 | struct jffs2_xattr_datum *jffs2_alloc_xattr_datum(void); | ||
411 | void jffs2_free_xattr_datum(struct jffs2_xattr_datum *); | ||
412 | struct jffs2_xattr_ref *jffs2_alloc_xattr_ref(void); | ||
413 | void jffs2_free_xattr_ref(struct jffs2_xattr_ref *); | ||
414 | #endif | ||
377 | 415 | ||
378 | /* gc.c */ | 416 | /* gc.c */ |
379 | int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); | 417 | int jffs2_garbage_collect_pass(struct jffs2_sb_info *c); |
@@ -393,12 +431,14 @@ int jffs2_fill_scan_buf(struct jffs2_sb_info *c, void *buf, | |||
393 | uint32_t ofs, uint32_t len); | 431 | uint32_t ofs, uint32_t len); |
394 | struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); | 432 | struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uint32_t ino); |
395 | int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | 433 | int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); |
434 | int jffs2_scan_dirty_space(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, uint32_t size); | ||
396 | 435 | ||
397 | /* build.c */ | 436 | /* build.c */ |
398 | int jffs2_do_mount_fs(struct jffs2_sb_info *c); | 437 | int jffs2_do_mount_fs(struct jffs2_sb_info *c); |
399 | 438 | ||
400 | /* erase.c */ | 439 | /* erase.c */ |
401 | void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); | 440 | void jffs2_erase_pending_blocks(struct jffs2_sb_info *c, int count); |
441 | void jffs2_free_jeb_node_refs(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb); | ||
402 | 442 | ||
403 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 443 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
404 | /* wbuf.c */ | 444 | /* wbuf.c */ |
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c index 49127a1f0458..8bedfd2ff689 100644 --- a/fs/jffs2/nodemgmt.c +++ b/fs/jffs2/nodemgmt.c | |||
@@ -23,13 +23,12 @@ | |||
23 | * jffs2_reserve_space - request physical space to write nodes to flash | 23 | * jffs2_reserve_space - request physical space to write nodes to flash |
24 | * @c: superblock info | 24 | * @c: superblock info |
25 | * @minsize: Minimum acceptable size of allocation | 25 | * @minsize: Minimum acceptable size of allocation |
26 | * @ofs: Returned value of node offset | ||
27 | * @len: Returned value of allocation length | 26 | * @len: Returned value of allocation length |
28 | * @prio: Allocation type - ALLOC_{NORMAL,DELETION} | 27 | * @prio: Allocation type - ALLOC_{NORMAL,DELETION} |
29 | * | 28 | * |
30 | * Requests a block of physical space on the flash. Returns zero for success | 29 | * Requests a block of physical space on the flash. Returns zero for success |
31 | * and puts 'ofs' and 'len' into the appriopriate place, or returns -ENOSPC | 30 | * and puts 'len' into the appropriate place, or returns -ENOSPC or other |
32 | * or other error if appropriate. | 31 | * error if appropriate. Doesn't return len since that's |
33 | * | 32 | * |
34 | * If it returns zero, jffs2_reserve_space() also downs the per-filesystem | 33 | * If it returns zero, jffs2_reserve_space() also downs the per-filesystem |
35 | * allocation semaphore, to prevent more than one allocation from being | 34 | * allocation semaphore, to prevent more than one allocation from being |
@@ -40,9 +39,9 @@ | |||
40 | */ | 39 | */ |
41 | 40 | ||
42 | static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, | 41 | static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, |
43 | uint32_t *ofs, uint32_t *len, uint32_t sumsize); | 42 | uint32_t *len, uint32_t sumsize); |
44 | 43 | ||
45 | int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, | 44 | int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, |
46 | uint32_t *len, int prio, uint32_t sumsize) | 45 | uint32_t *len, int prio, uint32_t sumsize) |
47 | { | 46 | { |
48 | int ret = -EAGAIN; | 47 | int ret = -EAGAIN; |
@@ -132,19 +131,21 @@ int jffs2_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs | |||
132 | spin_lock(&c->erase_completion_lock); | 131 | spin_lock(&c->erase_completion_lock); |
133 | } | 132 | } |
134 | 133 | ||
135 | ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); | 134 | ret = jffs2_do_reserve_space(c, minsize, len, sumsize); |
136 | if (ret) { | 135 | if (ret) { |
137 | D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); | 136 | D1(printk(KERN_DEBUG "jffs2_reserve_space: ret is %d\n", ret)); |
138 | } | 137 | } |
139 | } | 138 | } |
140 | spin_unlock(&c->erase_completion_lock); | 139 | spin_unlock(&c->erase_completion_lock); |
140 | if (!ret) | ||
141 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); | ||
141 | if (ret) | 142 | if (ret) |
142 | up(&c->alloc_sem); | 143 | up(&c->alloc_sem); |
143 | return ret; | 144 | return ret; |
144 | } | 145 | } |
145 | 146 | ||
146 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, | 147 | int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, |
147 | uint32_t *len, uint32_t sumsize) | 148 | uint32_t *len, uint32_t sumsize) |
148 | { | 149 | { |
149 | int ret = -EAGAIN; | 150 | int ret = -EAGAIN; |
150 | minsize = PAD(minsize); | 151 | minsize = PAD(minsize); |
@@ -153,12 +154,15 @@ int jffs2_reserve_space_gc(struct jffs2_sb_info *c, uint32_t minsize, uint32_t * | |||
153 | 154 | ||
154 | spin_lock(&c->erase_completion_lock); | 155 | spin_lock(&c->erase_completion_lock); |
155 | while(ret == -EAGAIN) { | 156 | while(ret == -EAGAIN) { |
156 | ret = jffs2_do_reserve_space(c, minsize, ofs, len, sumsize); | 157 | ret = jffs2_do_reserve_space(c, minsize, len, sumsize); |
157 | if (ret) { | 158 | if (ret) { |
158 | D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); | 159 | D1(printk(KERN_DEBUG "jffs2_reserve_space_gc: looping, ret is %d\n", ret)); |
159 | } | 160 | } |
160 | } | 161 | } |
161 | spin_unlock(&c->erase_completion_lock); | 162 | spin_unlock(&c->erase_completion_lock); |
163 | if (!ret) | ||
164 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); | ||
165 | |||
162 | return ret; | 166 | return ret; |
163 | } | 167 | } |
164 | 168 | ||
@@ -259,10 +263,11 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c) | |||
259 | } | 263 | } |
260 | 264 | ||
261 | /* Called with alloc sem _and_ erase_completion_lock */ | 265 | /* Called with alloc sem _and_ erase_completion_lock */ |
262 | static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uint32_t *ofs, uint32_t *len, uint32_t sumsize) | 266 | static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, |
267 | uint32_t *len, uint32_t sumsize) | ||
263 | { | 268 | { |
264 | struct jffs2_eraseblock *jeb = c->nextblock; | 269 | struct jffs2_eraseblock *jeb = c->nextblock; |
265 | uint32_t reserved_size; /* for summary information at the end of the jeb */ | 270 | uint32_t reserved_size; /* for summary information at the end of the jeb */ |
266 | int ret; | 271 | int ret; |
267 | 272 | ||
268 | restart: | 273 | restart: |
@@ -312,6 +317,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
312 | } | 317 | } |
313 | } else { | 318 | } else { |
314 | if (jeb && minsize > jeb->free_size) { | 319 | if (jeb && minsize > jeb->free_size) { |
320 | uint32_t waste; | ||
321 | |||
315 | /* Skip the end of this block and file it as having some dirty space */ | 322 | /* Skip the end of this block and file it as having some dirty space */ |
316 | /* If there's a pending write to it, flush now */ | 323 | /* If there's a pending write to it, flush now */ |
317 | 324 | ||
@@ -324,10 +331,26 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
324 | goto restart; | 331 | goto restart; |
325 | } | 332 | } |
326 | 333 | ||
327 | c->wasted_size += jeb->free_size; | 334 | spin_unlock(&c->erase_completion_lock); |
328 | c->free_size -= jeb->free_size; | 335 | |
329 | jeb->wasted_size += jeb->free_size; | 336 | ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); |
330 | jeb->free_size = 0; | 337 | if (ret) |
338 | return ret; | ||
339 | /* Just lock it again and continue. Nothing much can change because | ||
340 | we hold c->alloc_sem anyway. In fact, it's not entirely clear why | ||
341 | we hold c->erase_completion_lock in the majority of this function... | ||
342 | but that's a question for another (more caffeine-rich) day. */ | ||
343 | spin_lock(&c->erase_completion_lock); | ||
344 | |||
345 | waste = jeb->free_size; | ||
346 | jffs2_link_node_ref(c, jeb, | ||
347 | (jeb->offset + c->sector_size - waste) | REF_OBSOLETE, | ||
348 | waste, NULL); | ||
349 | /* FIXME: that made it count as dirty. Convert to wasted */ | ||
350 | jeb->dirty_size -= waste; | ||
351 | c->dirty_size -= waste; | ||
352 | jeb->wasted_size += waste; | ||
353 | c->wasted_size += waste; | ||
331 | 354 | ||
332 | jffs2_close_nextblock(c, jeb); | 355 | jffs2_close_nextblock(c, jeb); |
333 | jeb = NULL; | 356 | jeb = NULL; |
@@ -349,7 +372,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
349 | } | 372 | } |
350 | /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has | 373 | /* OK, jeb (==c->nextblock) is now pointing at a block which definitely has |
351 | enough space */ | 374 | enough space */ |
352 | *ofs = jeb->offset + (c->sector_size - jeb->free_size); | ||
353 | *len = jeb->free_size - reserved_size; | 375 | *len = jeb->free_size - reserved_size; |
354 | 376 | ||
355 | if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && | 377 | if (c->cleanmarker_size && jeb->used_size == c->cleanmarker_size && |
@@ -365,7 +387,8 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
365 | spin_lock(&c->erase_completion_lock); | 387 | spin_lock(&c->erase_completion_lock); |
366 | } | 388 | } |
367 | 389 | ||
368 | D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", *len, *ofs)); | 390 | D1(printk(KERN_DEBUG "jffs2_do_reserve_space(): Giving 0x%x bytes at 0x%x\n", |
391 | *len, jeb->offset + (c->sector_size - jeb->free_size))); | ||
369 | return 0; | 392 | return 0; |
370 | } | 393 | } |
371 | 394 | ||
@@ -374,7 +397,6 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
374 | * @c: superblock info | 397 | * @c: superblock info |
375 | * @new: new node reference to add | 398 | * @new: new node reference to add |
376 | * @len: length of this physical node | 399 | * @len: length of this physical node |
377 | * @dirty: dirty flag for new node | ||
378 | * | 400 | * |
379 | * Should only be used to report nodes for which space has been allocated | 401 | * Should only be used to report nodes for which space has been allocated |
380 | * by jffs2_reserve_space. | 402 | * by jffs2_reserve_space. |
@@ -382,42 +404,30 @@ static int jffs2_do_reserve_space(struct jffs2_sb_info *c, uint32_t minsize, uin | |||
382 | * Must be called with the alloc_sem held. | 404 | * Must be called with the alloc_sem held. |
383 | */ | 405 | */ |
384 | 406 | ||
385 | int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *new) | 407 | struct jffs2_raw_node_ref *jffs2_add_physical_node_ref(struct jffs2_sb_info *c, |
408 | uint32_t ofs, uint32_t len, | ||
409 | struct jffs2_inode_cache *ic) | ||
386 | { | 410 | { |
387 | struct jffs2_eraseblock *jeb; | 411 | struct jffs2_eraseblock *jeb; |
388 | uint32_t len; | 412 | struct jffs2_raw_node_ref *new; |
389 | 413 | ||
390 | jeb = &c->blocks[new->flash_offset / c->sector_size]; | 414 | jeb = &c->blocks[ofs / c->sector_size]; |
391 | len = ref_totlen(c, jeb, new); | ||
392 | 415 | ||
393 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", ref_offset(new), ref_flags(new), len)); | 416 | D1(printk(KERN_DEBUG "jffs2_add_physical_node_ref(): Node at 0x%x(%d), size 0x%x\n", |
417 | ofs & ~3, ofs & 3, len)); | ||
394 | #if 1 | 418 | #if 1 |
395 | /* we could get some obsolete nodes after nextblock was refiled | 419 | /* Allow non-obsolete nodes only to be added at the end of c->nextblock, |
396 | in wbuf.c */ | 420 | if c->nextblock is set. Note that wbuf.c will file obsolete nodes |
397 | if ((c->nextblock || !ref_obsolete(new)) | 421 | even after refiling c->nextblock */ |
398 | &&(jeb != c->nextblock || ref_offset(new) != jeb->offset + (c->sector_size - jeb->free_size))) { | 422 | if ((c->nextblock || ((ofs & 3) != REF_OBSOLETE)) |
423 | && (jeb != c->nextblock || (ofs & ~3) != jeb->offset + (c->sector_size - jeb->free_size))) { | ||
399 | printk(KERN_WARNING "argh. node added in wrong place\n"); | 424 | printk(KERN_WARNING "argh. node added in wrong place\n"); |
400 | jffs2_free_raw_node_ref(new); | 425 | return ERR_PTR(-EINVAL); |
401 | return -EINVAL; | ||
402 | } | 426 | } |
403 | #endif | 427 | #endif |
404 | spin_lock(&c->erase_completion_lock); | 428 | spin_lock(&c->erase_completion_lock); |
405 | 429 | ||
406 | if (!jeb->first_node) | 430 | new = jffs2_link_node_ref(c, jeb, ofs, len, ic); |
407 | jeb->first_node = new; | ||
408 | if (jeb->last_node) | ||
409 | jeb->last_node->next_phys = new; | ||
410 | jeb->last_node = new; | ||
411 | |||
412 | jeb->free_size -= len; | ||
413 | c->free_size -= len; | ||
414 | if (ref_obsolete(new)) { | ||
415 | jeb->dirty_size += len; | ||
416 | c->dirty_size += len; | ||
417 | } else { | ||
418 | jeb->used_size += len; | ||
419 | c->used_size += len; | ||
420 | } | ||
421 | 431 | ||
422 | if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { | 432 | if (!jeb->free_size && !jeb->dirty_size && !ISDIRTY(jeb->wasted_size)) { |
423 | /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ | 433 | /* If it lives on the dirty_list, jffs2_reserve_space will put it there */ |
@@ -438,7 +448,7 @@ int jffs2_add_physical_node_ref(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
438 | 448 | ||
439 | spin_unlock(&c->erase_completion_lock); | 449 | spin_unlock(&c->erase_completion_lock); |
440 | 450 | ||
441 | return 0; | 451 | return new; |
442 | } | 452 | } |
443 | 453 | ||
444 | 454 | ||
@@ -470,8 +480,9 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
470 | struct jffs2_unknown_node n; | 480 | struct jffs2_unknown_node n; |
471 | int ret, addedsize; | 481 | int ret, addedsize; |
472 | size_t retlen; | 482 | size_t retlen; |
483 | uint32_t freed_len; | ||
473 | 484 | ||
474 | if(!ref) { | 485 | if(unlikely(!ref)) { |
475 | printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); | 486 | printk(KERN_NOTICE "EEEEEK. jffs2_mark_node_obsolete called with NULL node\n"); |
476 | return; | 487 | return; |
477 | } | 488 | } |
@@ -499,32 +510,34 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
499 | 510 | ||
500 | spin_lock(&c->erase_completion_lock); | 511 | spin_lock(&c->erase_completion_lock); |
501 | 512 | ||
513 | freed_len = ref_totlen(c, jeb, ref); | ||
514 | |||
502 | if (ref_flags(ref) == REF_UNCHECKED) { | 515 | if (ref_flags(ref) == REF_UNCHECKED) { |
503 | D1(if (unlikely(jeb->unchecked_size < ref_totlen(c, jeb, ref))) { | 516 | D1(if (unlikely(jeb->unchecked_size < freed_len)) { |
504 | printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", | 517 | printk(KERN_NOTICE "raw unchecked node of size 0x%08x freed from erase block %d at 0x%08x, but unchecked_size was already 0x%08x\n", |
505 | ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); | 518 | freed_len, blocknr, ref->flash_offset, jeb->used_size); |
506 | BUG(); | 519 | BUG(); |
507 | }) | 520 | }) |
508 | D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); | 521 | D1(printk(KERN_DEBUG "Obsoleting previously unchecked node at 0x%08x of len %x: ", ref_offset(ref), freed_len)); |
509 | jeb->unchecked_size -= ref_totlen(c, jeb, ref); | 522 | jeb->unchecked_size -= freed_len; |
510 | c->unchecked_size -= ref_totlen(c, jeb, ref); | 523 | c->unchecked_size -= freed_len; |
511 | } else { | 524 | } else { |
512 | D1(if (unlikely(jeb->used_size < ref_totlen(c, jeb, ref))) { | 525 | D1(if (unlikely(jeb->used_size < freed_len)) { |
513 | printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", | 526 | printk(KERN_NOTICE "raw node of size 0x%08x freed from erase block %d at 0x%08x, but used_size was already 0x%08x\n", |
514 | ref_totlen(c, jeb, ref), blocknr, ref->flash_offset, jeb->used_size); | 527 | freed_len, blocknr, ref->flash_offset, jeb->used_size); |
515 | BUG(); | 528 | BUG(); |
516 | }) | 529 | }) |
517 | D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), ref_totlen(c, jeb, ref))); | 530 | D1(printk(KERN_DEBUG "Obsoleting node at 0x%08x of len %#x: ", ref_offset(ref), freed_len)); |
518 | jeb->used_size -= ref_totlen(c, jeb, ref); | 531 | jeb->used_size -= freed_len; |
519 | c->used_size -= ref_totlen(c, jeb, ref); | 532 | c->used_size -= freed_len; |
520 | } | 533 | } |
521 | 534 | ||
522 | // Take care, that wasted size is taken into concern | 535 | // Take care, that wasted size is taken into concern |
523 | if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + ref_totlen(c, jeb, ref))) && jeb != c->nextblock) { | 536 | if ((jeb->dirty_size || ISDIRTY(jeb->wasted_size + freed_len)) && jeb != c->nextblock) { |
524 | D1(printk(KERN_DEBUG "Dirtying\n")); | 537 | D1(printk("Dirtying\n")); |
525 | addedsize = ref_totlen(c, jeb, ref); | 538 | addedsize = freed_len; |
526 | jeb->dirty_size += ref_totlen(c, jeb, ref); | 539 | jeb->dirty_size += freed_len; |
527 | c->dirty_size += ref_totlen(c, jeb, ref); | 540 | c->dirty_size += freed_len; |
528 | 541 | ||
529 | /* Convert wasted space to dirty, if not a bad block */ | 542 | /* Convert wasted space to dirty, if not a bad block */ |
530 | if (jeb->wasted_size) { | 543 | if (jeb->wasted_size) { |
@@ -543,10 +556,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
543 | } | 556 | } |
544 | } | 557 | } |
545 | } else { | 558 | } else { |
546 | D1(printk(KERN_DEBUG "Wasting\n")); | 559 | D1(printk("Wasting\n")); |
547 | addedsize = 0; | 560 | addedsize = 0; |
548 | jeb->wasted_size += ref_totlen(c, jeb, ref); | 561 | jeb->wasted_size += freed_len; |
549 | c->wasted_size += ref_totlen(c, jeb, ref); | 562 | c->wasted_size += freed_len; |
550 | } | 563 | } |
551 | ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; | 564 | ref->flash_offset = ref_offset(ref) | REF_OBSOLETE; |
552 | 565 | ||
@@ -622,7 +635,7 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
622 | /* The erase_free_sem is locked, and has been since before we marked the node obsolete | 635 | /* The erase_free_sem is locked, and has been since before we marked the node obsolete |
623 | and potentially put its eraseblock onto the erase_pending_list. Thus, we know that | 636 | and potentially put its eraseblock onto the erase_pending_list. Thus, we know that |
624 | the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet | 637 | the block hasn't _already_ been erased, and that 'ref' itself hasn't been freed yet |
625 | by jffs2_free_all_node_refs() in erase.c. Which is nice. */ | 638 | by jffs2_free_jeb_node_refs() in erase.c. Which is nice. */ |
626 | 639 | ||
627 | D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); | 640 | D1(printk(KERN_DEBUG "obliterating obsoleted node at 0x%08x\n", ref_offset(ref))); |
628 | ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); | 641 | ret = jffs2_flash_read(c, ref_offset(ref), sizeof(n), &retlen, (char *)&n); |
@@ -634,8 +647,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
634 | printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); | 647 | printk(KERN_WARNING "Short read from obsoleted node at 0x%08x: %zd\n", ref_offset(ref), retlen); |
635 | goto out_erase_sem; | 648 | goto out_erase_sem; |
636 | } | 649 | } |
637 | if (PAD(je32_to_cpu(n.totlen)) != PAD(ref_totlen(c, jeb, ref))) { | 650 | if (PAD(je32_to_cpu(n.totlen)) != PAD(freed_len)) { |
638 | printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), ref_totlen(c, jeb, ref)); | 651 | printk(KERN_WARNING "Node totlen on flash (0x%08x) != totlen from node ref (0x%08x)\n", je32_to_cpu(n.totlen), freed_len); |
639 | goto out_erase_sem; | 652 | goto out_erase_sem; |
640 | } | 653 | } |
641 | if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { | 654 | if (!(je16_to_cpu(n.nodetype) & JFFS2_NODE_ACCURATE)) { |
@@ -671,6 +684,10 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
671 | spin_lock(&c->erase_completion_lock); | 684 | spin_lock(&c->erase_completion_lock); |
672 | 685 | ||
673 | ic = jffs2_raw_ref_to_ic(ref); | 686 | ic = jffs2_raw_ref_to_ic(ref); |
687 | /* It seems we should never call jffs2_mark_node_obsolete() for | ||
688 | XATTR nodes.... yet. Make sure we notice if/when we change | ||
689 | that :) */ | ||
690 | BUG_ON(ic->class != RAWNODE_CLASS_INODE_CACHE); | ||
674 | for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) | 691 | for (p = &ic->nodes; (*p) != ref; p = &((*p)->next_in_ino)) |
675 | ; | 692 | ; |
676 | 693 | ||
@@ -683,51 +700,6 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
683 | spin_unlock(&c->erase_completion_lock); | 700 | spin_unlock(&c->erase_completion_lock); |
684 | } | 701 | } |
685 | 702 | ||
686 | |||
687 | /* Merge with the next node in the physical list, if there is one | ||
688 | and if it's also obsolete and if it doesn't belong to any inode */ | ||
689 | if (ref->next_phys && ref_obsolete(ref->next_phys) && | ||
690 | !ref->next_phys->next_in_ino) { | ||
691 | struct jffs2_raw_node_ref *n = ref->next_phys; | ||
692 | |||
693 | spin_lock(&c->erase_completion_lock); | ||
694 | |||
695 | ref->__totlen += n->__totlen; | ||
696 | ref->next_phys = n->next_phys; | ||
697 | if (jeb->last_node == n) jeb->last_node = ref; | ||
698 | if (jeb->gc_node == n) { | ||
699 | /* gc will be happy continuing gc on this node */ | ||
700 | jeb->gc_node=ref; | ||
701 | } | ||
702 | spin_unlock(&c->erase_completion_lock); | ||
703 | |||
704 | jffs2_free_raw_node_ref(n); | ||
705 | } | ||
706 | |||
707 | /* Also merge with the previous node in the list, if there is one | ||
708 | and that one is obsolete */ | ||
709 | if (ref != jeb->first_node ) { | ||
710 | struct jffs2_raw_node_ref *p = jeb->first_node; | ||
711 | |||
712 | spin_lock(&c->erase_completion_lock); | ||
713 | |||
714 | while (p->next_phys != ref) | ||
715 | p = p->next_phys; | ||
716 | |||
717 | if (ref_obsolete(p) && !ref->next_in_ino) { | ||
718 | p->__totlen += ref->__totlen; | ||
719 | if (jeb->last_node == ref) { | ||
720 | jeb->last_node = p; | ||
721 | } | ||
722 | if (jeb->gc_node == ref) { | ||
723 | /* gc will be happy continuing gc on this node */ | ||
724 | jeb->gc_node=p; | ||
725 | } | ||
726 | p->next_phys = ref->next_phys; | ||
727 | jffs2_free_raw_node_ref(ref); | ||
728 | } | ||
729 | spin_unlock(&c->erase_completion_lock); | ||
730 | } | ||
731 | out_erase_sem: | 703 | out_erase_sem: |
732 | up(&c->erase_free_sem); | 704 | up(&c->erase_free_sem); |
733 | } | 705 | } |
diff --git a/fs/jffs2/os-linux.h b/fs/jffs2/os-linux.h index d307cf548625..6b5223565405 100644 --- a/fs/jffs2/os-linux.h +++ b/fs/jffs2/os-linux.h | |||
@@ -31,9 +31,7 @@ struct kvec; | |||
31 | #define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) | 31 | #define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode) |
32 | #define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) | 32 | #define JFFS2_F_I_UID(f) (OFNI_EDONI_2SFFJ(f)->i_uid) |
33 | #define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) | 33 | #define JFFS2_F_I_GID(f) (OFNI_EDONI_2SFFJ(f)->i_gid) |
34 | 34 | #define JFFS2_F_I_RDEV(f) (OFNI_EDONI_2SFFJ(f)->i_rdev) | |
35 | #define JFFS2_F_I_RDEV_MIN(f) (iminor(OFNI_EDONI_2SFFJ(f))) | ||
36 | #define JFFS2_F_I_RDEV_MAJ(f) (imajor(OFNI_EDONI_2SFFJ(f))) | ||
37 | 35 | ||
38 | #define ITIME(sec) ((struct timespec){sec, 0}) | 36 | #define ITIME(sec) ((struct timespec){sec, 0}) |
39 | #define I_SEC(tv) ((tv).tv_sec) | 37 | #define I_SEC(tv) ((tv).tv_sec) |
@@ -60,6 +58,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
60 | f->target = NULL; | 58 | f->target = NULL; |
61 | f->flags = 0; | 59 | f->flags = 0; |
62 | f->usercompr = 0; | 60 | f->usercompr = 0; |
61 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
62 | f->i_acl_access = JFFS2_ACL_NOT_CACHED; | ||
63 | f->i_acl_default = JFFS2_ACL_NOT_CACHED; | ||
64 | #endif | ||
63 | } | 65 | } |
64 | 66 | ||
65 | 67 | ||
@@ -90,13 +92,10 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
90 | #define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) | 92 | #define jffs2_flash_writev(a,b,c,d,e,f) jffs2_flash_direct_writev(a,b,c,d,e) |
91 | #define jffs2_wbuf_timeout NULL | 93 | #define jffs2_wbuf_timeout NULL |
92 | #define jffs2_wbuf_process NULL | 94 | #define jffs2_wbuf_process NULL |
93 | #define jffs2_nor_ecc(c) (0) | ||
94 | #define jffs2_dataflash(c) (0) | 95 | #define jffs2_dataflash(c) (0) |
95 | #define jffs2_nor_wbuf_flash(c) (0) | ||
96 | #define jffs2_nor_ecc_flash_setup(c) (0) | ||
97 | #define jffs2_nor_ecc_flash_cleanup(c) do {} while (0) | ||
98 | #define jffs2_dataflash_setup(c) (0) | 96 | #define jffs2_dataflash_setup(c) (0) |
99 | #define jffs2_dataflash_cleanup(c) do {} while (0) | 97 | #define jffs2_dataflash_cleanup(c) do {} while (0) |
98 | #define jffs2_nor_wbuf_flash(c) (0) | ||
100 | #define jffs2_nor_wbuf_flash_setup(c) (0) | 99 | #define jffs2_nor_wbuf_flash_setup(c) (0) |
101 | #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0) | 100 | #define jffs2_nor_wbuf_flash_cleanup(c) do {} while (0) |
102 | 101 | ||
@@ -107,9 +106,7 @@ static inline void jffs2_init_inode_info(struct jffs2_inode_info *f) | |||
107 | #ifdef CONFIG_JFFS2_SUMMARY | 106 | #ifdef CONFIG_JFFS2_SUMMARY |
108 | #define jffs2_can_mark_obsolete(c) (0) | 107 | #define jffs2_can_mark_obsolete(c) (0) |
109 | #else | 108 | #else |
110 | #define jffs2_can_mark_obsolete(c) \ | 109 | #define jffs2_can_mark_obsolete(c) (c->mtd->flags & (MTD_BIT_WRITEABLE)) |
111 | ((c->mtd->type == MTD_NORFLASH && !(c->mtd->flags & (MTD_ECC|MTD_PROGRAM_REGIONS))) || \ | ||
112 | c->mtd->type == MTD_RAM) | ||
113 | #endif | 110 | #endif |
114 | 111 | ||
115 | #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) | 112 | #define jffs2_cleanmarker_oob(c) (c->mtd->type == MTD_NANDFLASH) |
@@ -133,15 +130,11 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c); | |||
133 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c); | 130 | int jffs2_nand_flash_setup(struct jffs2_sb_info *c); |
134 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); | 131 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c); |
135 | 132 | ||
136 | #define jffs2_nor_ecc(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_ECC)) | ||
137 | int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c); | ||
138 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c); | ||
139 | |||
140 | #define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH) | 133 | #define jffs2_dataflash(c) (c->mtd->type == MTD_DATAFLASH) |
141 | int jffs2_dataflash_setup(struct jffs2_sb_info *c); | 134 | int jffs2_dataflash_setup(struct jffs2_sb_info *c); |
142 | void jffs2_dataflash_cleanup(struct jffs2_sb_info *c); | 135 | void jffs2_dataflash_cleanup(struct jffs2_sb_info *c); |
143 | 136 | ||
144 | #define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && (c->mtd->flags & MTD_PROGRAM_REGIONS)) | 137 | #define jffs2_nor_wbuf_flash(c) (c->mtd->type == MTD_NORFLASH && ! (c->mtd->flags & MTD_BIT_WRITEABLE)) |
145 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); | 138 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c); |
146 | void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); | 139 | void jffs2_nor_wbuf_flash_cleanup(struct jffs2_sb_info *c); |
147 | 140 | ||
@@ -182,7 +175,7 @@ void jffs2_clear_inode (struct inode *); | |||
182 | void jffs2_dirty_inode(struct inode *inode); | 175 | void jffs2_dirty_inode(struct inode *inode); |
183 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, | 176 | struct inode *jffs2_new_inode (struct inode *dir_i, int mode, |
184 | struct jffs2_raw_inode *ri); | 177 | struct jffs2_raw_inode *ri); |
185 | int jffs2_statfs (struct super_block *, struct kstatfs *); | 178 | int jffs2_statfs (struct dentry *, struct kstatfs *); |
186 | void jffs2_write_super (struct super_block *); | 179 | void jffs2_write_super (struct super_block *); |
187 | int jffs2_remount_fs (struct super_block *, int *, char *); | 180 | int jffs2_remount_fs (struct super_block *, int *, char *); |
188 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); | 181 | int jffs2_do_fill_super(struct super_block *sb, void *data, int silent); |
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c index f1695642d0f7..5fec012b02ed 100644 --- a/fs/jffs2/readinode.c +++ b/fs/jffs2/readinode.c | |||
@@ -66,7 +66,7 @@ static void jffs2_free_tmp_dnode_info_list(struct rb_root *list) | |||
66 | jffs2_free_full_dnode(tn->fn); | 66 | jffs2_free_full_dnode(tn->fn); |
67 | jffs2_free_tmp_dnode_info(tn); | 67 | jffs2_free_tmp_dnode_info(tn); |
68 | 68 | ||
69 | this = this->rb_parent; | 69 | this = rb_parent(this); |
70 | if (!this) | 70 | if (!this) |
71 | break; | 71 | break; |
72 | 72 | ||
@@ -116,19 +116,42 @@ static inline int read_direntry(struct jffs2_sb_info *c, struct jffs2_raw_node_r | |||
116 | uint32_t *latest_mctime, uint32_t *mctime_ver) | 116 | uint32_t *latest_mctime, uint32_t *mctime_ver) |
117 | { | 117 | { |
118 | struct jffs2_full_dirent *fd; | 118 | struct jffs2_full_dirent *fd; |
119 | uint32_t crc; | ||
119 | 120 | ||
120 | /* The direntry nodes are checked during the flash scanning */ | ||
121 | BUG_ON(ref_flags(ref) == REF_UNCHECKED); | ||
122 | /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ | 121 | /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ |
123 | BUG_ON(ref_obsolete(ref)); | 122 | BUG_ON(ref_obsolete(ref)); |
124 | 123 | ||
125 | /* Sanity check */ | 124 | crc = crc32(0, rd, sizeof(*rd) - 8); |
126 | if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { | 125 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { |
127 | JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", | 126 | JFFS2_NOTICE("header CRC failed on dirent node at %#08x: read %#08x, calculated %#08x\n", |
128 | ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); | 127 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); |
129 | return 1; | 128 | return 1; |
130 | } | 129 | } |
131 | 130 | ||
131 | /* If we've never checked the CRCs on this node, check them now */ | ||
132 | if (ref_flags(ref) == REF_UNCHECKED) { | ||
133 | struct jffs2_eraseblock *jeb; | ||
134 | int len; | ||
135 | |||
136 | /* Sanity check */ | ||
137 | if (unlikely(PAD((rd->nsize + sizeof(*rd))) != PAD(je32_to_cpu(rd->totlen)))) { | ||
138 | JFFS2_ERROR("illegal nsize in node at %#08x: nsize %#02x, totlen %#04x\n", | ||
139 | ref_offset(ref), rd->nsize, je32_to_cpu(rd->totlen)); | ||
140 | return 1; | ||
141 | } | ||
142 | |||
143 | jeb = &c->blocks[ref->flash_offset / c->sector_size]; | ||
144 | len = ref_totlen(c, jeb, ref); | ||
145 | |||
146 | spin_lock(&c->erase_completion_lock); | ||
147 | jeb->used_size += len; | ||
148 | jeb->unchecked_size -= len; | ||
149 | c->used_size += len; | ||
150 | c->unchecked_size -= len; | ||
151 | ref->flash_offset = ref_offset(ref) | REF_PRISTINE; | ||
152 | spin_unlock(&c->erase_completion_lock); | ||
153 | } | ||
154 | |||
132 | fd = jffs2_alloc_full_dirent(rd->nsize + 1); | 155 | fd = jffs2_alloc_full_dirent(rd->nsize + 1); |
133 | if (unlikely(!fd)) | 156 | if (unlikely(!fd)) |
134 | return -ENOMEM; | 157 | return -ENOMEM; |
@@ -198,13 +221,21 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
198 | struct jffs2_tmp_dnode_info *tn; | 221 | struct jffs2_tmp_dnode_info *tn; |
199 | uint32_t len, csize; | 222 | uint32_t len, csize; |
200 | int ret = 1; | 223 | int ret = 1; |
224 | uint32_t crc; | ||
201 | 225 | ||
202 | /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ | 226 | /* Obsoleted. This cannot happen, surely? dwmw2 20020308 */ |
203 | BUG_ON(ref_obsolete(ref)); | 227 | BUG_ON(ref_obsolete(ref)); |
204 | 228 | ||
229 | crc = crc32(0, rd, sizeof(*rd) - 8); | ||
230 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { | ||
231 | JFFS2_NOTICE("node CRC failed on dnode at %#08x: read %#08x, calculated %#08x\n", | ||
232 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); | ||
233 | return 1; | ||
234 | } | ||
235 | |||
205 | tn = jffs2_alloc_tmp_dnode_info(); | 236 | tn = jffs2_alloc_tmp_dnode_info(); |
206 | if (!tn) { | 237 | if (!tn) { |
207 | JFFS2_ERROR("failed to allocate tn (%d bytes).\n", sizeof(*tn)); | 238 | JFFS2_ERROR("failed to allocate tn (%zu bytes).\n", sizeof(*tn)); |
208 | return -ENOMEM; | 239 | return -ENOMEM; |
209 | } | 240 | } |
210 | 241 | ||
@@ -213,14 +244,6 @@ static inline int read_dnode(struct jffs2_sb_info *c, struct jffs2_raw_node_ref | |||
213 | 244 | ||
214 | /* If we've never checked the CRCs on this node, check them now */ | 245 | /* If we've never checked the CRCs on this node, check them now */ |
215 | if (ref_flags(ref) == REF_UNCHECKED) { | 246 | if (ref_flags(ref) == REF_UNCHECKED) { |
216 | uint32_t crc; | ||
217 | |||
218 | crc = crc32(0, rd, sizeof(*rd) - 8); | ||
219 | if (unlikely(crc != je32_to_cpu(rd->node_crc))) { | ||
220 | JFFS2_NOTICE("header CRC failed on node at %#08x: read %#08x, calculated %#08x\n", | ||
221 | ref_offset(ref), je32_to_cpu(rd->node_crc), crc); | ||
222 | goto free_out; | ||
223 | } | ||
224 | 247 | ||
225 | /* Sanity checks */ | 248 | /* Sanity checks */ |
226 | if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || | 249 | if (unlikely(je32_to_cpu(rd->offset) > je32_to_cpu(rd->isize)) || |
@@ -343,7 +366,7 @@ free_out: | |||
343 | * Helper function for jffs2_get_inode_nodes(). | 366 | * Helper function for jffs2_get_inode_nodes(). |
344 | * It is called every time an unknown node is found. | 367 | * It is called every time an unknown node is found. |
345 | * | 368 | * |
346 | * Returns: 0 on succes; | 369 | * Returns: 0 on success; |
347 | * 1 if the node should be marked obsolete; | 370 | * 1 if the node should be marked obsolete; |
348 | * negative error code on failure. | 371 | * negative error code on failure. |
349 | */ | 372 | */ |
@@ -354,37 +377,30 @@ static inline int read_unknown(struct jffs2_sb_info *c, struct jffs2_raw_node_re | |||
354 | 377 | ||
355 | un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); | 378 | un->nodetype = cpu_to_je16(JFFS2_NODE_ACCURATE | je16_to_cpu(un->nodetype)); |
356 | 379 | ||
357 | if (crc32(0, un, sizeof(struct jffs2_unknown_node) - 4) != je32_to_cpu(un->hdr_crc)) { | 380 | switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { |
358 | /* Hmmm. This should have been caught at scan time. */ | ||
359 | JFFS2_NOTICE("node header CRC failed at %#08x. But it must have been OK earlier.\n", ref_offset(ref)); | ||
360 | jffs2_dbg_dump_node(c, ref_offset(ref)); | ||
361 | return 1; | ||
362 | } else { | ||
363 | switch(je16_to_cpu(un->nodetype) & JFFS2_COMPAT_MASK) { | ||
364 | 381 | ||
365 | case JFFS2_FEATURE_INCOMPAT: | 382 | case JFFS2_FEATURE_INCOMPAT: |
366 | JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", | 383 | JFFS2_ERROR("unknown INCOMPAT nodetype %#04X at %#08x\n", |
367 | je16_to_cpu(un->nodetype), ref_offset(ref)); | 384 | je16_to_cpu(un->nodetype), ref_offset(ref)); |
368 | /* EEP */ | 385 | /* EEP */ |
369 | BUG(); | 386 | BUG(); |
370 | break; | 387 | break; |
371 | 388 | ||
372 | case JFFS2_FEATURE_ROCOMPAT: | 389 | case JFFS2_FEATURE_ROCOMPAT: |
373 | JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", | 390 | JFFS2_ERROR("unknown ROCOMPAT nodetype %#04X at %#08x\n", |
374 | je16_to_cpu(un->nodetype), ref_offset(ref)); | 391 | je16_to_cpu(un->nodetype), ref_offset(ref)); |
375 | BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); | 392 | BUG_ON(!(c->flags & JFFS2_SB_FLAG_RO)); |
376 | break; | 393 | break; |
377 | 394 | ||
378 | case JFFS2_FEATURE_RWCOMPAT_COPY: | 395 | case JFFS2_FEATURE_RWCOMPAT_COPY: |
379 | JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", | 396 | JFFS2_NOTICE("unknown RWCOMPAT_COPY nodetype %#04X at %#08x\n", |
380 | je16_to_cpu(un->nodetype), ref_offset(ref)); | 397 | je16_to_cpu(un->nodetype), ref_offset(ref)); |
381 | break; | 398 | break; |
382 | 399 | ||
383 | case JFFS2_FEATURE_RWCOMPAT_DELETE: | 400 | case JFFS2_FEATURE_RWCOMPAT_DELETE: |
384 | JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", | 401 | JFFS2_NOTICE("unknown RWCOMPAT_DELETE nodetype %#04X at %#08x\n", |
385 | je16_to_cpu(un->nodetype), ref_offset(ref)); | 402 | je16_to_cpu(un->nodetype), ref_offset(ref)); |
386 | return 1; | 403 | return 1; |
387 | } | ||
388 | } | 404 | } |
389 | 405 | ||
390 | return 0; | 406 | return 0; |
@@ -434,7 +450,7 @@ static int read_more(struct jffs2_sb_info *c, struct jffs2_raw_node_ref *ref, | |||
434 | } | 450 | } |
435 | 451 | ||
436 | if (retlen < len) { | 452 | if (retlen < len) { |
437 | JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", | 453 | JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", |
438 | offs, retlen, len); | 454 | offs, retlen, len); |
439 | return -EIO; | 455 | return -EIO; |
440 | } | 456 | } |
@@ -542,13 +558,25 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
542 | } | 558 | } |
543 | 559 | ||
544 | if (retlen < len) { | 560 | if (retlen < len) { |
545 | JFFS2_ERROR("short read at %#08x: %d instead of %d.\n", ref_offset(ref), retlen, len); | 561 | JFFS2_ERROR("short read at %#08x: %zu instead of %d.\n", ref_offset(ref), retlen, len); |
546 | err = -EIO; | 562 | err = -EIO; |
547 | goto free_out; | 563 | goto free_out; |
548 | } | 564 | } |
549 | 565 | ||
550 | node = (union jffs2_node_union *)bufstart; | 566 | node = (union jffs2_node_union *)bufstart; |
551 | 567 | ||
568 | /* No need to mask in the valid bit; it shouldn't be invalid */ | ||
569 | if (je32_to_cpu(node->u.hdr_crc) != crc32(0, node, sizeof(node->u)-4)) { | ||
570 | JFFS2_NOTICE("Node header CRC failed at %#08x. {%04x,%04x,%08x,%08x}\n", | ||
571 | ref_offset(ref), je16_to_cpu(node->u.magic), | ||
572 | je16_to_cpu(node->u.nodetype), | ||
573 | je32_to_cpu(node->u.totlen), | ||
574 | je32_to_cpu(node->u.hdr_crc)); | ||
575 | jffs2_dbg_dump_node(c, ref_offset(ref)); | ||
576 | jffs2_mark_node_obsolete(c, ref); | ||
577 | goto cont; | ||
578 | } | ||
579 | |||
552 | switch (je16_to_cpu(node->u.nodetype)) { | 580 | switch (je16_to_cpu(node->u.nodetype)) { |
553 | 581 | ||
554 | case JFFS2_NODETYPE_DIRENT: | 582 | case JFFS2_NODETYPE_DIRENT: |
@@ -606,6 +634,7 @@ static int jffs2_get_inode_nodes(struct jffs2_sb_info *c, struct jffs2_inode_inf | |||
606 | goto free_out; | 634 | goto free_out; |
607 | 635 | ||
608 | } | 636 | } |
637 | cont: | ||
609 | spin_lock(&c->erase_completion_lock); | 638 | spin_lock(&c->erase_completion_lock); |
610 | } | 639 | } |
611 | 640 | ||
@@ -679,12 +708,12 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
679 | jffs2_mark_node_obsolete(c, fn->raw); | 708 | jffs2_mark_node_obsolete(c, fn->raw); |
680 | 709 | ||
681 | BUG_ON(rb->rb_left); | 710 | BUG_ON(rb->rb_left); |
682 | if (rb->rb_parent && rb->rb_parent->rb_left == rb) { | 711 | if (rb_parent(rb) && rb_parent(rb)->rb_left == rb) { |
683 | /* We were then left-hand child of our parent. We need | 712 | /* We were then left-hand child of our parent. We need |
684 | * to move our own right-hand child into our place. */ | 713 | * to move our own right-hand child into our place. */ |
685 | repl_rb = rb->rb_right; | 714 | repl_rb = rb->rb_right; |
686 | if (repl_rb) | 715 | if (repl_rb) |
687 | repl_rb->rb_parent = rb->rb_parent; | 716 | rb_set_parent(repl_rb, rb_parent(rb)); |
688 | } else | 717 | } else |
689 | repl_rb = NULL; | 718 | repl_rb = NULL; |
690 | 719 | ||
@@ -692,14 +721,14 @@ static int jffs2_do_read_inode_internal(struct jffs2_sb_info *c, | |||
692 | 721 | ||
693 | /* Remove the spent tn from the tree; don't bother rebalancing | 722 | /* Remove the spent tn from the tree; don't bother rebalancing |
694 | * but put our right-hand child in our own place. */ | 723 | * but put our right-hand child in our own place. */ |
695 | if (tn->rb.rb_parent) { | 724 | if (rb_parent(&tn->rb)) { |
696 | if (tn->rb.rb_parent->rb_left == &tn->rb) | 725 | if (rb_parent(&tn->rb)->rb_left == &tn->rb) |
697 | tn->rb.rb_parent->rb_left = repl_rb; | 726 | rb_parent(&tn->rb)->rb_left = repl_rb; |
698 | else if (tn->rb.rb_parent->rb_right == &tn->rb) | 727 | else if (rb_parent(&tn->rb)->rb_right == &tn->rb) |
699 | tn->rb.rb_parent->rb_right = repl_rb; | 728 | rb_parent(&tn->rb)->rb_right = repl_rb; |
700 | else BUG(); | 729 | else BUG(); |
701 | } else if (tn->rb.rb_right) | 730 | } else if (tn->rb.rb_right) |
702 | tn->rb.rb_right->rb_parent = NULL; | 731 | rb_set_parent(tn->rb.rb_right, NULL); |
703 | 732 | ||
704 | jffs2_free_tmp_dnode_info(tn); | 733 | jffs2_free_tmp_dnode_info(tn); |
705 | if (ret) { | 734 | if (ret) { |
diff --git a/fs/jffs2/scan.c b/fs/jffs2/scan.c index cf55b221fc2b..61618080b86f 100644 --- a/fs/jffs2/scan.c +++ b/fs/jffs2/scan.c | |||
@@ -65,6 +65,28 @@ static inline uint32_t EMPTY_SCAN_SIZE(uint32_t sector_size) { | |||
65 | return DEFAULT_EMPTY_SCAN_SIZE; | 65 | return DEFAULT_EMPTY_SCAN_SIZE; |
66 | } | 66 | } |
67 | 67 | ||
68 | static int file_dirty(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | ||
69 | { | ||
70 | int ret; | ||
71 | |||
72 | if ((ret = jffs2_prealloc_raw_node_refs(c, jeb, 1))) | ||
73 | return ret; | ||
74 | if ((ret = jffs2_scan_dirty_space(c, jeb, jeb->free_size))) | ||
75 | return ret; | ||
76 | /* Turned wasted size into dirty, since we apparently | ||
77 | think it's recoverable now. */ | ||
78 | jeb->dirty_size += jeb->wasted_size; | ||
79 | c->dirty_size += jeb->wasted_size; | ||
80 | c->wasted_size -= jeb->wasted_size; | ||
81 | jeb->wasted_size = 0; | ||
82 | if (VERYDIRTY(c, jeb->dirty_size)) { | ||
83 | list_add(&jeb->list, &c->very_dirty_list); | ||
84 | } else { | ||
85 | list_add(&jeb->list, &c->dirty_list); | ||
86 | } | ||
87 | return 0; | ||
88 | } | ||
89 | |||
68 | int jffs2_scan_medium(struct jffs2_sb_info *c) | 90 | int jffs2_scan_medium(struct jffs2_sb_info *c) |
69 | { | 91 | { |
70 | int i, ret; | 92 | int i, ret; |
@@ -170,34 +192,20 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
170 | (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { | 192 | (!c->nextblock || c->nextblock->free_size < jeb->free_size)) { |
171 | /* Better candidate for the next writes to go to */ | 193 | /* Better candidate for the next writes to go to */ |
172 | if (c->nextblock) { | 194 | if (c->nextblock) { |
173 | c->nextblock->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; | 195 | ret = file_dirty(c, c->nextblock); |
174 | c->dirty_size += c->nextblock->free_size + c->nextblock->wasted_size; | 196 | if (ret) |
175 | c->free_size -= c->nextblock->free_size; | 197 | return ret; |
176 | c->wasted_size -= c->nextblock->wasted_size; | ||
177 | c->nextblock->free_size = c->nextblock->wasted_size = 0; | ||
178 | if (VERYDIRTY(c, c->nextblock->dirty_size)) { | ||
179 | list_add(&c->nextblock->list, &c->very_dirty_list); | ||
180 | } else { | ||
181 | list_add(&c->nextblock->list, &c->dirty_list); | ||
182 | } | ||
183 | /* deleting summary information of the old nextblock */ | 198 | /* deleting summary information of the old nextblock */ |
184 | jffs2_sum_reset_collected(c->summary); | 199 | jffs2_sum_reset_collected(c->summary); |
185 | } | 200 | } |
186 | /* update collected summary infromation for the current nextblock */ | 201 | /* update collected summary information for the current nextblock */ |
187 | jffs2_sum_move_collected(c, s); | 202 | jffs2_sum_move_collected(c, s); |
188 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); | 203 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): new nextblock = 0x%08x\n", jeb->offset)); |
189 | c->nextblock = jeb; | 204 | c->nextblock = jeb; |
190 | } else { | 205 | } else { |
191 | jeb->dirty_size += jeb->free_size + jeb->wasted_size; | 206 | ret = file_dirty(c, jeb); |
192 | c->dirty_size += jeb->free_size + jeb->wasted_size; | 207 | if (ret) |
193 | c->free_size -= jeb->free_size; | 208 | return ret; |
194 | c->wasted_size -= jeb->wasted_size; | ||
195 | jeb->free_size = jeb->wasted_size = 0; | ||
196 | if (VERYDIRTY(c, jeb->dirty_size)) { | ||
197 | list_add(&jeb->list, &c->very_dirty_list); | ||
198 | } else { | ||
199 | list_add(&jeb->list, &c->dirty_list); | ||
200 | } | ||
201 | } | 209 | } |
202 | break; | 210 | break; |
203 | 211 | ||
@@ -222,9 +230,6 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
222 | } | 230 | } |
223 | } | 231 | } |
224 | 232 | ||
225 | if (jffs2_sum_active() && s) | ||
226 | kfree(s); | ||
227 | |||
228 | /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ | 233 | /* Nextblock dirty is always seen as wasted, because we cannot recycle it now */ |
229 | if (c->nextblock && (c->nextblock->dirty_size)) { | 234 | if (c->nextblock && (c->nextblock->dirty_size)) { |
230 | c->nextblock->wasted_size += c->nextblock->dirty_size; | 235 | c->nextblock->wasted_size += c->nextblock->dirty_size; |
@@ -242,11 +247,8 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
242 | 247 | ||
243 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", | 248 | D1(printk(KERN_DEBUG "jffs2_scan_medium(): Skipping %d bytes in nextblock to ensure page alignment\n", |
244 | skip)); | 249 | skip)); |
245 | c->nextblock->wasted_size += skip; | 250 | jffs2_prealloc_raw_node_refs(c, c->nextblock, 1); |
246 | c->wasted_size += skip; | 251 | jffs2_scan_dirty_space(c, c->nextblock, skip); |
247 | |||
248 | c->nextblock->free_size -= skip; | ||
249 | c->free_size -= skip; | ||
250 | } | 252 | } |
251 | #endif | 253 | #endif |
252 | if (c->nr_erasing_blocks) { | 254 | if (c->nr_erasing_blocks) { |
@@ -266,6 +268,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c) | |||
266 | else | 268 | else |
267 | c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); | 269 | c->mtd->unpoint(c->mtd, flashbuf, 0, c->mtd->size); |
268 | #endif | 270 | #endif |
271 | if (s) | ||
272 | kfree(s); | ||
273 | |||
269 | return ret; | 274 | return ret; |
270 | } | 275 | } |
271 | 276 | ||
@@ -290,7 +295,7 @@ int jffs2_fill_scan_buf (struct jffs2_sb_info *c, void *buf, | |||
290 | int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 295 | int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) |
291 | { | 296 | { |
292 | if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size | 297 | if ((jeb->used_size + jeb->unchecked_size) == PAD(c->cleanmarker_size) && !jeb->dirty_size |
293 | && (!jeb->first_node || !jeb->first_node->next_phys) ) | 298 | && (!jeb->first_node || !ref_next(jeb->first_node)) ) |
294 | return BLK_STATE_CLEANMARKER; | 299 | return BLK_STATE_CLEANMARKER; |
295 | 300 | ||
296 | /* move blocks with max 4 byte dirty space to cleanlist */ | 301 | /* move blocks with max 4 byte dirty space to cleanlist */ |
@@ -306,11 +311,119 @@ int jffs2_scan_classify_jeb(struct jffs2_sb_info *c, struct jffs2_eraseblock *je | |||
306 | return BLK_STATE_ALLDIRTY; | 311 | return BLK_STATE_ALLDIRTY; |
307 | } | 312 | } |
308 | 313 | ||
314 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
315 | static int jffs2_scan_xattr_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
316 | struct jffs2_raw_xattr *rx, uint32_t ofs, | ||
317 | struct jffs2_summary *s) | ||
318 | { | ||
319 | struct jffs2_xattr_datum *xd; | ||
320 | uint32_t totlen, crc; | ||
321 | int err; | ||
322 | |||
323 | crc = crc32(0, rx, sizeof(struct jffs2_raw_xattr) - 4); | ||
324 | if (crc != je32_to_cpu(rx->node_crc)) { | ||
325 | if (je32_to_cpu(rx->node_crc) != 0xffffffff) | ||
326 | JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
327 | ofs, je32_to_cpu(rx->node_crc), crc); | ||
328 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) | ||
329 | return err; | ||
330 | return 0; | ||
331 | } | ||
332 | |||
333 | totlen = PAD(sizeof(*rx) + rx->name_len + 1 + je16_to_cpu(rx->value_len)); | ||
334 | if (totlen != je32_to_cpu(rx->totlen)) { | ||
335 | JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%u\n", | ||
336 | ofs, je32_to_cpu(rx->totlen), totlen); | ||
337 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rx->totlen)))) | ||
338 | return err; | ||
339 | return 0; | ||
340 | } | ||
341 | |||
342 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(rx->xid), je32_to_cpu(rx->version)); | ||
343 | if (IS_ERR(xd)) { | ||
344 | if (PTR_ERR(xd) == -EEXIST) { | ||
345 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rx->totlen))))) | ||
346 | return err; | ||
347 | return 0; | ||
348 | } | ||
349 | return PTR_ERR(xd); | ||
350 | } | ||
351 | xd->xprefix = rx->xprefix; | ||
352 | xd->name_len = rx->name_len; | ||
353 | xd->value_len = je16_to_cpu(rx->value_len); | ||
354 | xd->data_crc = je32_to_cpu(rx->data_crc); | ||
355 | |||
356 | xd->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, totlen, NULL); | ||
357 | /* FIXME */ xd->node->next_in_ino = (void *)xd; | ||
358 | |||
359 | if (jffs2_sum_active()) | ||
360 | jffs2_sum_add_xattr_mem(s, rx, ofs - jeb->offset); | ||
361 | dbg_xattr("scaning xdatum at %#08x (xid=%u, version=%u)\n", | ||
362 | ofs, xd->xid, xd->version); | ||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static int jffs2_scan_xref_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | ||
367 | struct jffs2_raw_xref *rr, uint32_t ofs, | ||
368 | struct jffs2_summary *s) | ||
369 | { | ||
370 | struct jffs2_xattr_ref *ref; | ||
371 | uint32_t crc; | ||
372 | int err; | ||
373 | |||
374 | crc = crc32(0, rr, sizeof(*rr) - 4); | ||
375 | if (crc != je32_to_cpu(rr->node_crc)) { | ||
376 | if (je32_to_cpu(rr->node_crc) != 0xffffffff) | ||
377 | JFFS2_WARNING("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
378 | ofs, je32_to_cpu(rr->node_crc), crc); | ||
379 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rr->totlen))))) | ||
380 | return err; | ||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | if (PAD(sizeof(struct jffs2_raw_xref)) != je32_to_cpu(rr->totlen)) { | ||
385 | JFFS2_WARNING("node length mismatch at %#08x, read=%u, calc=%zd\n", | ||
386 | ofs, je32_to_cpu(rr->totlen), | ||
387 | PAD(sizeof(struct jffs2_raw_xref))); | ||
388 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(rr->totlen)))) | ||
389 | return err; | ||
390 | return 0; | ||
391 | } | ||
392 | |||
393 | ref = jffs2_alloc_xattr_ref(); | ||
394 | if (!ref) | ||
395 | return -ENOMEM; | ||
396 | |||
397 | /* BEFORE jffs2_build_xattr_subsystem() called, | ||
398 | * ref->xid is used to store 32bit xid, xd is not used | ||
399 | * ref->ino is used to store 32bit inode-number, ic is not used | ||
400 | * Thoes variables are declared as union, thus using those | ||
401 | * are exclusive. In a similar way, ref->next is temporarily | ||
402 | * used to chain all xattr_ref object. It's re-chained to | ||
403 | * jffs2_inode_cache in jffs2_build_xattr_subsystem() correctly. | ||
404 | */ | ||
405 | ref->ino = je32_to_cpu(rr->ino); | ||
406 | ref->xid = je32_to_cpu(rr->xid); | ||
407 | ref->next = c->xref_temp; | ||
408 | c->xref_temp = ref; | ||
409 | |||
410 | ref->node = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rr->totlen)), NULL); | ||
411 | /* FIXME */ ref->node->next_in_ino = (void *)ref; | ||
412 | |||
413 | if (jffs2_sum_active()) | ||
414 | jffs2_sum_add_xref_mem(s, rr, ofs - jeb->offset); | ||
415 | dbg_xattr("scan xref at %#08x (xid=%u, ino=%u)\n", | ||
416 | ofs, ref->xid, ref->ino); | ||
417 | return 0; | ||
418 | } | ||
419 | #endif | ||
420 | |||
421 | /* Called with 'buf_size == 0' if buf is in fact a pointer _directly_ into | ||
422 | the flash, XIP-style */ | ||
309 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 423 | static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
310 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { | 424 | unsigned char *buf, uint32_t buf_size, struct jffs2_summary *s) { |
311 | struct jffs2_unknown_node *node; | 425 | struct jffs2_unknown_node *node; |
312 | struct jffs2_unknown_node crcnode; | 426 | struct jffs2_unknown_node crcnode; |
313 | struct jffs2_sum_marker *sm; | ||
314 | uint32_t ofs, prevofs; | 427 | uint32_t ofs, prevofs; |
315 | uint32_t hdr_crc, buf_ofs, buf_len; | 428 | uint32_t hdr_crc, buf_ofs, buf_len; |
316 | int err; | 429 | int err; |
@@ -344,44 +457,75 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
344 | #endif | 457 | #endif |
345 | 458 | ||
346 | if (jffs2_sum_active()) { | 459 | if (jffs2_sum_active()) { |
347 | sm = kmalloc(sizeof(struct jffs2_sum_marker), GFP_KERNEL); | 460 | struct jffs2_sum_marker *sm; |
348 | if (!sm) { | 461 | void *sumptr = NULL; |
349 | return -ENOMEM; | 462 | uint32_t sumlen; |
350 | } | 463 | |
351 | 464 | if (!buf_size) { | |
352 | err = jffs2_fill_scan_buf(c, (unsigned char *) sm, jeb->offset + c->sector_size - | 465 | /* XIP case. Just look, point at the summary if it's there */ |
353 | sizeof(struct jffs2_sum_marker), sizeof(struct jffs2_sum_marker)); | 466 | sm = (void *)buf + c->sector_size - sizeof(*sm); |
354 | if (err) { | 467 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { |
355 | kfree(sm); | 468 | sumptr = buf + je32_to_cpu(sm->offset); |
356 | return err; | 469 | sumlen = c->sector_size - je32_to_cpu(sm->offset); |
357 | } | 470 | } |
358 | 471 | } else { | |
359 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC ) { | 472 | /* If NAND flash, read a whole page of it. Else just the end */ |
360 | err = jffs2_sum_scan_sumnode(c, jeb, je32_to_cpu(sm->offset), &pseudo_random); | 473 | if (c->wbuf_pagesize) |
361 | if (err) { | 474 | buf_len = c->wbuf_pagesize; |
362 | kfree(sm); | 475 | else |
476 | buf_len = sizeof(*sm); | ||
477 | |||
478 | /* Read as much as we want into the _end_ of the preallocated buffer */ | ||
479 | err = jffs2_fill_scan_buf(c, buf + buf_size - buf_len, | ||
480 | jeb->offset + c->sector_size - buf_len, | ||
481 | buf_len); | ||
482 | if (err) | ||
363 | return err; | 483 | return err; |
484 | |||
485 | sm = (void *)buf + buf_size - sizeof(*sm); | ||
486 | if (je32_to_cpu(sm->magic) == JFFS2_SUM_MAGIC) { | ||
487 | sumlen = c->sector_size - je32_to_cpu(sm->offset); | ||
488 | sumptr = buf + buf_size - sumlen; | ||
489 | |||
490 | /* Now, make sure the summary itself is available */ | ||
491 | if (sumlen > buf_size) { | ||
492 | /* Need to kmalloc for this. */ | ||
493 | sumptr = kmalloc(sumlen, GFP_KERNEL); | ||
494 | if (!sumptr) | ||
495 | return -ENOMEM; | ||
496 | memcpy(sumptr + sumlen - buf_len, buf + buf_size - buf_len, buf_len); | ||
497 | } | ||
498 | if (buf_len < sumlen) { | ||
499 | /* Need to read more so that the entire summary node is present */ | ||
500 | err = jffs2_fill_scan_buf(c, sumptr, | ||
501 | jeb->offset + c->sector_size - sumlen, | ||
502 | sumlen - buf_len); | ||
503 | if (err) | ||
504 | return err; | ||
505 | } | ||
364 | } | 506 | } |
507 | |||
365 | } | 508 | } |
366 | 509 | ||
367 | kfree(sm); | 510 | if (sumptr) { |
511 | err = jffs2_sum_scan_sumnode(c, jeb, sumptr, sumlen, &pseudo_random); | ||
368 | 512 | ||
369 | ofs = jeb->offset; | 513 | if (buf_size && sumlen > buf_size) |
370 | prevofs = jeb->offset - 1; | 514 | kfree(sumptr); |
515 | /* If it returns with a real error, bail. | ||
516 | If it returns positive, that's a block classification | ||
517 | (i.e. BLK_STATE_xxx) so return that too. | ||
518 | If it returns zero, fall through to full scan. */ | ||
519 | if (err) | ||
520 | return err; | ||
521 | } | ||
371 | } | 522 | } |
372 | 523 | ||
373 | buf_ofs = jeb->offset; | 524 | buf_ofs = jeb->offset; |
374 | 525 | ||
375 | if (!buf_size) { | 526 | if (!buf_size) { |
527 | /* This is the XIP case -- we're reading _directly_ from the flash chip */ | ||
376 | buf_len = c->sector_size; | 528 | buf_len = c->sector_size; |
377 | |||
378 | if (jffs2_sum_active()) { | ||
379 | /* must reread because of summary test */ | ||
380 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); | ||
381 | if (err) | ||
382 | return err; | ||
383 | } | ||
384 | |||
385 | } else { | 529 | } else { |
386 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); | 530 | buf_len = EMPTY_SCAN_SIZE(c->sector_size); |
387 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); | 531 | err = jffs2_fill_scan_buf(c, buf, buf_ofs, buf_len); |
@@ -418,7 +562,10 @@ static int jffs2_scan_eraseblock (struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
418 | if (ofs) { | 562 | if (ofs) { |
419 | D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, | 563 | D1(printk(KERN_DEBUG "Free space at %08x ends at %08x\n", jeb->offset, |
420 | jeb->offset + ofs)); | 564 | jeb->offset + ofs)); |
421 | DIRTY_SPACE(ofs); | 565 | if ((err = jffs2_prealloc_raw_node_refs(c, jeb, 1))) |
566 | return err; | ||
567 | if ((err = jffs2_scan_dirty_space(c, jeb, ofs))) | ||
568 | return err; | ||
422 | } | 569 | } |
423 | 570 | ||
424 | /* Now ofs is a complete physical flash offset as it always was... */ | 571 | /* Now ofs is a complete physical flash offset as it always was... */ |
@@ -433,6 +580,11 @@ scan_more: | |||
433 | 580 | ||
434 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | 581 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); |
435 | 582 | ||
583 | /* Make sure there are node refs available for use */ | ||
584 | err = jffs2_prealloc_raw_node_refs(c, jeb, 2); | ||
585 | if (err) | ||
586 | return err; | ||
587 | |||
436 | cond_resched(); | 588 | cond_resched(); |
437 | 589 | ||
438 | if (ofs & 3) { | 590 | if (ofs & 3) { |
@@ -442,7 +594,8 @@ scan_more: | |||
442 | } | 594 | } |
443 | if (ofs == prevofs) { | 595 | if (ofs == prevofs) { |
444 | printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs); | 596 | printk(KERN_WARNING "ofs 0x%08x has already been seen. Skipping\n", ofs); |
445 | DIRTY_SPACE(4); | 597 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
598 | return err; | ||
446 | ofs += 4; | 599 | ofs += 4; |
447 | continue; | 600 | continue; |
448 | } | 601 | } |
@@ -451,7 +604,8 @@ scan_more: | |||
451 | if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { | 604 | if (jeb->offset + c->sector_size < ofs + sizeof(*node)) { |
452 | D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), | 605 | D1(printk(KERN_DEBUG "Fewer than %zd bytes left to end of block. (%x+%x<%x+%zx) Not reading\n", sizeof(struct jffs2_unknown_node), |
453 | jeb->offset, c->sector_size, ofs, sizeof(*node))); | 606 | jeb->offset, c->sector_size, ofs, sizeof(*node))); |
454 | DIRTY_SPACE((jeb->offset + c->sector_size)-ofs); | 607 | if ((err = jffs2_scan_dirty_space(c, jeb, (jeb->offset + c->sector_size)-ofs))) |
608 | return err; | ||
455 | break; | 609 | break; |
456 | } | 610 | } |
457 | 611 | ||
@@ -481,7 +635,8 @@ scan_more: | |||
481 | if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { | 635 | if (*(uint32_t *)(&buf[inbuf_ofs]) != 0xffffffff) { |
482 | printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", | 636 | printk(KERN_WARNING "Empty flash at 0x%08x ends at 0x%08x\n", |
483 | empty_start, ofs); | 637 | empty_start, ofs); |
484 | DIRTY_SPACE(ofs-empty_start); | 638 | if ((err = jffs2_scan_dirty_space(c, jeb, ofs-empty_start))) |
639 | return err; | ||
485 | goto scan_more; | 640 | goto scan_more; |
486 | } | 641 | } |
487 | 642 | ||
@@ -494,7 +649,7 @@ scan_more: | |||
494 | /* If we're only checking the beginning of a block with a cleanmarker, | 649 | /* If we're only checking the beginning of a block with a cleanmarker, |
495 | bail now */ | 650 | bail now */ |
496 | if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && | 651 | if (buf_ofs == jeb->offset && jeb->used_size == PAD(c->cleanmarker_size) && |
497 | c->cleanmarker_size && !jeb->dirty_size && !jeb->first_node->next_phys) { | 652 | c->cleanmarker_size && !jeb->dirty_size && !ref_next(jeb->first_node)) { |
498 | D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); | 653 | D1(printk(KERN_DEBUG "%d bytes at start of block seems clean... assuming all clean\n", EMPTY_SCAN_SIZE(c->sector_size))); |
499 | return BLK_STATE_CLEANMARKER; | 654 | return BLK_STATE_CLEANMARKER; |
500 | } | 655 | } |
@@ -518,20 +673,23 @@ scan_more: | |||
518 | 673 | ||
519 | if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { | 674 | if (ofs == jeb->offset && je16_to_cpu(node->magic) == KSAMTIB_CIGAM_2SFFJ) { |
520 | printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); | 675 | printk(KERN_WARNING "Magic bitmask is backwards at offset 0x%08x. Wrong endian filesystem?\n", ofs); |
521 | DIRTY_SPACE(4); | 676 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
677 | return err; | ||
522 | ofs += 4; | 678 | ofs += 4; |
523 | continue; | 679 | continue; |
524 | } | 680 | } |
525 | if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { | 681 | if (je16_to_cpu(node->magic) == JFFS2_DIRTY_BITMASK) { |
526 | D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); | 682 | D1(printk(KERN_DEBUG "Dirty bitmask at 0x%08x\n", ofs)); |
527 | DIRTY_SPACE(4); | 683 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
684 | return err; | ||
528 | ofs += 4; | 685 | ofs += 4; |
529 | continue; | 686 | continue; |
530 | } | 687 | } |
531 | if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { | 688 | if (je16_to_cpu(node->magic) == JFFS2_OLD_MAGIC_BITMASK) { |
532 | printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); | 689 | printk(KERN_WARNING "Old JFFS2 bitmask found at 0x%08x\n", ofs); |
533 | printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); | 690 | printk(KERN_WARNING "You cannot use older JFFS2 filesystems with newer kernels\n"); |
534 | DIRTY_SPACE(4); | 691 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
692 | return err; | ||
535 | ofs += 4; | 693 | ofs += 4; |
536 | continue; | 694 | continue; |
537 | } | 695 | } |
@@ -540,7 +698,8 @@ scan_more: | |||
540 | noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", | 698 | noisy_printk(&noise, "jffs2_scan_eraseblock(): Magic bitmask 0x%04x not found at 0x%08x: 0x%04x instead\n", |
541 | JFFS2_MAGIC_BITMASK, ofs, | 699 | JFFS2_MAGIC_BITMASK, ofs, |
542 | je16_to_cpu(node->magic)); | 700 | je16_to_cpu(node->magic)); |
543 | DIRTY_SPACE(4); | 701 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
702 | return err; | ||
544 | ofs += 4; | 703 | ofs += 4; |
545 | continue; | 704 | continue; |
546 | } | 705 | } |
@@ -557,7 +716,8 @@ scan_more: | |||
557 | je32_to_cpu(node->totlen), | 716 | je32_to_cpu(node->totlen), |
558 | je32_to_cpu(node->hdr_crc), | 717 | je32_to_cpu(node->hdr_crc), |
559 | hdr_crc); | 718 | hdr_crc); |
560 | DIRTY_SPACE(4); | 719 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
720 | return err; | ||
561 | ofs += 4; | 721 | ofs += 4; |
562 | continue; | 722 | continue; |
563 | } | 723 | } |
@@ -568,7 +728,8 @@ scan_more: | |||
568 | printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", | 728 | printk(KERN_WARNING "Node at 0x%08x with length 0x%08x would run over the end of the erase block\n", |
569 | ofs, je32_to_cpu(node->totlen)); | 729 | ofs, je32_to_cpu(node->totlen)); |
570 | printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); | 730 | printk(KERN_WARNING "Perhaps the file system was created with the wrong erase size?\n"); |
571 | DIRTY_SPACE(4); | 731 | if ((err = jffs2_scan_dirty_space(c, jeb, 4))) |
732 | return err; | ||
572 | ofs += 4; | 733 | ofs += 4; |
573 | continue; | 734 | continue; |
574 | } | 735 | } |
@@ -576,7 +737,8 @@ scan_more: | |||
576 | if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { | 737 | if (!(je16_to_cpu(node->nodetype) & JFFS2_NODE_ACCURATE)) { |
577 | /* Wheee. This is an obsoleted node */ | 738 | /* Wheee. This is an obsoleted node */ |
578 | D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); | 739 | D2(printk(KERN_DEBUG "Node at 0x%08x is obsolete. Skipping\n", ofs)); |
579 | DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); | 740 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) |
741 | return err; | ||
580 | ofs += PAD(je32_to_cpu(node->totlen)); | 742 | ofs += PAD(je32_to_cpu(node->totlen)); |
581 | continue; | 743 | continue; |
582 | } | 744 | } |
@@ -614,30 +776,59 @@ scan_more: | |||
614 | ofs += PAD(je32_to_cpu(node->totlen)); | 776 | ofs += PAD(je32_to_cpu(node->totlen)); |
615 | break; | 777 | break; |
616 | 778 | ||
779 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
780 | case JFFS2_NODETYPE_XATTR: | ||
781 | if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { | ||
782 | buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); | ||
783 | D1(printk(KERN_DEBUG "Fewer than %d bytes (xattr node)" | ||
784 | " left to end of buf. Reading 0x%x at 0x%08x\n", | ||
785 | je32_to_cpu(node->totlen), buf_len, ofs)); | ||
786 | err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); | ||
787 | if (err) | ||
788 | return err; | ||
789 | buf_ofs = ofs; | ||
790 | node = (void *)buf; | ||
791 | } | ||
792 | err = jffs2_scan_xattr_node(c, jeb, (void *)node, ofs, s); | ||
793 | if (err) | ||
794 | return err; | ||
795 | ofs += PAD(je32_to_cpu(node->totlen)); | ||
796 | break; | ||
797 | case JFFS2_NODETYPE_XREF: | ||
798 | if (buf_ofs + buf_len < ofs + je32_to_cpu(node->totlen)) { | ||
799 | buf_len = min_t(uint32_t, buf_size, jeb->offset + c->sector_size - ofs); | ||
800 | D1(printk(KERN_DEBUG "Fewer than %d bytes (xref node)" | ||
801 | " left to end of buf. Reading 0x%x at 0x%08x\n", | ||
802 | je32_to_cpu(node->totlen), buf_len, ofs)); | ||
803 | err = jffs2_fill_scan_buf(c, buf, ofs, buf_len); | ||
804 | if (err) | ||
805 | return err; | ||
806 | buf_ofs = ofs; | ||
807 | node = (void *)buf; | ||
808 | } | ||
809 | err = jffs2_scan_xref_node(c, jeb, (void *)node, ofs, s); | ||
810 | if (err) | ||
811 | return err; | ||
812 | ofs += PAD(je32_to_cpu(node->totlen)); | ||
813 | break; | ||
814 | #endif /* CONFIG_JFFS2_FS_XATTR */ | ||
815 | |||
617 | case JFFS2_NODETYPE_CLEANMARKER: | 816 | case JFFS2_NODETYPE_CLEANMARKER: |
618 | D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); | 817 | D1(printk(KERN_DEBUG "CLEANMARKER node found at 0x%08x\n", ofs)); |
619 | if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { | 818 | if (je32_to_cpu(node->totlen) != c->cleanmarker_size) { |
620 | printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", | 819 | printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x has totlen 0x%x != normal 0x%x\n", |
621 | ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); | 820 | ofs, je32_to_cpu(node->totlen), c->cleanmarker_size); |
622 | DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); | 821 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node))))) |
822 | return err; | ||
623 | ofs += PAD(sizeof(struct jffs2_unknown_node)); | 823 | ofs += PAD(sizeof(struct jffs2_unknown_node)); |
624 | } else if (jeb->first_node) { | 824 | } else if (jeb->first_node) { |
625 | printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); | 825 | printk(KERN_NOTICE "CLEANMARKER node found at 0x%08x, not first node in block (0x%08x)\n", ofs, jeb->offset); |
626 | DIRTY_SPACE(PAD(sizeof(struct jffs2_unknown_node))); | 826 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(sizeof(struct jffs2_unknown_node))))) |
827 | return err; | ||
627 | ofs += PAD(sizeof(struct jffs2_unknown_node)); | 828 | ofs += PAD(sizeof(struct jffs2_unknown_node)); |
628 | } else { | 829 | } else { |
629 | struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); | 830 | jffs2_link_node_ref(c, jeb, ofs | REF_NORMAL, c->cleanmarker_size, NULL); |
630 | if (!marker_ref) { | ||
631 | printk(KERN_NOTICE "Failed to allocate node ref for clean marker\n"); | ||
632 | return -ENOMEM; | ||
633 | } | ||
634 | marker_ref->next_in_ino = NULL; | ||
635 | marker_ref->next_phys = NULL; | ||
636 | marker_ref->flash_offset = ofs | REF_NORMAL; | ||
637 | marker_ref->__totlen = c->cleanmarker_size; | ||
638 | jeb->first_node = jeb->last_node = marker_ref; | ||
639 | 831 | ||
640 | USED_SPACE(PAD(c->cleanmarker_size)); | ||
641 | ofs += PAD(c->cleanmarker_size); | 832 | ofs += PAD(c->cleanmarker_size); |
642 | } | 833 | } |
643 | break; | 834 | break; |
@@ -645,7 +836,8 @@ scan_more: | |||
645 | case JFFS2_NODETYPE_PADDING: | 836 | case JFFS2_NODETYPE_PADDING: |
646 | if (jffs2_sum_active()) | 837 | if (jffs2_sum_active()) |
647 | jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); | 838 | jffs2_sum_add_padding_mem(s, je32_to_cpu(node->totlen)); |
648 | DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); | 839 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) |
840 | return err; | ||
649 | ofs += PAD(je32_to_cpu(node->totlen)); | 841 | ofs += PAD(je32_to_cpu(node->totlen)); |
650 | break; | 842 | break; |
651 | 843 | ||
@@ -656,7 +848,8 @@ scan_more: | |||
656 | c->flags |= JFFS2_SB_FLAG_RO; | 848 | c->flags |= JFFS2_SB_FLAG_RO; |
657 | if (!(jffs2_is_readonly(c))) | 849 | if (!(jffs2_is_readonly(c))) |
658 | return -EROFS; | 850 | return -EROFS; |
659 | DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); | 851 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) |
852 | return err; | ||
660 | ofs += PAD(je32_to_cpu(node->totlen)); | 853 | ofs += PAD(je32_to_cpu(node->totlen)); |
661 | break; | 854 | break; |
662 | 855 | ||
@@ -666,15 +859,21 @@ scan_more: | |||
666 | 859 | ||
667 | case JFFS2_FEATURE_RWCOMPAT_DELETE: | 860 | case JFFS2_FEATURE_RWCOMPAT_DELETE: |
668 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); | 861 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); |
669 | DIRTY_SPACE(PAD(je32_to_cpu(node->totlen))); | 862 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(node->totlen))))) |
863 | return err; | ||
670 | ofs += PAD(je32_to_cpu(node->totlen)); | 864 | ofs += PAD(je32_to_cpu(node->totlen)); |
671 | break; | 865 | break; |
672 | 866 | ||
673 | case JFFS2_FEATURE_RWCOMPAT_COPY: | 867 | case JFFS2_FEATURE_RWCOMPAT_COPY: { |
674 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); | 868 | D1(printk(KERN_NOTICE "Unknown but compatible feature node (0x%04x) found at offset 0x%08x\n", je16_to_cpu(node->nodetype), ofs)); |
675 | USED_SPACE(PAD(je32_to_cpu(node->totlen))); | 869 | |
870 | jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(node->totlen)), NULL); | ||
871 | |||
872 | /* We can't summarise nodes we don't grok */ | ||
873 | jffs2_sum_disable_collecting(s); | ||
676 | ofs += PAD(je32_to_cpu(node->totlen)); | 874 | ofs += PAD(je32_to_cpu(node->totlen)); |
677 | break; | 875 | break; |
876 | } | ||
678 | } | 877 | } |
679 | } | 878 | } |
680 | } | 879 | } |
@@ -687,9 +886,9 @@ scan_more: | |||
687 | } | 886 | } |
688 | } | 887 | } |
689 | 888 | ||
690 | D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x\n", jeb->offset, | 889 | D1(printk(KERN_DEBUG "Block at 0x%08x: free 0x%08x, dirty 0x%08x, unchecked 0x%08x, used 0x%08x, wasted 0x%08x\n", |
691 | jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size)); | 890 | jeb->offset,jeb->free_size, jeb->dirty_size, jeb->unchecked_size, jeb->used_size, jeb->wasted_size)); |
692 | 891 | ||
693 | /* mark_node_obsolete can add to wasted !! */ | 892 | /* mark_node_obsolete can add to wasted !! */ |
694 | if (jeb->wasted_size) { | 893 | if (jeb->wasted_size) { |
695 | jeb->dirty_size += jeb->wasted_size; | 894 | jeb->dirty_size += jeb->wasted_size; |
@@ -730,9 +929,9 @@ struct jffs2_inode_cache *jffs2_scan_make_ino_cache(struct jffs2_sb_info *c, uin | |||
730 | static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 929 | static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
731 | struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) | 930 | struct jffs2_raw_inode *ri, uint32_t ofs, struct jffs2_summary *s) |
732 | { | 931 | { |
733 | struct jffs2_raw_node_ref *raw; | ||
734 | struct jffs2_inode_cache *ic; | 932 | struct jffs2_inode_cache *ic; |
735 | uint32_t ino = je32_to_cpu(ri->ino); | 933 | uint32_t ino = je32_to_cpu(ri->ino); |
934 | int err; | ||
736 | 935 | ||
737 | D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); | 936 | D1(printk(KERN_DEBUG "jffs2_scan_inode_node(): Node at 0x%08x\n", ofs)); |
738 | 937 | ||
@@ -745,12 +944,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
745 | Which means that the _full_ amount of time to get to proper write mode with GC | 944 | Which means that the _full_ amount of time to get to proper write mode with GC |
746 | operational may actually be _longer_ than before. Sucks to be me. */ | 945 | operational may actually be _longer_ than before. Sucks to be me. */ |
747 | 946 | ||
748 | raw = jffs2_alloc_raw_node_ref(); | ||
749 | if (!raw) { | ||
750 | printk(KERN_NOTICE "jffs2_scan_inode_node(): allocation of node reference failed\n"); | ||
751 | return -ENOMEM; | ||
752 | } | ||
753 | |||
754 | ic = jffs2_get_ino_cache(c, ino); | 947 | ic = jffs2_get_ino_cache(c, ino); |
755 | if (!ic) { | 948 | if (!ic) { |
756 | /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the | 949 | /* Inocache get failed. Either we read a bogus ino# or it's just genuinely the |
@@ -762,30 +955,17 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
762 | printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", | 955 | printk(KERN_NOTICE "jffs2_scan_inode_node(): CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", |
763 | ofs, je32_to_cpu(ri->node_crc), crc); | 956 | ofs, je32_to_cpu(ri->node_crc), crc); |
764 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ | 957 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ |
765 | DIRTY_SPACE(PAD(je32_to_cpu(ri->totlen))); | 958 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(ri->totlen))))) |
766 | jffs2_free_raw_node_ref(raw); | 959 | return err; |
767 | return 0; | 960 | return 0; |
768 | } | 961 | } |
769 | ic = jffs2_scan_make_ino_cache(c, ino); | 962 | ic = jffs2_scan_make_ino_cache(c, ino); |
770 | if (!ic) { | 963 | if (!ic) |
771 | jffs2_free_raw_node_ref(raw); | ||
772 | return -ENOMEM; | 964 | return -ENOMEM; |
773 | } | ||
774 | } | 965 | } |
775 | 966 | ||
776 | /* Wheee. It worked */ | 967 | /* Wheee. It worked */ |
777 | 968 | jffs2_link_node_ref(c, jeb, ofs | REF_UNCHECKED, PAD(je32_to_cpu(ri->totlen)), ic); | |
778 | raw->flash_offset = ofs | REF_UNCHECKED; | ||
779 | raw->__totlen = PAD(je32_to_cpu(ri->totlen)); | ||
780 | raw->next_phys = NULL; | ||
781 | raw->next_in_ino = ic->nodes; | ||
782 | |||
783 | ic->nodes = raw; | ||
784 | if (!jeb->first_node) | ||
785 | jeb->first_node = raw; | ||
786 | if (jeb->last_node) | ||
787 | jeb->last_node->next_phys = raw; | ||
788 | jeb->last_node = raw; | ||
789 | 969 | ||
790 | D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", | 970 | D1(printk(KERN_DEBUG "Node is ino #%u, version %d. Range 0x%x-0x%x\n", |
791 | je32_to_cpu(ri->ino), je32_to_cpu(ri->version), | 971 | je32_to_cpu(ri->ino), je32_to_cpu(ri->version), |
@@ -794,8 +974,6 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
794 | 974 | ||
795 | pseudo_random += je32_to_cpu(ri->version); | 975 | pseudo_random += je32_to_cpu(ri->version); |
796 | 976 | ||
797 | UNCHECKED_SPACE(PAD(je32_to_cpu(ri->totlen))); | ||
798 | |||
799 | if (jffs2_sum_active()) { | 977 | if (jffs2_sum_active()) { |
800 | jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); | 978 | jffs2_sum_add_inode_mem(s, ri, ofs - jeb->offset); |
801 | } | 979 | } |
@@ -806,10 +984,10 @@ static int jffs2_scan_inode_node(struct jffs2_sb_info *c, struct jffs2_erasebloc | |||
806 | static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 984 | static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
807 | struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) | 985 | struct jffs2_raw_dirent *rd, uint32_t ofs, struct jffs2_summary *s) |
808 | { | 986 | { |
809 | struct jffs2_raw_node_ref *raw; | ||
810 | struct jffs2_full_dirent *fd; | 987 | struct jffs2_full_dirent *fd; |
811 | struct jffs2_inode_cache *ic; | 988 | struct jffs2_inode_cache *ic; |
812 | uint32_t crc; | 989 | uint32_t crc; |
990 | int err; | ||
813 | 991 | ||
814 | D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); | 992 | D1(printk(KERN_DEBUG "jffs2_scan_dirent_node(): Node at 0x%08x\n", ofs)); |
815 | 993 | ||
@@ -821,7 +999,8 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
821 | printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", | 999 | printk(KERN_NOTICE "jffs2_scan_dirent_node(): Node CRC failed on node at 0x%08x: Read 0x%08x, calculated 0x%08x\n", |
822 | ofs, je32_to_cpu(rd->node_crc), crc); | 1000 | ofs, je32_to_cpu(rd->node_crc), crc); |
823 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ | 1001 | /* We believe totlen because the CRC on the node _header_ was OK, just the node itself failed. */ |
824 | DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); | 1002 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen))))) |
1003 | return err; | ||
825 | return 0; | 1004 | return 0; |
826 | } | 1005 | } |
827 | 1006 | ||
@@ -842,40 +1021,23 @@ static int jffs2_scan_dirent_node(struct jffs2_sb_info *c, struct jffs2_eraseblo | |||
842 | jffs2_free_full_dirent(fd); | 1021 | jffs2_free_full_dirent(fd); |
843 | /* FIXME: Why do we believe totlen? */ | 1022 | /* FIXME: Why do we believe totlen? */ |
844 | /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ | 1023 | /* We believe totlen because the CRC on the node _header_ was OK, just the name failed. */ |
845 | DIRTY_SPACE(PAD(je32_to_cpu(rd->totlen))); | 1024 | if ((err = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(rd->totlen))))) |
1025 | return err; | ||
846 | return 0; | 1026 | return 0; |
847 | } | 1027 | } |
848 | raw = jffs2_alloc_raw_node_ref(); | ||
849 | if (!raw) { | ||
850 | jffs2_free_full_dirent(fd); | ||
851 | printk(KERN_NOTICE "jffs2_scan_dirent_node(): allocation of node reference failed\n"); | ||
852 | return -ENOMEM; | ||
853 | } | ||
854 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); | 1028 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(rd->pino)); |
855 | if (!ic) { | 1029 | if (!ic) { |
856 | jffs2_free_full_dirent(fd); | 1030 | jffs2_free_full_dirent(fd); |
857 | jffs2_free_raw_node_ref(raw); | ||
858 | return -ENOMEM; | 1031 | return -ENOMEM; |
859 | } | 1032 | } |
860 | 1033 | ||
861 | raw->__totlen = PAD(je32_to_cpu(rd->totlen)); | 1034 | fd->raw = jffs2_link_node_ref(c, jeb, ofs | REF_PRISTINE, PAD(je32_to_cpu(rd->totlen)), ic); |
862 | raw->flash_offset = ofs | REF_PRISTINE; | ||
863 | raw->next_phys = NULL; | ||
864 | raw->next_in_ino = ic->nodes; | ||
865 | ic->nodes = raw; | ||
866 | if (!jeb->first_node) | ||
867 | jeb->first_node = raw; | ||
868 | if (jeb->last_node) | ||
869 | jeb->last_node->next_phys = raw; | ||
870 | jeb->last_node = raw; | ||
871 | 1035 | ||
872 | fd->raw = raw; | ||
873 | fd->next = NULL; | 1036 | fd->next = NULL; |
874 | fd->version = je32_to_cpu(rd->version); | 1037 | fd->version = je32_to_cpu(rd->version); |
875 | fd->ino = je32_to_cpu(rd->ino); | 1038 | fd->ino = je32_to_cpu(rd->ino); |
876 | fd->nhash = full_name_hash(fd->name, rd->nsize); | 1039 | fd->nhash = full_name_hash(fd->name, rd->nsize); |
877 | fd->type = rd->type; | 1040 | fd->type = rd->type; |
878 | USED_SPACE(PAD(je32_to_cpu(rd->totlen))); | ||
879 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); | 1041 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); |
880 | 1042 | ||
881 | if (jffs2_sum_active()) { | 1043 | if (jffs2_sum_active()) { |
diff --git a/fs/jffs2/security.c b/fs/jffs2/security.c new file mode 100644 index 000000000000..52a9894a6364 --- /dev/null +++ b/fs/jffs2/security.c | |||
@@ -0,0 +1,82 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/time.h> | ||
15 | #include <linux/pagemap.h> | ||
16 | #include <linux/highmem.h> | ||
17 | #include <linux/crc32.h> | ||
18 | #include <linux/jffs2.h> | ||
19 | #include <linux/xattr.h> | ||
20 | #include <linux/mtd/mtd.h> | ||
21 | #include <linux/security.h> | ||
22 | #include "nodelist.h" | ||
23 | |||
24 | /* ---- Initial Security Label Attachment -------------- */ | ||
25 | int jffs2_init_security(struct inode *inode, struct inode *dir) | ||
26 | { | ||
27 | int rc; | ||
28 | size_t len; | ||
29 | void *value; | ||
30 | char *name; | ||
31 | |||
32 | rc = security_inode_init_security(inode, dir, &name, &value, &len); | ||
33 | if (rc) { | ||
34 | if (rc == -EOPNOTSUPP) | ||
35 | return 0; | ||
36 | return rc; | ||
37 | } | ||
38 | rc = do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, value, len, 0); | ||
39 | |||
40 | kfree(name); | ||
41 | kfree(value); | ||
42 | return rc; | ||
43 | } | ||
44 | |||
45 | /* ---- XATTR Handler for "security.*" ----------------- */ | ||
46 | static int jffs2_security_getxattr(struct inode *inode, const char *name, | ||
47 | void *buffer, size_t size) | ||
48 | { | ||
49 | if (!strcmp(name, "")) | ||
50 | return -EINVAL; | ||
51 | |||
52 | return do_jffs2_getxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size); | ||
53 | } | ||
54 | |||
55 | static int jffs2_security_setxattr(struct inode *inode, const char *name, const void *buffer, | ||
56 | size_t size, int flags) | ||
57 | { | ||
58 | if (!strcmp(name, "")) | ||
59 | return -EINVAL; | ||
60 | |||
61 | return do_jffs2_setxattr(inode, JFFS2_XPREFIX_SECURITY, name, buffer, size, flags); | ||
62 | } | ||
63 | |||
64 | static size_t jffs2_security_listxattr(struct inode *inode, char *list, size_t list_size, | ||
65 | const char *name, size_t name_len) | ||
66 | { | ||
67 | size_t retlen = XATTR_SECURITY_PREFIX_LEN + name_len + 1; | ||
68 | |||
69 | if (list && retlen <= list_size) { | ||
70 | strcpy(list, XATTR_SECURITY_PREFIX); | ||
71 | strcpy(list + XATTR_SECURITY_PREFIX_LEN, name); | ||
72 | } | ||
73 | |||
74 | return retlen; | ||
75 | } | ||
76 | |||
77 | struct xattr_handler jffs2_security_xattr_handler = { | ||
78 | .prefix = XATTR_SECURITY_PREFIX, | ||
79 | .list = jffs2_security_listxattr, | ||
80 | .set = jffs2_security_setxattr, | ||
81 | .get = jffs2_security_getxattr | ||
82 | }; | ||
diff --git a/fs/jffs2/summary.c b/fs/jffs2/summary.c index fb9cec61fcf2..0b02fc79e4d1 100644 --- a/fs/jffs2/summary.c +++ b/fs/jffs2/summary.c | |||
@@ -5,6 +5,7 @@ | |||
5 | * Zoltan Sogor <weth@inf.u-szeged.hu>, | 5 | * Zoltan Sogor <weth@inf.u-szeged.hu>, |
6 | * Patrik Kluba <pajko@halom.u-szeged.hu>, | 6 | * Patrik Kluba <pajko@halom.u-szeged.hu>, |
7 | * University of Szeged, Hungary | 7 | * University of Szeged, Hungary |
8 | * 2005 KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
8 | * | 9 | * |
9 | * For licensing information, see the file 'LICENCE' in this directory. | 10 | * For licensing information, see the file 'LICENCE' in this directory. |
10 | * | 11 | * |
@@ -81,6 +82,19 @@ static int jffs2_sum_add_mem(struct jffs2_summary *s, union jffs2_sum_mem *item) | |||
81 | dbg_summary("dirent (%u) added to summary\n", | 82 | dbg_summary("dirent (%u) added to summary\n", |
82 | je32_to_cpu(item->d.ino)); | 83 | je32_to_cpu(item->d.ino)); |
83 | break; | 84 | break; |
85 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
86 | case JFFS2_NODETYPE_XATTR: | ||
87 | s->sum_size += JFFS2_SUMMARY_XATTR_SIZE; | ||
88 | s->sum_num++; | ||
89 | dbg_summary("xattr (xid=%u, version=%u) added to summary\n", | ||
90 | je32_to_cpu(item->x.xid), je32_to_cpu(item->x.version)); | ||
91 | break; | ||
92 | case JFFS2_NODETYPE_XREF: | ||
93 | s->sum_size += JFFS2_SUMMARY_XREF_SIZE; | ||
94 | s->sum_num++; | ||
95 | dbg_summary("xref added to summary\n"); | ||
96 | break; | ||
97 | #endif | ||
84 | default: | 98 | default: |
85 | JFFS2_WARNING("UNKNOWN node type %u\n", | 99 | JFFS2_WARNING("UNKNOWN node type %u\n", |
86 | je16_to_cpu(item->u.nodetype)); | 100 | je16_to_cpu(item->u.nodetype)); |
@@ -141,6 +155,40 @@ int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *r | |||
141 | return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); | 155 | return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); |
142 | } | 156 | } |
143 | 157 | ||
158 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
159 | int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs) | ||
160 | { | ||
161 | struct jffs2_sum_xattr_mem *temp; | ||
162 | |||
163 | temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL); | ||
164 | if (!temp) | ||
165 | return -ENOMEM; | ||
166 | |||
167 | temp->nodetype = rx->nodetype; | ||
168 | temp->xid = rx->xid; | ||
169 | temp->version = rx->version; | ||
170 | temp->offset = cpu_to_je32(ofs); | ||
171 | temp->totlen = rx->totlen; | ||
172 | temp->next = NULL; | ||
173 | |||
174 | return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); | ||
175 | } | ||
176 | |||
177 | int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs) | ||
178 | { | ||
179 | struct jffs2_sum_xref_mem *temp; | ||
180 | |||
181 | temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL); | ||
182 | if (!temp) | ||
183 | return -ENOMEM; | ||
184 | |||
185 | temp->nodetype = rr->nodetype; | ||
186 | temp->offset = cpu_to_je32(ofs); | ||
187 | temp->next = NULL; | ||
188 | |||
189 | return jffs2_sum_add_mem(s, (union jffs2_sum_mem *)temp); | ||
190 | } | ||
191 | #endif | ||
144 | /* Cleanup every collected summary information */ | 192 | /* Cleanup every collected summary information */ |
145 | 193 | ||
146 | static void jffs2_sum_clean_collected(struct jffs2_summary *s) | 194 | static void jffs2_sum_clean_collected(struct jffs2_summary *s) |
@@ -259,7 +307,40 @@ int jffs2_sum_add_kvec(struct jffs2_sb_info *c, const struct kvec *invecs, | |||
259 | 307 | ||
260 | return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); | 308 | return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); |
261 | } | 309 | } |
310 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
311 | case JFFS2_NODETYPE_XATTR: { | ||
312 | struct jffs2_sum_xattr_mem *temp; | ||
313 | if (je32_to_cpu(node->x.version) == 0xffffffff) | ||
314 | return 0; | ||
315 | temp = kmalloc(sizeof(struct jffs2_sum_xattr_mem), GFP_KERNEL); | ||
316 | if (!temp) | ||
317 | goto no_mem; | ||
318 | |||
319 | temp->nodetype = node->x.nodetype; | ||
320 | temp->xid = node->x.xid; | ||
321 | temp->version = node->x.version; | ||
322 | temp->totlen = node->x.totlen; | ||
323 | temp->offset = cpu_to_je32(ofs); | ||
324 | temp->next = NULL; | ||
325 | |||
326 | return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); | ||
327 | } | ||
328 | case JFFS2_NODETYPE_XREF: { | ||
329 | struct jffs2_sum_xref_mem *temp; | ||
330 | |||
331 | if (je32_to_cpu(node->r.ino) == 0xffffffff | ||
332 | && je32_to_cpu(node->r.xid) == 0xffffffff) | ||
333 | return 0; | ||
334 | temp = kmalloc(sizeof(struct jffs2_sum_xref_mem), GFP_KERNEL); | ||
335 | if (!temp) | ||
336 | goto no_mem; | ||
337 | temp->nodetype = node->r.nodetype; | ||
338 | temp->offset = cpu_to_je32(ofs); | ||
339 | temp->next = NULL; | ||
262 | 340 | ||
341 | return jffs2_sum_add_mem(c->summary, (union jffs2_sum_mem *)temp); | ||
342 | } | ||
343 | #endif | ||
263 | case JFFS2_NODETYPE_PADDING: | 344 | case JFFS2_NODETYPE_PADDING: |
264 | dbg_summary("node PADDING\n"); | 345 | dbg_summary("node PADDING\n"); |
265 | c->summary->sum_padded += je32_to_cpu(node->u.totlen); | 346 | c->summary->sum_padded += je32_to_cpu(node->u.totlen); |
@@ -288,23 +369,41 @@ no_mem: | |||
288 | return -ENOMEM; | 369 | return -ENOMEM; |
289 | } | 370 | } |
290 | 371 | ||
372 | static struct jffs2_raw_node_ref *sum_link_node_ref(struct jffs2_sb_info *c, | ||
373 | struct jffs2_eraseblock *jeb, | ||
374 | uint32_t ofs, uint32_t len, | ||
375 | struct jffs2_inode_cache *ic) | ||
376 | { | ||
377 | /* If there was a gap, mark it dirty */ | ||
378 | if ((ofs & ~3) > c->sector_size - jeb->free_size) { | ||
379 | /* Ew. Summary doesn't actually tell us explicitly about dirty space */ | ||
380 | jffs2_scan_dirty_space(c, jeb, (ofs & ~3) - (c->sector_size - jeb->free_size)); | ||
381 | } | ||
382 | |||
383 | return jffs2_link_node_ref(c, jeb, jeb->offset + ofs, len, ic); | ||
384 | } | ||
291 | 385 | ||
292 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ | 386 | /* Process the stored summary information - helper function for jffs2_sum_scan_sumnode() */ |
293 | 387 | ||
294 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 388 | static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
295 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) | 389 | struct jffs2_raw_summary *summary, uint32_t *pseudo_random) |
296 | { | 390 | { |
297 | struct jffs2_raw_node_ref *raw; | ||
298 | struct jffs2_inode_cache *ic; | 391 | struct jffs2_inode_cache *ic; |
299 | struct jffs2_full_dirent *fd; | 392 | struct jffs2_full_dirent *fd; |
300 | void *sp; | 393 | void *sp; |
301 | int i, ino; | 394 | int i, ino; |
395 | int err; | ||
302 | 396 | ||
303 | sp = summary->sum; | 397 | sp = summary->sum; |
304 | 398 | ||
305 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { | 399 | for (i=0; i<je32_to_cpu(summary->sum_num); i++) { |
306 | dbg_summary("processing summary index %d\n", i); | 400 | dbg_summary("processing summary index %d\n", i); |
307 | 401 | ||
402 | /* Make sure there's a spare ref for dirty space */ | ||
403 | err = jffs2_prealloc_raw_node_refs(c, jeb, 2); | ||
404 | if (err) | ||
405 | return err; | ||
406 | |||
308 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { | 407 | switch (je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype)) { |
309 | case JFFS2_NODETYPE_INODE: { | 408 | case JFFS2_NODETYPE_INODE: { |
310 | struct jffs2_sum_inode_flash *spi; | 409 | struct jffs2_sum_inode_flash *spi; |
@@ -312,38 +411,20 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
312 | 411 | ||
313 | ino = je32_to_cpu(spi->inode); | 412 | ino = je32_to_cpu(spi->inode); |
314 | 413 | ||
315 | dbg_summary("Inode at 0x%08x\n", | 414 | dbg_summary("Inode at 0x%08x-0x%08x\n", |
316 | jeb->offset + je32_to_cpu(spi->offset)); | 415 | jeb->offset + je32_to_cpu(spi->offset), |
317 | 416 | jeb->offset + je32_to_cpu(spi->offset) + je32_to_cpu(spi->totlen)); | |
318 | raw = jffs2_alloc_raw_node_ref(); | ||
319 | if (!raw) { | ||
320 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
321 | kfree(summary); | ||
322 | return -ENOMEM; | ||
323 | } | ||
324 | 417 | ||
325 | ic = jffs2_scan_make_ino_cache(c, ino); | 418 | ic = jffs2_scan_make_ino_cache(c, ino); |
326 | if (!ic) { | 419 | if (!ic) { |
327 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); | 420 | JFFS2_NOTICE("scan_make_ino_cache failed\n"); |
328 | jffs2_free_raw_node_ref(raw); | ||
329 | kfree(summary); | ||
330 | return -ENOMEM; | 421 | return -ENOMEM; |
331 | } | 422 | } |
332 | 423 | ||
333 | raw->flash_offset = (jeb->offset + je32_to_cpu(spi->offset)) | REF_UNCHECKED; | 424 | sum_link_node_ref(c, jeb, je32_to_cpu(spi->offset) | REF_UNCHECKED, |
334 | raw->__totlen = PAD(je32_to_cpu(spi->totlen)); | 425 | PAD(je32_to_cpu(spi->totlen)), ic); |
335 | raw->next_phys = NULL; | ||
336 | raw->next_in_ino = ic->nodes; | ||
337 | |||
338 | ic->nodes = raw; | ||
339 | if (!jeb->first_node) | ||
340 | jeb->first_node = raw; | ||
341 | if (jeb->last_node) | ||
342 | jeb->last_node->next_phys = raw; | ||
343 | jeb->last_node = raw; | ||
344 | *pseudo_random += je32_to_cpu(spi->version); | ||
345 | 426 | ||
346 | UNCHECKED_SPACE(PAD(je32_to_cpu(spi->totlen))); | 427 | *pseudo_random += je32_to_cpu(spi->version); |
347 | 428 | ||
348 | sp += JFFS2_SUMMARY_INODE_SIZE; | 429 | sp += JFFS2_SUMMARY_INODE_SIZE; |
349 | 430 | ||
@@ -354,52 +435,33 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
354 | struct jffs2_sum_dirent_flash *spd; | 435 | struct jffs2_sum_dirent_flash *spd; |
355 | spd = sp; | 436 | spd = sp; |
356 | 437 | ||
357 | dbg_summary("Dirent at 0x%08x\n", | 438 | dbg_summary("Dirent at 0x%08x-0x%08x\n", |
358 | jeb->offset + je32_to_cpu(spd->offset)); | 439 | jeb->offset + je32_to_cpu(spd->offset), |
440 | jeb->offset + je32_to_cpu(spd->offset) + je32_to_cpu(spd->totlen)); | ||
441 | |||
359 | 442 | ||
360 | fd = jffs2_alloc_full_dirent(spd->nsize+1); | 443 | fd = jffs2_alloc_full_dirent(spd->nsize+1); |
361 | if (!fd) { | 444 | if (!fd) |
362 | kfree(summary); | ||
363 | return -ENOMEM; | 445 | return -ENOMEM; |
364 | } | ||
365 | 446 | ||
366 | memcpy(&fd->name, spd->name, spd->nsize); | 447 | memcpy(&fd->name, spd->name, spd->nsize); |
367 | fd->name[spd->nsize] = 0; | 448 | fd->name[spd->nsize] = 0; |
368 | 449 | ||
369 | raw = jffs2_alloc_raw_node_ref(); | ||
370 | if (!raw) { | ||
371 | jffs2_free_full_dirent(fd); | ||
372 | JFFS2_NOTICE("allocation of node reference failed\n"); | ||
373 | kfree(summary); | ||
374 | return -ENOMEM; | ||
375 | } | ||
376 | |||
377 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); | 450 | ic = jffs2_scan_make_ino_cache(c, je32_to_cpu(spd->pino)); |
378 | if (!ic) { | 451 | if (!ic) { |
379 | jffs2_free_full_dirent(fd); | 452 | jffs2_free_full_dirent(fd); |
380 | jffs2_free_raw_node_ref(raw); | ||
381 | kfree(summary); | ||
382 | return -ENOMEM; | 453 | return -ENOMEM; |
383 | } | 454 | } |
384 | 455 | ||
385 | raw->__totlen = PAD(je32_to_cpu(spd->totlen)); | 456 | fd->raw = sum_link_node_ref(c, jeb, je32_to_cpu(spd->offset) | REF_UNCHECKED, |
386 | raw->flash_offset = (jeb->offset + je32_to_cpu(spd->offset)) | REF_PRISTINE; | 457 | PAD(je32_to_cpu(spd->totlen)), ic); |
387 | raw->next_phys = NULL; | 458 | |
388 | raw->next_in_ino = ic->nodes; | ||
389 | ic->nodes = raw; | ||
390 | if (!jeb->first_node) | ||
391 | jeb->first_node = raw; | ||
392 | if (jeb->last_node) | ||
393 | jeb->last_node->next_phys = raw; | ||
394 | jeb->last_node = raw; | ||
395 | |||
396 | fd->raw = raw; | ||
397 | fd->next = NULL; | 459 | fd->next = NULL; |
398 | fd->version = je32_to_cpu(spd->version); | 460 | fd->version = je32_to_cpu(spd->version); |
399 | fd->ino = je32_to_cpu(spd->ino); | 461 | fd->ino = je32_to_cpu(spd->ino); |
400 | fd->nhash = full_name_hash(fd->name, spd->nsize); | 462 | fd->nhash = full_name_hash(fd->name, spd->nsize); |
401 | fd->type = spd->type; | 463 | fd->type = spd->type; |
402 | USED_SPACE(PAD(je32_to_cpu(spd->totlen))); | 464 | |
403 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); | 465 | jffs2_add_fd_to_list(c, fd, &ic->scan_dents); |
404 | 466 | ||
405 | *pseudo_random += je32_to_cpu(spd->version); | 467 | *pseudo_random += je32_to_cpu(spd->version); |
@@ -408,48 +470,105 @@ static int jffs2_sum_process_sum_data(struct jffs2_sb_info *c, struct jffs2_eras | |||
408 | 470 | ||
409 | break; | 471 | break; |
410 | } | 472 | } |
473 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
474 | case JFFS2_NODETYPE_XATTR: { | ||
475 | struct jffs2_xattr_datum *xd; | ||
476 | struct jffs2_sum_xattr_flash *spx; | ||
477 | |||
478 | spx = (struct jffs2_sum_xattr_flash *)sp; | ||
479 | dbg_summary("xattr at %#08x-%#08x (xid=%u, version=%u)\n", | ||
480 | jeb->offset + je32_to_cpu(spx->offset), | ||
481 | jeb->offset + je32_to_cpu(spx->offset) + je32_to_cpu(spx->totlen), | ||
482 | je32_to_cpu(spx->xid), je32_to_cpu(spx->version)); | ||
483 | |||
484 | xd = jffs2_setup_xattr_datum(c, je32_to_cpu(spx->xid), | ||
485 | je32_to_cpu(spx->version)); | ||
486 | if (IS_ERR(xd)) { | ||
487 | if (PTR_ERR(xd) == -EEXIST) { | ||
488 | /* a newer version of xd exists */ | ||
489 | if ((err = jffs2_scan_dirty_space(c, jeb, je32_to_cpu(spx->totlen)))) | ||
490 | return err; | ||
491 | sp += JFFS2_SUMMARY_XATTR_SIZE; | ||
492 | break; | ||
493 | } | ||
494 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | ||
495 | return PTR_ERR(xd); | ||
496 | } | ||
497 | |||
498 | xd->node = sum_link_node_ref(c, jeb, je32_to_cpu(spx->offset) | REF_UNCHECKED, | ||
499 | PAD(je32_to_cpu(spx->totlen)), NULL); | ||
500 | /* FIXME */ xd->node->next_in_ino = (void *)xd; | ||
501 | |||
502 | *pseudo_random += je32_to_cpu(spx->xid); | ||
503 | sp += JFFS2_SUMMARY_XATTR_SIZE; | ||
504 | |||
505 | break; | ||
506 | } | ||
507 | case JFFS2_NODETYPE_XREF: { | ||
508 | struct jffs2_xattr_ref *ref; | ||
509 | struct jffs2_sum_xref_flash *spr; | ||
510 | |||
511 | spr = (struct jffs2_sum_xref_flash *)sp; | ||
512 | dbg_summary("xref at %#08x-%#08x\n", | ||
513 | jeb->offset + je32_to_cpu(spr->offset), | ||
514 | jeb->offset + je32_to_cpu(spr->offset) + | ||
515 | (uint32_t)PAD(sizeof(struct jffs2_raw_xref))); | ||
516 | |||
517 | ref = jffs2_alloc_xattr_ref(); | ||
518 | if (!ref) { | ||
519 | JFFS2_NOTICE("allocation of xattr_datum failed\n"); | ||
520 | return -ENOMEM; | ||
521 | } | ||
522 | ref->ino = 0xfffffffe; | ||
523 | ref->xid = 0xfffffffd; | ||
524 | ref->next = c->xref_temp; | ||
525 | c->xref_temp = ref; | ||
411 | 526 | ||
527 | ref->node = sum_link_node_ref(c, jeb, je32_to_cpu(spr->offset) | REF_UNCHECKED, | ||
528 | PAD(sizeof(struct jffs2_raw_xref)), NULL); | ||
529 | /* FIXME */ ref->node->next_in_ino = (void *)ref; | ||
530 | |||
531 | *pseudo_random += ref->node->flash_offset; | ||
532 | sp += JFFS2_SUMMARY_XREF_SIZE; | ||
533 | |||
534 | break; | ||
535 | } | ||
536 | #endif | ||
412 | default : { | 537 | default : { |
413 | JFFS2_WARNING("Unsupported node type found in summary! Exiting..."); | 538 | uint16_t nodetype = je16_to_cpu(((struct jffs2_sum_unknown_flash *)sp)->nodetype); |
414 | kfree(summary); | 539 | JFFS2_WARNING("Unsupported node type %x found in summary! Exiting...\n", nodetype); |
415 | return -EIO; | 540 | if ((nodetype & JFFS2_COMPAT_MASK) == JFFS2_FEATURE_INCOMPAT) |
541 | return -EIO; | ||
542 | |||
543 | /* For compatible node types, just fall back to the full scan */ | ||
544 | c->wasted_size -= jeb->wasted_size; | ||
545 | c->free_size += c->sector_size - jeb->free_size; | ||
546 | c->used_size -= jeb->used_size; | ||
547 | c->dirty_size -= jeb->dirty_size; | ||
548 | jeb->wasted_size = jeb->used_size = jeb->dirty_size = 0; | ||
549 | jeb->free_size = c->sector_size; | ||
550 | |||
551 | jffs2_free_jeb_node_refs(c, jeb); | ||
552 | return -ENOTRECOVERABLE; | ||
416 | } | 553 | } |
417 | } | 554 | } |
418 | } | 555 | } |
419 | |||
420 | kfree(summary); | ||
421 | return 0; | 556 | return 0; |
422 | } | 557 | } |
423 | 558 | ||
424 | /* Process the summary node - called from jffs2_scan_eraseblock() */ | 559 | /* Process the summary node - called from jffs2_scan_eraseblock() */ |
425 | |||
426 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 560 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
427 | uint32_t ofs, uint32_t *pseudo_random) | 561 | struct jffs2_raw_summary *summary, uint32_t sumsize, |
562 | uint32_t *pseudo_random) | ||
428 | { | 563 | { |
429 | struct jffs2_unknown_node crcnode; | 564 | struct jffs2_unknown_node crcnode; |
430 | struct jffs2_raw_node_ref *cache_ref; | 565 | int ret, ofs; |
431 | struct jffs2_raw_summary *summary; | ||
432 | int ret, sumsize; | ||
433 | uint32_t crc; | 566 | uint32_t crc; |
434 | 567 | ||
435 | sumsize = c->sector_size - ofs; | 568 | ofs = c->sector_size - sumsize; |
436 | ofs += jeb->offset; | ||
437 | 569 | ||
438 | dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", | 570 | dbg_summary("summary found for 0x%08x at 0x%08x (0x%x bytes)\n", |
439 | jeb->offset, ofs, sumsize); | 571 | jeb->offset, jeb->offset + ofs, sumsize); |
440 | |||
441 | summary = kmalloc(sumsize, GFP_KERNEL); | ||
442 | |||
443 | if (!summary) { | ||
444 | return -ENOMEM; | ||
445 | } | ||
446 | |||
447 | ret = jffs2_fill_scan_buf(c, (unsigned char *)summary, ofs, sumsize); | ||
448 | |||
449 | if (ret) { | ||
450 | kfree(summary); | ||
451 | return ret; | ||
452 | } | ||
453 | 572 | ||
454 | /* OK, now check for node validity and CRC */ | 573 | /* OK, now check for node validity and CRC */ |
455 | crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 574 | crcnode.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
@@ -486,66 +605,49 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
486 | 605 | ||
487 | dbg_summary("Summary : CLEANMARKER node \n"); | 606 | dbg_summary("Summary : CLEANMARKER node \n"); |
488 | 607 | ||
608 | ret = jffs2_prealloc_raw_node_refs(c, jeb, 1); | ||
609 | if (ret) | ||
610 | return ret; | ||
611 | |||
489 | if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { | 612 | if (je32_to_cpu(summary->cln_mkr) != c->cleanmarker_size) { |
490 | dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", | 613 | dbg_summary("CLEANMARKER node has totlen 0x%x != normal 0x%x\n", |
491 | je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); | 614 | je32_to_cpu(summary->cln_mkr), c->cleanmarker_size); |
492 | UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); | 615 | if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) |
616 | return ret; | ||
493 | } else if (jeb->first_node) { | 617 | } else if (jeb->first_node) { |
494 | dbg_summary("CLEANMARKER node not first node in block " | 618 | dbg_summary("CLEANMARKER node not first node in block " |
495 | "(0x%08x)\n", jeb->offset); | 619 | "(0x%08x)\n", jeb->offset); |
496 | UNCHECKED_SPACE(PAD(je32_to_cpu(summary->cln_mkr))); | 620 | if ((ret = jffs2_scan_dirty_space(c, jeb, PAD(je32_to_cpu(summary->cln_mkr))))) |
621 | return ret; | ||
497 | } else { | 622 | } else { |
498 | struct jffs2_raw_node_ref *marker_ref = jffs2_alloc_raw_node_ref(); | 623 | jffs2_link_node_ref(c, jeb, jeb->offset | REF_NORMAL, |
499 | 624 | je32_to_cpu(summary->cln_mkr), NULL); | |
500 | if (!marker_ref) { | ||
501 | JFFS2_NOTICE("Failed to allocate node ref for clean marker\n"); | ||
502 | kfree(summary); | ||
503 | return -ENOMEM; | ||
504 | } | ||
505 | |||
506 | marker_ref->next_in_ino = NULL; | ||
507 | marker_ref->next_phys = NULL; | ||
508 | marker_ref->flash_offset = jeb->offset | REF_NORMAL; | ||
509 | marker_ref->__totlen = je32_to_cpu(summary->cln_mkr); | ||
510 | jeb->first_node = jeb->last_node = marker_ref; | ||
511 | |||
512 | USED_SPACE( PAD(je32_to_cpu(summary->cln_mkr)) ); | ||
513 | } | 625 | } |
514 | } | 626 | } |
515 | 627 | ||
516 | if (je32_to_cpu(summary->padded)) { | ||
517 | DIRTY_SPACE(je32_to_cpu(summary->padded)); | ||
518 | } | ||
519 | |||
520 | ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); | 628 | ret = jffs2_sum_process_sum_data(c, jeb, summary, pseudo_random); |
629 | /* -ENOTRECOVERABLE isn't a fatal error -- it means we should do a full | ||
630 | scan of this eraseblock. So return zero */ | ||
631 | if (ret == -ENOTRECOVERABLE) | ||
632 | return 0; | ||
521 | if (ret) | 633 | if (ret) |
522 | return ret; | 634 | return ret; /* real error */ |
523 | 635 | ||
524 | /* for PARANOIA_CHECK */ | 636 | /* for PARANOIA_CHECK */ |
525 | cache_ref = jffs2_alloc_raw_node_ref(); | 637 | ret = jffs2_prealloc_raw_node_refs(c, jeb, 2); |
526 | 638 | if (ret) | |
527 | if (!cache_ref) { | 639 | return ret; |
528 | JFFS2_NOTICE("Failed to allocate node ref for cache\n"); | ||
529 | return -ENOMEM; | ||
530 | } | ||
531 | |||
532 | cache_ref->next_in_ino = NULL; | ||
533 | cache_ref->next_phys = NULL; | ||
534 | cache_ref->flash_offset = ofs | REF_NORMAL; | ||
535 | cache_ref->__totlen = sumsize; | ||
536 | |||
537 | if (!jeb->first_node) | ||
538 | jeb->first_node = cache_ref; | ||
539 | if (jeb->last_node) | ||
540 | jeb->last_node->next_phys = cache_ref; | ||
541 | jeb->last_node = cache_ref; | ||
542 | 640 | ||
543 | USED_SPACE(sumsize); | 641 | sum_link_node_ref(c, jeb, ofs | REF_NORMAL, sumsize, NULL); |
544 | 642 | ||
545 | jeb->wasted_size += jeb->free_size; | 643 | if (unlikely(jeb->free_size)) { |
546 | c->wasted_size += jeb->free_size; | 644 | JFFS2_WARNING("Free size 0x%x bytes in eraseblock @0x%08x with summary?\n", |
547 | c->free_size -= jeb->free_size; | 645 | jeb->free_size, jeb->offset); |
548 | jeb->free_size = 0; | 646 | jeb->wasted_size += jeb->free_size; |
647 | c->wasted_size += jeb->free_size; | ||
648 | c->free_size -= jeb->free_size; | ||
649 | jeb->free_size = 0; | ||
650 | } | ||
549 | 651 | ||
550 | return jffs2_scan_classify_jeb(c, jeb); | 652 | return jffs2_scan_classify_jeb(c, jeb); |
551 | 653 | ||
@@ -564,6 +666,7 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
564 | union jffs2_sum_mem *temp; | 666 | union jffs2_sum_mem *temp; |
565 | struct jffs2_sum_marker *sm; | 667 | struct jffs2_sum_marker *sm; |
566 | struct kvec vecs[2]; | 668 | struct kvec vecs[2]; |
669 | uint32_t sum_ofs; | ||
567 | void *wpage; | 670 | void *wpage; |
568 | int ret; | 671 | int ret; |
569 | size_t retlen; | 672 | size_t retlen; |
@@ -581,16 +684,17 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
581 | wpage = c->summary->sum_buf; | 684 | wpage = c->summary->sum_buf; |
582 | 685 | ||
583 | while (c->summary->sum_num) { | 686 | while (c->summary->sum_num) { |
687 | temp = c->summary->sum_list_head; | ||
584 | 688 | ||
585 | switch (je16_to_cpu(c->summary->sum_list_head->u.nodetype)) { | 689 | switch (je16_to_cpu(temp->u.nodetype)) { |
586 | case JFFS2_NODETYPE_INODE: { | 690 | case JFFS2_NODETYPE_INODE: { |
587 | struct jffs2_sum_inode_flash *sino_ptr = wpage; | 691 | struct jffs2_sum_inode_flash *sino_ptr = wpage; |
588 | 692 | ||
589 | sino_ptr->nodetype = c->summary->sum_list_head->i.nodetype; | 693 | sino_ptr->nodetype = temp->i.nodetype; |
590 | sino_ptr->inode = c->summary->sum_list_head->i.inode; | 694 | sino_ptr->inode = temp->i.inode; |
591 | sino_ptr->version = c->summary->sum_list_head->i.version; | 695 | sino_ptr->version = temp->i.version; |
592 | sino_ptr->offset = c->summary->sum_list_head->i.offset; | 696 | sino_ptr->offset = temp->i.offset; |
593 | sino_ptr->totlen = c->summary->sum_list_head->i.totlen; | 697 | sino_ptr->totlen = temp->i.totlen; |
594 | 698 | ||
595 | wpage += JFFS2_SUMMARY_INODE_SIZE; | 699 | wpage += JFFS2_SUMMARY_INODE_SIZE; |
596 | 700 | ||
@@ -600,30 +704,60 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
600 | case JFFS2_NODETYPE_DIRENT: { | 704 | case JFFS2_NODETYPE_DIRENT: { |
601 | struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; | 705 | struct jffs2_sum_dirent_flash *sdrnt_ptr = wpage; |
602 | 706 | ||
603 | sdrnt_ptr->nodetype = c->summary->sum_list_head->d.nodetype; | 707 | sdrnt_ptr->nodetype = temp->d.nodetype; |
604 | sdrnt_ptr->totlen = c->summary->sum_list_head->d.totlen; | 708 | sdrnt_ptr->totlen = temp->d.totlen; |
605 | sdrnt_ptr->offset = c->summary->sum_list_head->d.offset; | 709 | sdrnt_ptr->offset = temp->d.offset; |
606 | sdrnt_ptr->pino = c->summary->sum_list_head->d.pino; | 710 | sdrnt_ptr->pino = temp->d.pino; |
607 | sdrnt_ptr->version = c->summary->sum_list_head->d.version; | 711 | sdrnt_ptr->version = temp->d.version; |
608 | sdrnt_ptr->ino = c->summary->sum_list_head->d.ino; | 712 | sdrnt_ptr->ino = temp->d.ino; |
609 | sdrnt_ptr->nsize = c->summary->sum_list_head->d.nsize; | 713 | sdrnt_ptr->nsize = temp->d.nsize; |
610 | sdrnt_ptr->type = c->summary->sum_list_head->d.type; | 714 | sdrnt_ptr->type = temp->d.type; |
611 | 715 | ||
612 | memcpy(sdrnt_ptr->name, c->summary->sum_list_head->d.name, | 716 | memcpy(sdrnt_ptr->name, temp->d.name, |
613 | c->summary->sum_list_head->d.nsize); | 717 | temp->d.nsize); |
614 | 718 | ||
615 | wpage += JFFS2_SUMMARY_DIRENT_SIZE(c->summary->sum_list_head->d.nsize); | 719 | wpage += JFFS2_SUMMARY_DIRENT_SIZE(temp->d.nsize); |
616 | 720 | ||
617 | break; | 721 | break; |
618 | } | 722 | } |
723 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
724 | case JFFS2_NODETYPE_XATTR: { | ||
725 | struct jffs2_sum_xattr_flash *sxattr_ptr = wpage; | ||
726 | |||
727 | temp = c->summary->sum_list_head; | ||
728 | sxattr_ptr->nodetype = temp->x.nodetype; | ||
729 | sxattr_ptr->xid = temp->x.xid; | ||
730 | sxattr_ptr->version = temp->x.version; | ||
731 | sxattr_ptr->offset = temp->x.offset; | ||
732 | sxattr_ptr->totlen = temp->x.totlen; | ||
733 | |||
734 | wpage += JFFS2_SUMMARY_XATTR_SIZE; | ||
735 | break; | ||
736 | } | ||
737 | case JFFS2_NODETYPE_XREF: { | ||
738 | struct jffs2_sum_xref_flash *sxref_ptr = wpage; | ||
619 | 739 | ||
740 | temp = c->summary->sum_list_head; | ||
741 | sxref_ptr->nodetype = temp->r.nodetype; | ||
742 | sxref_ptr->offset = temp->r.offset; | ||
743 | |||
744 | wpage += JFFS2_SUMMARY_XREF_SIZE; | ||
745 | break; | ||
746 | } | ||
747 | #endif | ||
620 | default : { | 748 | default : { |
621 | BUG(); /* unknown node in summary information */ | 749 | if ((je16_to_cpu(temp->u.nodetype) & JFFS2_COMPAT_MASK) |
750 | == JFFS2_FEATURE_RWCOMPAT_COPY) { | ||
751 | dbg_summary("Writing unknown RWCOMPAT_COPY node type %x\n", | ||
752 | je16_to_cpu(temp->u.nodetype)); | ||
753 | jffs2_sum_disable_collecting(c->summary); | ||
754 | } else { | ||
755 | BUG(); /* unknown node in summary information */ | ||
756 | } | ||
622 | } | 757 | } |
623 | } | 758 | } |
624 | 759 | ||
625 | temp = c->summary->sum_list_head; | 760 | c->summary->sum_list_head = temp->u.next; |
626 | c->summary->sum_list_head = c->summary->sum_list_head->u.next; | ||
627 | kfree(temp); | 761 | kfree(temp); |
628 | 762 | ||
629 | c->summary->sum_num--; | 763 | c->summary->sum_num--; |
@@ -645,25 +779,34 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
645 | vecs[1].iov_base = c->summary->sum_buf; | 779 | vecs[1].iov_base = c->summary->sum_buf; |
646 | vecs[1].iov_len = datasize; | 780 | vecs[1].iov_len = datasize; |
647 | 781 | ||
648 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", | 782 | sum_ofs = jeb->offset + c->sector_size - jeb->free_size; |
649 | jeb->offset + c->sector_size - jeb->free_size); | ||
650 | 783 | ||
651 | spin_unlock(&c->erase_completion_lock); | 784 | dbg_summary("JFFS2: writing out data to flash to pos : 0x%08x\n", |
652 | ret = jffs2_flash_writev(c, vecs, 2, jeb->offset + c->sector_size - | 785 | sum_ofs); |
653 | jeb->free_size, &retlen, 0); | ||
654 | spin_lock(&c->erase_completion_lock); | ||
655 | 786 | ||
787 | ret = jffs2_flash_writev(c, vecs, 2, sum_ofs, &retlen, 0); | ||
656 | 788 | ||
657 | if (ret || (retlen != infosize)) { | 789 | if (ret || (retlen != infosize)) { |
658 | JFFS2_WARNING("Write of %zd bytes at 0x%08x failed. returned %d, retlen %zd\n", | 790 | |
659 | infosize, jeb->offset + c->sector_size - jeb->free_size, ret, retlen); | 791 | JFFS2_WARNING("Write of %u bytes at 0x%08x failed. returned %d, retlen %zd\n", |
792 | infosize, sum_ofs, ret, retlen); | ||
793 | |||
794 | if (retlen) { | ||
795 | /* Waste remaining space */ | ||
796 | spin_lock(&c->erase_completion_lock); | ||
797 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_OBSOLETE, infosize, NULL); | ||
798 | spin_unlock(&c->erase_completion_lock); | ||
799 | } | ||
660 | 800 | ||
661 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; | 801 | c->summary->sum_size = JFFS2_SUMMARY_NOSUM_SIZE; |
662 | WASTED_SPACE(infosize); | ||
663 | 802 | ||
664 | return 1; | 803 | return 0; |
665 | } | 804 | } |
666 | 805 | ||
806 | spin_lock(&c->erase_completion_lock); | ||
807 | jffs2_link_node_ref(c, jeb, sum_ofs | REF_NORMAL, infosize, NULL); | ||
808 | spin_unlock(&c->erase_completion_lock); | ||
809 | |||
667 | return 0; | 810 | return 0; |
668 | } | 811 | } |
669 | 812 | ||
@@ -671,13 +814,16 @@ static int jffs2_sum_write_data(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
671 | 814 | ||
672 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | 815 | int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) |
673 | { | 816 | { |
674 | struct jffs2_raw_node_ref *summary_ref; | 817 | int datasize, infosize, padsize; |
675 | int datasize, infosize, padsize, ret; | ||
676 | struct jffs2_eraseblock *jeb; | 818 | struct jffs2_eraseblock *jeb; |
819 | int ret; | ||
677 | 820 | ||
678 | dbg_summary("called\n"); | 821 | dbg_summary("called\n"); |
679 | 822 | ||
823 | spin_unlock(&c->erase_completion_lock); | ||
824 | |||
680 | jeb = c->nextblock; | 825 | jeb = c->nextblock; |
826 | jffs2_prealloc_raw_node_refs(c, jeb, 1); | ||
681 | 827 | ||
682 | if (!c->summary->sum_num || !c->summary->sum_list_head) { | 828 | if (!c->summary->sum_num || !c->summary->sum_list_head) { |
683 | JFFS2_WARNING("Empty summary info!!!\n"); | 829 | JFFS2_WARNING("Empty summary info!!!\n"); |
@@ -696,35 +842,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c) | |||
696 | jffs2_sum_disable_collecting(c->summary); | 842 | jffs2_sum_disable_collecting(c->summary); |
697 | 843 | ||
698 | JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); | 844 | JFFS2_WARNING("Not enough space for summary, padsize = %d\n", padsize); |
845 | spin_lock(&c->erase_completion_lock); | ||
699 | return 0; | 846 | return 0; |
700 | } | 847 | } |
701 | 848 | ||
702 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); | 849 | ret = jffs2_sum_write_data(c, jeb, infosize, datasize, padsize); |
703 | if (ret) | ||
704 | return 0; /* can't write out summary, block is marked as NOSUM_SIZE */ | ||
705 | |||
706 | /* for ACCT_PARANOIA_CHECK */ | ||
707 | spin_unlock(&c->erase_completion_lock); | ||
708 | summary_ref = jffs2_alloc_raw_node_ref(); | ||
709 | spin_lock(&c->erase_completion_lock); | 850 | spin_lock(&c->erase_completion_lock); |
710 | 851 | return ret; | |
711 | if (!summary_ref) { | ||
712 | JFFS2_NOTICE("Failed to allocate node ref for summary\n"); | ||
713 | return -ENOMEM; | ||
714 | } | ||
715 | |||
716 | summary_ref->next_in_ino = NULL; | ||
717 | summary_ref->next_phys = NULL; | ||
718 | summary_ref->flash_offset = (jeb->offset + c->sector_size - jeb->free_size) | REF_NORMAL; | ||
719 | summary_ref->__totlen = infosize; | ||
720 | |||
721 | if (!jeb->first_node) | ||
722 | jeb->first_node = summary_ref; | ||
723 | if (jeb->last_node) | ||
724 | jeb->last_node->next_phys = summary_ref; | ||
725 | jeb->last_node = summary_ref; | ||
726 | |||
727 | USED_SPACE(infosize); | ||
728 | |||
729 | return 0; | ||
730 | } | 852 | } |
diff --git a/fs/jffs2/summary.h b/fs/jffs2/summary.h index b7a678be1709..6bf1f6aa4552 100644 --- a/fs/jffs2/summary.h +++ b/fs/jffs2/summary.h | |||
@@ -18,23 +18,6 @@ | |||
18 | #include <linux/uio.h> | 18 | #include <linux/uio.h> |
19 | #include <linux/jffs2.h> | 19 | #include <linux/jffs2.h> |
20 | 20 | ||
21 | #define DIRTY_SPACE(x) do { typeof(x) _x = (x); \ | ||
22 | c->free_size -= _x; c->dirty_size += _x; \ | ||
23 | jeb->free_size -= _x ; jeb->dirty_size += _x; \ | ||
24 | }while(0) | ||
25 | #define USED_SPACE(x) do { typeof(x) _x = (x); \ | ||
26 | c->free_size -= _x; c->used_size += _x; \ | ||
27 | jeb->free_size -= _x ; jeb->used_size += _x; \ | ||
28 | }while(0) | ||
29 | #define WASTED_SPACE(x) do { typeof(x) _x = (x); \ | ||
30 | c->free_size -= _x; c->wasted_size += _x; \ | ||
31 | jeb->free_size -= _x ; jeb->wasted_size += _x; \ | ||
32 | }while(0) | ||
33 | #define UNCHECKED_SPACE(x) do { typeof(x) _x = (x); \ | ||
34 | c->free_size -= _x; c->unchecked_size += _x; \ | ||
35 | jeb->free_size -= _x ; jeb->unchecked_size += _x; \ | ||
36 | }while(0) | ||
37 | |||
38 | #define BLK_STATE_ALLFF 0 | 21 | #define BLK_STATE_ALLFF 0 |
39 | #define BLK_STATE_CLEAN 1 | 22 | #define BLK_STATE_CLEAN 1 |
40 | #define BLK_STATE_PARTDIRTY 2 | 23 | #define BLK_STATE_PARTDIRTY 2 |
@@ -45,6 +28,8 @@ | |||
45 | #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff | 28 | #define JFFS2_SUMMARY_NOSUM_SIZE 0xffffffff |
46 | #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) | 29 | #define JFFS2_SUMMARY_INODE_SIZE (sizeof(struct jffs2_sum_inode_flash)) |
47 | #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) | 30 | #define JFFS2_SUMMARY_DIRENT_SIZE(x) (sizeof(struct jffs2_sum_dirent_flash) + (x)) |
31 | #define JFFS2_SUMMARY_XATTR_SIZE (sizeof(struct jffs2_sum_xattr_flash)) | ||
32 | #define JFFS2_SUMMARY_XREF_SIZE (sizeof(struct jffs2_sum_xref_flash)) | ||
48 | 33 | ||
49 | /* Summary structures used on flash */ | 34 | /* Summary structures used on flash */ |
50 | 35 | ||
@@ -75,11 +60,28 @@ struct jffs2_sum_dirent_flash | |||
75 | uint8_t name[0]; /* dirent name */ | 60 | uint8_t name[0]; /* dirent name */ |
76 | } __attribute__((packed)); | 61 | } __attribute__((packed)); |
77 | 62 | ||
63 | struct jffs2_sum_xattr_flash | ||
64 | { | ||
65 | jint16_t nodetype; /* == JFFS2_NODETYPE_XATR */ | ||
66 | jint32_t xid; /* xattr identifier */ | ||
67 | jint32_t version; /* version number */ | ||
68 | jint32_t offset; /* offset on jeb */ | ||
69 | jint32_t totlen; /* node length */ | ||
70 | } __attribute__((packed)); | ||
71 | |||
72 | struct jffs2_sum_xref_flash | ||
73 | { | ||
74 | jint16_t nodetype; /* == JFFS2_NODETYPE_XREF */ | ||
75 | jint32_t offset; /* offset on jeb */ | ||
76 | } __attribute__((packed)); | ||
77 | |||
78 | union jffs2_sum_flash | 78 | union jffs2_sum_flash |
79 | { | 79 | { |
80 | struct jffs2_sum_unknown_flash u; | 80 | struct jffs2_sum_unknown_flash u; |
81 | struct jffs2_sum_inode_flash i; | 81 | struct jffs2_sum_inode_flash i; |
82 | struct jffs2_sum_dirent_flash d; | 82 | struct jffs2_sum_dirent_flash d; |
83 | struct jffs2_sum_xattr_flash x; | ||
84 | struct jffs2_sum_xref_flash r; | ||
83 | }; | 85 | }; |
84 | 86 | ||
85 | /* Summary structures used in the memory */ | 87 | /* Summary structures used in the memory */ |
@@ -114,11 +116,30 @@ struct jffs2_sum_dirent_mem | |||
114 | uint8_t name[0]; /* dirent name */ | 116 | uint8_t name[0]; /* dirent name */ |
115 | } __attribute__((packed)); | 117 | } __attribute__((packed)); |
116 | 118 | ||
119 | struct jffs2_sum_xattr_mem | ||
120 | { | ||
121 | union jffs2_sum_mem *next; | ||
122 | jint16_t nodetype; | ||
123 | jint32_t xid; | ||
124 | jint32_t version; | ||
125 | jint32_t offset; | ||
126 | jint32_t totlen; | ||
127 | } __attribute__((packed)); | ||
128 | |||
129 | struct jffs2_sum_xref_mem | ||
130 | { | ||
131 | union jffs2_sum_mem *next; | ||
132 | jint16_t nodetype; | ||
133 | jint32_t offset; | ||
134 | } __attribute__((packed)); | ||
135 | |||
117 | union jffs2_sum_mem | 136 | union jffs2_sum_mem |
118 | { | 137 | { |
119 | struct jffs2_sum_unknown_mem u; | 138 | struct jffs2_sum_unknown_mem u; |
120 | struct jffs2_sum_inode_mem i; | 139 | struct jffs2_sum_inode_mem i; |
121 | struct jffs2_sum_dirent_mem d; | 140 | struct jffs2_sum_dirent_mem d; |
141 | struct jffs2_sum_xattr_mem x; | ||
142 | struct jffs2_sum_xref_mem r; | ||
122 | }; | 143 | }; |
123 | 144 | ||
124 | /* Summary related information stored in superblock */ | 145 | /* Summary related information stored in superblock */ |
@@ -159,8 +180,11 @@ int jffs2_sum_write_sumnode(struct jffs2_sb_info *c); | |||
159 | int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); | 180 | int jffs2_sum_add_padding_mem(struct jffs2_summary *s, uint32_t size); |
160 | int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); | 181 | int jffs2_sum_add_inode_mem(struct jffs2_summary *s, struct jffs2_raw_inode *ri, uint32_t ofs); |
161 | int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); | 182 | int jffs2_sum_add_dirent_mem(struct jffs2_summary *s, struct jffs2_raw_dirent *rd, uint32_t ofs); |
183 | int jffs2_sum_add_xattr_mem(struct jffs2_summary *s, struct jffs2_raw_xattr *rx, uint32_t ofs); | ||
184 | int jffs2_sum_add_xref_mem(struct jffs2_summary *s, struct jffs2_raw_xref *rr, uint32_t ofs); | ||
162 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, | 185 | int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, |
163 | uint32_t ofs, uint32_t *pseudo_random); | 186 | struct jffs2_raw_summary *summary, uint32_t sumlen, |
187 | uint32_t *pseudo_random); | ||
164 | 188 | ||
165 | #else /* SUMMARY DISABLED */ | 189 | #else /* SUMMARY DISABLED */ |
166 | 190 | ||
@@ -176,7 +200,9 @@ int jffs2_sum_scan_sumnode(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb | |||
176 | #define jffs2_sum_add_padding_mem(a,b) | 200 | #define jffs2_sum_add_padding_mem(a,b) |
177 | #define jffs2_sum_add_inode_mem(a,b,c) | 201 | #define jffs2_sum_add_inode_mem(a,b,c) |
178 | #define jffs2_sum_add_dirent_mem(a,b,c) | 202 | #define jffs2_sum_add_dirent_mem(a,b,c) |
179 | #define jffs2_sum_scan_sumnode(a,b,c,d) (0) | 203 | #define jffs2_sum_add_xattr_mem(a,b,c) |
204 | #define jffs2_sum_add_xref_mem(a,b,c) | ||
205 | #define jffs2_sum_scan_sumnode(a,b,c,d,e) (0) | ||
180 | 206 | ||
181 | #endif /* CONFIG_JFFS2_SUMMARY */ | 207 | #endif /* CONFIG_JFFS2_SUMMARY */ |
182 | 208 | ||
diff --git a/fs/jffs2/super.c b/fs/jffs2/super.c index ffd8e84b22cc..2378a662c256 100644 --- a/fs/jffs2/super.c +++ b/fs/jffs2/super.c | |||
@@ -111,9 +111,10 @@ static int jffs2_sb_set(struct super_block *sb, void *data) | |||
111 | return 0; | 111 | return 0; |
112 | } | 112 | } |
113 | 113 | ||
114 | static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, | 114 | static int jffs2_get_sb_mtd(struct file_system_type *fs_type, |
115 | int flags, const char *dev_name, | 115 | int flags, const char *dev_name, |
116 | void *data, struct mtd_info *mtd) | 116 | void *data, struct mtd_info *mtd, |
117 | struct vfsmount *mnt) | ||
117 | { | 118 | { |
118 | struct super_block *sb; | 119 | struct super_block *sb; |
119 | struct jffs2_sb_info *c; | 120 | struct jffs2_sb_info *c; |
@@ -121,19 +122,20 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, | |||
121 | 122 | ||
122 | c = kmalloc(sizeof(*c), GFP_KERNEL); | 123 | c = kmalloc(sizeof(*c), GFP_KERNEL); |
123 | if (!c) | 124 | if (!c) |
124 | return ERR_PTR(-ENOMEM); | 125 | return -ENOMEM; |
125 | memset(c, 0, sizeof(*c)); | 126 | memset(c, 0, sizeof(*c)); |
126 | c->mtd = mtd; | 127 | c->mtd = mtd; |
127 | 128 | ||
128 | sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); | 129 | sb = sget(fs_type, jffs2_sb_compare, jffs2_sb_set, c); |
129 | 130 | ||
130 | if (IS_ERR(sb)) | 131 | if (IS_ERR(sb)) |
131 | goto out_put; | 132 | goto out_error; |
132 | 133 | ||
133 | if (sb->s_root) { | 134 | if (sb->s_root) { |
134 | /* New mountpoint for JFFS2 which is already mounted */ | 135 | /* New mountpoint for JFFS2 which is already mounted */ |
135 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", | 136 | D1(printk(KERN_DEBUG "jffs2_get_sb_mtd(): Device %d (\"%s\") is already mounted\n", |
136 | mtd->index, mtd->name)); | 137 | mtd->index, mtd->name)); |
138 | ret = simple_set_mnt(mnt, sb); | ||
137 | goto out_put; | 139 | goto out_put; |
138 | } | 140 | } |
139 | 141 | ||
@@ -151,51 +153,57 @@ static struct super_block *jffs2_get_sb_mtd(struct file_system_type *fs_type, | |||
151 | 153 | ||
152 | sb->s_op = &jffs2_super_operations; | 154 | sb->s_op = &jffs2_super_operations; |
153 | sb->s_flags = flags | MS_NOATIME; | 155 | sb->s_flags = flags | MS_NOATIME; |
154 | 156 | sb->s_xattr = jffs2_xattr_handlers; | |
157 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
158 | sb->s_flags |= MS_POSIXACL; | ||
159 | #endif | ||
155 | ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); | 160 | ret = jffs2_do_fill_super(sb, data, flags & MS_SILENT ? 1 : 0); |
156 | 161 | ||
157 | if (ret) { | 162 | if (ret) { |
158 | /* Failure case... */ | 163 | /* Failure case... */ |
159 | up_write(&sb->s_umount); | 164 | up_write(&sb->s_umount); |
160 | deactivate_super(sb); | 165 | deactivate_super(sb); |
161 | return ERR_PTR(ret); | 166 | return ret; |
162 | } | 167 | } |
163 | 168 | ||
164 | sb->s_flags |= MS_ACTIVE; | 169 | sb->s_flags |= MS_ACTIVE; |
165 | return sb; | 170 | return simple_set_mnt(mnt, sb); |
166 | 171 | ||
172 | out_error: | ||
173 | ret = PTR_ERR(sb); | ||
167 | out_put: | 174 | out_put: |
168 | kfree(c); | 175 | kfree(c); |
169 | put_mtd_device(mtd); | 176 | put_mtd_device(mtd); |
170 | 177 | ||
171 | return sb; | 178 | return ret; |
172 | } | 179 | } |
173 | 180 | ||
174 | static struct super_block *jffs2_get_sb_mtdnr(struct file_system_type *fs_type, | 181 | static int jffs2_get_sb_mtdnr(struct file_system_type *fs_type, |
175 | int flags, const char *dev_name, | 182 | int flags, const char *dev_name, |
176 | void *data, int mtdnr) | 183 | void *data, int mtdnr, |
184 | struct vfsmount *mnt) | ||
177 | { | 185 | { |
178 | struct mtd_info *mtd; | 186 | struct mtd_info *mtd; |
179 | 187 | ||
180 | mtd = get_mtd_device(NULL, mtdnr); | 188 | mtd = get_mtd_device(NULL, mtdnr); |
181 | if (!mtd) { | 189 | if (!mtd) { |
182 | D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); | 190 | D1(printk(KERN_DEBUG "jffs2: MTD device #%u doesn't appear to exist\n", mtdnr)); |
183 | return ERR_PTR(-EINVAL); | 191 | return -EINVAL; |
184 | } | 192 | } |
185 | 193 | ||
186 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); | 194 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); |
187 | } | 195 | } |
188 | 196 | ||
189 | static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | 197 | static int jffs2_get_sb(struct file_system_type *fs_type, |
190 | int flags, const char *dev_name, | 198 | int flags, const char *dev_name, |
191 | void *data) | 199 | void *data, struct vfsmount *mnt) |
192 | { | 200 | { |
193 | int err; | 201 | int err; |
194 | struct nameidata nd; | 202 | struct nameidata nd; |
195 | int mtdnr; | 203 | int mtdnr; |
196 | 204 | ||
197 | if (!dev_name) | 205 | if (!dev_name) |
198 | return ERR_PTR(-EINVAL); | 206 | return -EINVAL; |
199 | 207 | ||
200 | D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); | 208 | D1(printk(KERN_DEBUG "jffs2_get_sb(): dev_name \"%s\"\n", dev_name)); |
201 | 209 | ||
@@ -217,7 +225,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | |||
217 | mtd = get_mtd_device(NULL, mtdnr); | 225 | mtd = get_mtd_device(NULL, mtdnr); |
218 | if (mtd) { | 226 | if (mtd) { |
219 | if (!strcmp(mtd->name, dev_name+4)) | 227 | if (!strcmp(mtd->name, dev_name+4)) |
220 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd); | 228 | return jffs2_get_sb_mtd(fs_type, flags, dev_name, data, mtd, mnt); |
221 | put_mtd_device(mtd); | 229 | put_mtd_device(mtd); |
222 | } | 230 | } |
223 | } | 231 | } |
@@ -230,7 +238,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | |||
230 | if (!*endptr) { | 238 | if (!*endptr) { |
231 | /* It was a valid number */ | 239 | /* It was a valid number */ |
232 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); | 240 | D1(printk(KERN_DEBUG "jffs2_get_sb(): mtd%%d, mtdnr %d\n", mtdnr)); |
233 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); | 241 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); |
234 | } | 242 | } |
235 | } | 243 | } |
236 | } | 244 | } |
@@ -244,7 +252,7 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | |||
244 | err, nd.dentry->d_inode)); | 252 | err, nd.dentry->d_inode)); |
245 | 253 | ||
246 | if (err) | 254 | if (err) |
247 | return ERR_PTR(err); | 255 | return err; |
248 | 256 | ||
249 | err = -EINVAL; | 257 | err = -EINVAL; |
250 | 258 | ||
@@ -266,11 +274,11 @@ static struct super_block *jffs2_get_sb(struct file_system_type *fs_type, | |||
266 | mtdnr = iminor(nd.dentry->d_inode); | 274 | mtdnr = iminor(nd.dentry->d_inode); |
267 | path_release(&nd); | 275 | path_release(&nd); |
268 | 276 | ||
269 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr); | 277 | return jffs2_get_sb_mtdnr(fs_type, flags, dev_name, data, mtdnr, mnt); |
270 | 278 | ||
271 | out: | 279 | out: |
272 | path_release(&nd); | 280 | path_release(&nd); |
273 | return ERR_PTR(err); | 281 | return err; |
274 | } | 282 | } |
275 | 283 | ||
276 | static void jffs2_put_super (struct super_block *sb) | 284 | static void jffs2_put_super (struct super_block *sb) |
@@ -293,6 +301,7 @@ static void jffs2_put_super (struct super_block *sb) | |||
293 | kfree(c->blocks); | 301 | kfree(c->blocks); |
294 | jffs2_flash_cleanup(c); | 302 | jffs2_flash_cleanup(c); |
295 | kfree(c->inocache_list); | 303 | kfree(c->inocache_list); |
304 | jffs2_clear_xattr_subsystem(c); | ||
296 | if (c->mtd->sync) | 305 | if (c->mtd->sync) |
297 | c->mtd->sync(c->mtd); | 306 | c->mtd->sync(c->mtd); |
298 | 307 | ||
@@ -320,6 +329,18 @@ static int __init init_jffs2_fs(void) | |||
320 | { | 329 | { |
321 | int ret; | 330 | int ret; |
322 | 331 | ||
332 | /* Paranoia checks for on-medium structures. If we ask GCC | ||
333 | to pack them with __attribute__((packed)) then it _also_ | ||
334 | assumes that they're not aligned -- so it emits crappy | ||
335 | code on some architectures. Ideally we want an attribute | ||
336 | which means just 'no padding', without the alignment | ||
337 | thing. But GCC doesn't have that -- we have to just | ||
338 | hope the structs are the right sizes, instead. */ | ||
339 | BUG_ON(sizeof(struct jffs2_unknown_node) != 12); | ||
340 | BUG_ON(sizeof(struct jffs2_raw_dirent) != 40); | ||
341 | BUG_ON(sizeof(struct jffs2_raw_inode) != 68); | ||
342 | BUG_ON(sizeof(struct jffs2_raw_summary) != 32); | ||
343 | |||
323 | printk(KERN_INFO "JFFS2 version 2.2." | 344 | printk(KERN_INFO "JFFS2 version 2.2." |
324 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER | 345 | #ifdef CONFIG_JFFS2_FS_WRITEBUFFER |
325 | " (NAND)" | 346 | " (NAND)" |
@@ -327,7 +348,7 @@ static int __init init_jffs2_fs(void) | |||
327 | #ifdef CONFIG_JFFS2_SUMMARY | 348 | #ifdef CONFIG_JFFS2_SUMMARY |
328 | " (SUMMARY) " | 349 | " (SUMMARY) " |
329 | #endif | 350 | #endif |
330 | " (C) 2001-2003 Red Hat, Inc.\n"); | 351 | " (C) 2001-2006 Red Hat, Inc.\n"); |
331 | 352 | ||
332 | jffs2_inode_cachep = kmem_cache_create("jffs2_i", | 353 | jffs2_inode_cachep = kmem_cache_create("jffs2_i", |
333 | sizeof(struct jffs2_inode_info), | 354 | sizeof(struct jffs2_inode_info), |
diff --git a/fs/jffs2/symlink.c b/fs/jffs2/symlink.c index d55754fe8925..fc211b6e9b03 100644 --- a/fs/jffs2/symlink.c +++ b/fs/jffs2/symlink.c | |||
@@ -24,7 +24,12 @@ struct inode_operations jffs2_symlink_inode_operations = | |||
24 | { | 24 | { |
25 | .readlink = generic_readlink, | 25 | .readlink = generic_readlink, |
26 | .follow_link = jffs2_follow_link, | 26 | .follow_link = jffs2_follow_link, |
27 | .setattr = jffs2_setattr | 27 | .permission = jffs2_permission, |
28 | .setattr = jffs2_setattr, | ||
29 | .setxattr = jffs2_setxattr, | ||
30 | .getxattr = jffs2_getxattr, | ||
31 | .listxattr = jffs2_listxattr, | ||
32 | .removexattr = jffs2_removexattr | ||
28 | }; | 33 | }; |
29 | 34 | ||
30 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) | 35 | static void *jffs2_follow_link(struct dentry *dentry, struct nameidata *nd) |
diff --git a/fs/jffs2/wbuf.c b/fs/jffs2/wbuf.c index 4cebf0e57c46..a7f153f79ecb 100644 --- a/fs/jffs2/wbuf.c +++ b/fs/jffs2/wbuf.c | |||
@@ -156,69 +156,130 @@ static void jffs2_block_refile(struct jffs2_sb_info *c, struct jffs2_eraseblock | |||
156 | jffs2_erase_pending_trigger(c); | 156 | jffs2_erase_pending_trigger(c); |
157 | } | 157 | } |
158 | 158 | ||
159 | /* Adjust its size counts accordingly */ | 159 | if (!jffs2_prealloc_raw_node_refs(c, jeb, 1)) { |
160 | c->wasted_size += jeb->free_size; | 160 | uint32_t oldfree = jeb->free_size; |
161 | c->free_size -= jeb->free_size; | 161 | |
162 | jeb->wasted_size += jeb->free_size; | 162 | jffs2_link_node_ref(c, jeb, |
163 | jeb->free_size = 0; | 163 | (jeb->offset+c->sector_size-oldfree) | REF_OBSOLETE, |
164 | oldfree, NULL); | ||
165 | /* convert to wasted */ | ||
166 | c->wasted_size += oldfree; | ||
167 | jeb->wasted_size += oldfree; | ||
168 | c->dirty_size -= oldfree; | ||
169 | jeb->dirty_size -= oldfree; | ||
170 | } | ||
164 | 171 | ||
165 | jffs2_dbg_dump_block_lists_nolock(c); | 172 | jffs2_dbg_dump_block_lists_nolock(c); |
166 | jffs2_dbg_acct_sanity_check_nolock(c,jeb); | 173 | jffs2_dbg_acct_sanity_check_nolock(c,jeb); |
167 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | 174 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); |
168 | } | 175 | } |
169 | 176 | ||
177 | static struct jffs2_raw_node_ref **jffs2_incore_replace_raw(struct jffs2_sb_info *c, | ||
178 | struct jffs2_inode_info *f, | ||
179 | struct jffs2_raw_node_ref *raw, | ||
180 | union jffs2_node_union *node) | ||
181 | { | ||
182 | struct jffs2_node_frag *frag; | ||
183 | struct jffs2_full_dirent *fd; | ||
184 | |||
185 | dbg_noderef("incore_replace_raw: node at %p is {%04x,%04x}\n", | ||
186 | node, je16_to_cpu(node->u.magic), je16_to_cpu(node->u.nodetype)); | ||
187 | |||
188 | BUG_ON(je16_to_cpu(node->u.magic) != 0x1985 && | ||
189 | je16_to_cpu(node->u.magic) != 0); | ||
190 | |||
191 | switch (je16_to_cpu(node->u.nodetype)) { | ||
192 | case JFFS2_NODETYPE_INODE: | ||
193 | if (f->metadata && f->metadata->raw == raw) { | ||
194 | dbg_noderef("Will replace ->raw in f->metadata at %p\n", f->metadata); | ||
195 | return &f->metadata->raw; | ||
196 | } | ||
197 | frag = jffs2_lookup_node_frag(&f->fragtree, je32_to_cpu(node->i.offset)); | ||
198 | BUG_ON(!frag); | ||
199 | /* Find a frag which refers to the full_dnode we want to modify */ | ||
200 | while (!frag->node || frag->node->raw != raw) { | ||
201 | frag = frag_next(frag); | ||
202 | BUG_ON(!frag); | ||
203 | } | ||
204 | dbg_noderef("Will replace ->raw in full_dnode at %p\n", frag->node); | ||
205 | return &frag->node->raw; | ||
206 | |||
207 | case JFFS2_NODETYPE_DIRENT: | ||
208 | for (fd = f->dents; fd; fd = fd->next) { | ||
209 | if (fd->raw == raw) { | ||
210 | dbg_noderef("Will replace ->raw in full_dirent at %p\n", fd); | ||
211 | return &fd->raw; | ||
212 | } | ||
213 | } | ||
214 | BUG(); | ||
215 | |||
216 | default: | ||
217 | dbg_noderef("Don't care about replacing raw for nodetype %x\n", | ||
218 | je16_to_cpu(node->u.nodetype)); | ||
219 | break; | ||
220 | } | ||
221 | return NULL; | ||
222 | } | ||
223 | |||
170 | /* Recover from failure to write wbuf. Recover the nodes up to the | 224 | /* Recover from failure to write wbuf. Recover the nodes up to the |
171 | * wbuf, not the one which we were starting to try to write. */ | 225 | * wbuf, not the one which we were starting to try to write. */ |
172 | 226 | ||
173 | static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | 227 | static void jffs2_wbuf_recover(struct jffs2_sb_info *c) |
174 | { | 228 | { |
175 | struct jffs2_eraseblock *jeb, *new_jeb; | 229 | struct jffs2_eraseblock *jeb, *new_jeb; |
176 | struct jffs2_raw_node_ref **first_raw, **raw; | 230 | struct jffs2_raw_node_ref *raw, *next, *first_raw = NULL; |
177 | size_t retlen; | 231 | size_t retlen; |
178 | int ret; | 232 | int ret; |
233 | int nr_refile = 0; | ||
179 | unsigned char *buf; | 234 | unsigned char *buf; |
180 | uint32_t start, end, ofs, len; | 235 | uint32_t start, end, ofs, len; |
181 | 236 | ||
182 | spin_lock(&c->erase_completion_lock); | ||
183 | |||
184 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | 237 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; |
185 | 238 | ||
239 | spin_lock(&c->erase_completion_lock); | ||
186 | jffs2_block_refile(c, jeb, REFILE_NOTEMPTY); | 240 | jffs2_block_refile(c, jeb, REFILE_NOTEMPTY); |
241 | spin_unlock(&c->erase_completion_lock); | ||
242 | |||
243 | BUG_ON(!ref_obsolete(jeb->last_node)); | ||
187 | 244 | ||
188 | /* Find the first node to be recovered, by skipping over every | 245 | /* Find the first node to be recovered, by skipping over every |
189 | node which ends before the wbuf starts, or which is obsolete. */ | 246 | node which ends before the wbuf starts, or which is obsolete. */ |
190 | first_raw = &jeb->first_node; | 247 | for (next = raw = jeb->first_node; next; raw = next) { |
191 | while (*first_raw && | 248 | next = ref_next(raw); |
192 | (ref_obsolete(*first_raw) || | 249 | |
193 | (ref_offset(*first_raw)+ref_totlen(c, jeb, *first_raw)) < c->wbuf_ofs)) { | 250 | if (ref_obsolete(raw) || |
194 | D1(printk(KERN_DEBUG "Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", | 251 | (next && ref_offset(next) <= c->wbuf_ofs)) { |
195 | ref_offset(*first_raw), ref_flags(*first_raw), | 252 | dbg_noderef("Skipping node at 0x%08x(%d)-0x%08x which is either before 0x%08x or obsolete\n", |
196 | (ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw)), | 253 | ref_offset(raw), ref_flags(raw), |
197 | c->wbuf_ofs)); | 254 | (ref_offset(raw) + ref_totlen(c, jeb, raw)), |
198 | first_raw = &(*first_raw)->next_phys; | 255 | c->wbuf_ofs); |
256 | continue; | ||
257 | } | ||
258 | dbg_noderef("First node to be recovered is at 0x%08x(%d)-0x%08x\n", | ||
259 | ref_offset(raw), ref_flags(raw), | ||
260 | (ref_offset(raw) + ref_totlen(c, jeb, raw))); | ||
261 | |||
262 | first_raw = raw; | ||
263 | break; | ||
199 | } | 264 | } |
200 | 265 | ||
201 | if (!*first_raw) { | 266 | if (!first_raw) { |
202 | /* All nodes were obsolete. Nothing to recover. */ | 267 | /* All nodes were obsolete. Nothing to recover. */ |
203 | D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n")); | 268 | D1(printk(KERN_DEBUG "No non-obsolete nodes to be recovered. Just filing block bad\n")); |
204 | spin_unlock(&c->erase_completion_lock); | 269 | c->wbuf_len = 0; |
205 | return; | 270 | return; |
206 | } | 271 | } |
207 | 272 | ||
208 | start = ref_offset(*first_raw); | 273 | start = ref_offset(first_raw); |
209 | end = ref_offset(*first_raw) + ref_totlen(c, jeb, *first_raw); | 274 | end = ref_offset(jeb->last_node); |
210 | 275 | nr_refile = 1; | |
211 | /* Find the last node to be recovered */ | ||
212 | raw = first_raw; | ||
213 | while ((*raw)) { | ||
214 | if (!ref_obsolete(*raw)) | ||
215 | end = ref_offset(*raw) + ref_totlen(c, jeb, *raw); | ||
216 | 276 | ||
217 | raw = &(*raw)->next_phys; | 277 | /* Count the number of refs which need to be copied */ |
218 | } | 278 | while ((raw = ref_next(raw)) != jeb->last_node) |
219 | spin_unlock(&c->erase_completion_lock); | 279 | nr_refile++; |
220 | 280 | ||
221 | D1(printk(KERN_DEBUG "wbuf recover %08x-%08x\n", start, end)); | 281 | dbg_noderef("wbuf recover %08x-%08x (%d bytes in %d nodes)\n", |
282 | start, end, end - start, nr_refile); | ||
222 | 283 | ||
223 | buf = NULL; | 284 | buf = NULL; |
224 | if (start < c->wbuf_ofs) { | 285 | if (start < c->wbuf_ofs) { |
@@ -233,28 +294,37 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
233 | } | 294 | } |
234 | 295 | ||
235 | /* Do the read... */ | 296 | /* Do the read... */ |
236 | if (jffs2_cleanmarker_oob(c)) | 297 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); |
237 | ret = c->mtd->read_ecc(c->mtd, start, c->wbuf_ofs - start, &retlen, buf, NULL, c->oobinfo); | ||
238 | else | ||
239 | ret = c->mtd->read(c->mtd, start, c->wbuf_ofs - start, &retlen, buf); | ||
240 | 298 | ||
241 | if (ret == -EBADMSG && retlen == c->wbuf_ofs - start) { | 299 | /* ECC recovered ? */ |
242 | /* ECC recovered */ | 300 | if ((ret == -EUCLEAN || ret == -EBADMSG) && |
301 | (retlen == c->wbuf_ofs - start)) | ||
243 | ret = 0; | 302 | ret = 0; |
244 | } | 303 | |
245 | if (ret || retlen != c->wbuf_ofs - start) { | 304 | if (ret || retlen != c->wbuf_ofs - start) { |
246 | printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); | 305 | printk(KERN_CRIT "Old data are already lost in wbuf recovery. Data loss ensues.\n"); |
247 | 306 | ||
248 | kfree(buf); | 307 | kfree(buf); |
249 | buf = NULL; | 308 | buf = NULL; |
250 | read_failed: | 309 | read_failed: |
251 | first_raw = &(*first_raw)->next_phys; | 310 | first_raw = ref_next(first_raw); |
311 | nr_refile--; | ||
312 | while (first_raw && ref_obsolete(first_raw)) { | ||
313 | first_raw = ref_next(first_raw); | ||
314 | nr_refile--; | ||
315 | } | ||
316 | |||
252 | /* If this was the only node to be recovered, give up */ | 317 | /* If this was the only node to be recovered, give up */ |
253 | if (!(*first_raw)) | 318 | if (!first_raw) { |
319 | c->wbuf_len = 0; | ||
254 | return; | 320 | return; |
321 | } | ||
255 | 322 | ||
256 | /* It wasn't. Go on and try to recover nodes complete in the wbuf */ | 323 | /* It wasn't. Go on and try to recover nodes complete in the wbuf */ |
257 | start = ref_offset(*first_raw); | 324 | start = ref_offset(first_raw); |
325 | dbg_noderef("wbuf now recover %08x-%08x (%d bytes in %d nodes)\n", | ||
326 | start, end, end - start, nr_refile); | ||
327 | |||
258 | } else { | 328 | } else { |
259 | /* Read succeeded. Copy the remaining data from the wbuf */ | 329 | /* Read succeeded. Copy the remaining data from the wbuf */ |
260 | memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs); | 330 | memcpy(buf + (c->wbuf_ofs - start), c->wbuf, end - c->wbuf_ofs); |
@@ -263,14 +333,23 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
263 | /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards. | 333 | /* OK... we're to rewrite (end-start) bytes of data from first_raw onwards. |
264 | Either 'buf' contains the data, or we find it in the wbuf */ | 334 | Either 'buf' contains the data, or we find it in the wbuf */ |
265 | 335 | ||
266 | |||
267 | /* ... and get an allocation of space from a shiny new block instead */ | 336 | /* ... and get an allocation of space from a shiny new block instead */ |
268 | ret = jffs2_reserve_space_gc(c, end-start, &ofs, &len, JFFS2_SUMMARY_NOSUM_SIZE); | 337 | ret = jffs2_reserve_space_gc(c, end-start, &len, JFFS2_SUMMARY_NOSUM_SIZE); |
269 | if (ret) { | 338 | if (ret) { |
270 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); | 339 | printk(KERN_WARNING "Failed to allocate space for wbuf recovery. Data loss ensues.\n"); |
271 | kfree(buf); | 340 | kfree(buf); |
272 | return; | 341 | return; |
273 | } | 342 | } |
343 | |||
344 | ret = jffs2_prealloc_raw_node_refs(c, c->nextblock, nr_refile); | ||
345 | if (ret) { | ||
346 | printk(KERN_WARNING "Failed to allocate node refs for wbuf recovery. Data loss ensues.\n"); | ||
347 | kfree(buf); | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | ofs = write_ofs(c); | ||
352 | |||
274 | if (end-start >= c->wbuf_pagesize) { | 353 | if (end-start >= c->wbuf_pagesize) { |
275 | /* Need to do another write immediately, but it's possible | 354 | /* Need to do another write immediately, but it's possible |
276 | that this is just because the wbuf itself is completely | 355 | that this is just because the wbuf itself is completely |
@@ -288,36 +367,22 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
288 | if (breakme++ == 20) { | 367 | if (breakme++ == 20) { |
289 | printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs); | 368 | printk(KERN_NOTICE "Faking write error at 0x%08x\n", ofs); |
290 | breakme = 0; | 369 | breakme = 0; |
291 | c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, | 370 | c->mtd->write(c->mtd, ofs, towrite, &retlen, |
292 | brokenbuf, NULL, c->oobinfo); | 371 | brokenbuf); |
293 | ret = -EIO; | 372 | ret = -EIO; |
294 | } else | 373 | } else |
295 | #endif | 374 | #endif |
296 | if (jffs2_cleanmarker_oob(c)) | 375 | ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, |
297 | ret = c->mtd->write_ecc(c->mtd, ofs, towrite, &retlen, | 376 | rewrite_buf); |
298 | rewrite_buf, NULL, c->oobinfo); | ||
299 | else | ||
300 | ret = c->mtd->write(c->mtd, ofs, towrite, &retlen, rewrite_buf); | ||
301 | 377 | ||
302 | if (ret || retlen != towrite) { | 378 | if (ret || retlen != towrite) { |
303 | /* Argh. We tried. Really we did. */ | 379 | /* Argh. We tried. Really we did. */ |
304 | printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); | 380 | printk(KERN_CRIT "Recovery of wbuf failed due to a second write error\n"); |
305 | kfree(buf); | 381 | kfree(buf); |
306 | 382 | ||
307 | if (retlen) { | 383 | if (retlen) |
308 | struct jffs2_raw_node_ref *raw2; | 384 | jffs2_add_physical_node_ref(c, ofs | REF_OBSOLETE, ref_totlen(c, jeb, first_raw), NULL); |
309 | |||
310 | raw2 = jffs2_alloc_raw_node_ref(); | ||
311 | if (!raw2) | ||
312 | return; | ||
313 | 385 | ||
314 | raw2->flash_offset = ofs | REF_OBSOLETE; | ||
315 | raw2->__totlen = ref_totlen(c, jeb, *first_raw); | ||
316 | raw2->next_phys = NULL; | ||
317 | raw2->next_in_ino = NULL; | ||
318 | |||
319 | jffs2_add_physical_node_ref(c, raw2); | ||
320 | } | ||
321 | return; | 386 | return; |
322 | } | 387 | } |
323 | printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); | 388 | printk(KERN_NOTICE "Recovery of wbuf succeeded to %08x\n", ofs); |
@@ -326,12 +391,10 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
326 | c->wbuf_ofs = ofs + towrite; | 391 | c->wbuf_ofs = ofs + towrite; |
327 | memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); | 392 | memmove(c->wbuf, rewrite_buf + towrite, c->wbuf_len); |
328 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ | 393 | /* Don't muck about with c->wbuf_inodes. False positives are harmless. */ |
329 | kfree(buf); | ||
330 | } else { | 394 | } else { |
331 | /* OK, now we're left with the dregs in whichever buffer we're using */ | 395 | /* OK, now we're left with the dregs in whichever buffer we're using */ |
332 | if (buf) { | 396 | if (buf) { |
333 | memcpy(c->wbuf, buf, end-start); | 397 | memcpy(c->wbuf, buf, end-start); |
334 | kfree(buf); | ||
335 | } else { | 398 | } else { |
336 | memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start); | 399 | memmove(c->wbuf, c->wbuf + (start - c->wbuf_ofs), end - start); |
337 | } | 400 | } |
@@ -343,62 +406,111 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
343 | new_jeb = &c->blocks[ofs / c->sector_size]; | 406 | new_jeb = &c->blocks[ofs / c->sector_size]; |
344 | 407 | ||
345 | spin_lock(&c->erase_completion_lock); | 408 | spin_lock(&c->erase_completion_lock); |
346 | if (new_jeb->first_node) { | 409 | for (raw = first_raw; raw != jeb->last_node; raw = ref_next(raw)) { |
347 | /* Odd, but possible with ST flash later maybe */ | 410 | uint32_t rawlen = ref_totlen(c, jeb, raw); |
348 | new_jeb->last_node->next_phys = *first_raw; | 411 | struct jffs2_inode_cache *ic; |
349 | } else { | 412 | struct jffs2_raw_node_ref *new_ref; |
350 | new_jeb->first_node = *first_raw; | 413 | struct jffs2_raw_node_ref **adjust_ref = NULL; |
351 | } | 414 | struct jffs2_inode_info *f = NULL; |
352 | |||
353 | raw = first_raw; | ||
354 | while (*raw) { | ||
355 | uint32_t rawlen = ref_totlen(c, jeb, *raw); | ||
356 | 415 | ||
357 | D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n", | 416 | D1(printk(KERN_DEBUG "Refiling block of %08x at %08x(%d) to %08x\n", |
358 | rawlen, ref_offset(*raw), ref_flags(*raw), ofs)); | 417 | rawlen, ref_offset(raw), ref_flags(raw), ofs)); |
418 | |||
419 | ic = jffs2_raw_ref_to_ic(raw); | ||
420 | |||
421 | /* Ick. This XATTR mess should be fixed shortly... */ | ||
422 | if (ic && ic->class == RAWNODE_CLASS_XATTR_DATUM) { | ||
423 | struct jffs2_xattr_datum *xd = (void *)ic; | ||
424 | BUG_ON(xd->node != raw); | ||
425 | adjust_ref = &xd->node; | ||
426 | raw->next_in_ino = NULL; | ||
427 | ic = NULL; | ||
428 | } else if (ic && ic->class == RAWNODE_CLASS_XATTR_REF) { | ||
429 | struct jffs2_xattr_datum *xr = (void *)ic; | ||
430 | BUG_ON(xr->node != raw); | ||
431 | adjust_ref = &xr->node; | ||
432 | raw->next_in_ino = NULL; | ||
433 | ic = NULL; | ||
434 | } else if (ic && ic->class == RAWNODE_CLASS_INODE_CACHE) { | ||
435 | struct jffs2_raw_node_ref **p = &ic->nodes; | ||
436 | |||
437 | /* Remove the old node from the per-inode list */ | ||
438 | while (*p && *p != (void *)ic) { | ||
439 | if (*p == raw) { | ||
440 | (*p) = (raw->next_in_ino); | ||
441 | raw->next_in_ino = NULL; | ||
442 | break; | ||
443 | } | ||
444 | p = &((*p)->next_in_ino); | ||
445 | } | ||
359 | 446 | ||
360 | if (ref_obsolete(*raw)) { | 447 | if (ic->state == INO_STATE_PRESENT && !ref_obsolete(raw)) { |
361 | /* Shouldn't really happen much */ | 448 | /* If it's an in-core inode, then we have to adjust any |
362 | new_jeb->dirty_size += rawlen; | 449 | full_dirent or full_dnode structure to point to the |
363 | new_jeb->free_size -= rawlen; | 450 | new version instead of the old */ |
364 | c->dirty_size += rawlen; | 451 | f = jffs2_gc_fetch_inode(c, ic->ino, ic->nlink); |
365 | } else { | 452 | if (IS_ERR(f)) { |
366 | new_jeb->used_size += rawlen; | 453 | /* Should never happen; it _must_ be present */ |
367 | new_jeb->free_size -= rawlen; | 454 | JFFS2_ERROR("Failed to iget() ino #%u, err %ld\n", |
455 | ic->ino, PTR_ERR(f)); | ||
456 | BUG(); | ||
457 | } | ||
458 | /* We don't lock f->sem. There's a number of ways we could | ||
459 | end up in here with it already being locked, and nobody's | ||
460 | going to modify it on us anyway because we hold the | ||
461 | alloc_sem. We're only changing one ->raw pointer too, | ||
462 | which we can get away with without upsetting readers. */ | ||
463 | adjust_ref = jffs2_incore_replace_raw(c, f, raw, | ||
464 | (void *)(buf?:c->wbuf) + (ref_offset(raw) - start)); | ||
465 | } else if (unlikely(ic->state != INO_STATE_PRESENT && | ||
466 | ic->state != INO_STATE_CHECKEDABSENT && | ||
467 | ic->state != INO_STATE_GC)) { | ||
468 | JFFS2_ERROR("Inode #%u is in strange state %d!\n", ic->ino, ic->state); | ||
469 | BUG(); | ||
470 | } | ||
471 | } | ||
472 | |||
473 | new_ref = jffs2_link_node_ref(c, new_jeb, ofs | ref_flags(raw), rawlen, ic); | ||
474 | |||
475 | if (adjust_ref) { | ||
476 | BUG_ON(*adjust_ref != raw); | ||
477 | *adjust_ref = new_ref; | ||
478 | } | ||
479 | if (f) | ||
480 | jffs2_gc_release_inode(c, f); | ||
481 | |||
482 | if (!ref_obsolete(raw)) { | ||
368 | jeb->dirty_size += rawlen; | 483 | jeb->dirty_size += rawlen; |
369 | jeb->used_size -= rawlen; | 484 | jeb->used_size -= rawlen; |
370 | c->dirty_size += rawlen; | 485 | c->dirty_size += rawlen; |
486 | c->used_size -= rawlen; | ||
487 | raw->flash_offset = ref_offset(raw) | REF_OBSOLETE; | ||
488 | BUG_ON(raw->next_in_ino); | ||
371 | } | 489 | } |
372 | c->free_size -= rawlen; | ||
373 | (*raw)->flash_offset = ofs | ref_flags(*raw); | ||
374 | ofs += rawlen; | 490 | ofs += rawlen; |
375 | new_jeb->last_node = *raw; | ||
376 | |||
377 | raw = &(*raw)->next_phys; | ||
378 | } | 491 | } |
379 | 492 | ||
493 | kfree(buf); | ||
494 | |||
380 | /* Fix up the original jeb now it's on the bad_list */ | 495 | /* Fix up the original jeb now it's on the bad_list */ |
381 | *first_raw = NULL; | 496 | if (first_raw == jeb->first_node) { |
382 | if (first_raw == &jeb->first_node) { | ||
383 | jeb->last_node = NULL; | ||
384 | D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); | 497 | D1(printk(KERN_DEBUG "Failing block at %08x is now empty. Moving to erase_pending_list\n", jeb->offset)); |
385 | list_del(&jeb->list); | 498 | list_del(&jeb->list); |
386 | list_add(&jeb->list, &c->erase_pending_list); | 499 | list_add(&jeb->list, &c->erase_pending_list); |
387 | c->nr_erasing_blocks++; | 500 | c->nr_erasing_blocks++; |
388 | jffs2_erase_pending_trigger(c); | 501 | jffs2_erase_pending_trigger(c); |
389 | } | 502 | } |
390 | else | ||
391 | jeb->last_node = container_of(first_raw, struct jffs2_raw_node_ref, next_phys); | ||
392 | 503 | ||
393 | jffs2_dbg_acct_sanity_check_nolock(c, jeb); | 504 | jffs2_dbg_acct_sanity_check_nolock(c, jeb); |
394 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); | 505 | jffs2_dbg_acct_paranoia_check_nolock(c, jeb); |
395 | 506 | ||
396 | jffs2_dbg_acct_sanity_check_nolock(c, new_jeb); | 507 | jffs2_dbg_acct_sanity_check_nolock(c, new_jeb); |
397 | jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb); | 508 | jffs2_dbg_acct_paranoia_check_nolock(c, new_jeb); |
398 | 509 | ||
399 | spin_unlock(&c->erase_completion_lock); | 510 | spin_unlock(&c->erase_completion_lock); |
400 | 511 | ||
401 | D1(printk(KERN_DEBUG "wbuf recovery completed OK\n")); | 512 | D1(printk(KERN_DEBUG "wbuf recovery completed OK. wbuf_ofs 0x%08x, len 0x%x\n", c->wbuf_ofs, c->wbuf_len)); |
513 | |||
402 | } | 514 | } |
403 | 515 | ||
404 | /* Meaning of pad argument: | 516 | /* Meaning of pad argument: |
@@ -412,6 +524,7 @@ static void jffs2_wbuf_recover(struct jffs2_sb_info *c) | |||
412 | 524 | ||
413 | static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | 525 | static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) |
414 | { | 526 | { |
527 | struct jffs2_eraseblock *wbuf_jeb; | ||
415 | int ret; | 528 | int ret; |
416 | size_t retlen; | 529 | size_t retlen; |
417 | 530 | ||
@@ -429,6 +542,10 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
429 | if (!c->wbuf_len) /* already checked c->wbuf above */ | 542 | if (!c->wbuf_len) /* already checked c->wbuf above */ |
430 | return 0; | 543 | return 0; |
431 | 544 | ||
545 | wbuf_jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | ||
546 | if (jffs2_prealloc_raw_node_refs(c, wbuf_jeb, c->nextblock->allocated_refs + 1)) | ||
547 | return -ENOMEM; | ||
548 | |||
432 | /* claim remaining space on the page | 549 | /* claim remaining space on the page |
433 | this happens, if we have a change to a new block, | 550 | this happens, if we have a change to a new block, |
434 | or if fsync forces us to flush the writebuffer. | 551 | or if fsync forces us to flush the writebuffer. |
@@ -458,15 +575,12 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
458 | if (breakme++ == 20) { | 575 | if (breakme++ == 20) { |
459 | printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs); | 576 | printk(KERN_NOTICE "Faking write error at 0x%08x\n", c->wbuf_ofs); |
460 | breakme = 0; | 577 | breakme = 0; |
461 | c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, | 578 | c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, |
462 | &retlen, brokenbuf, NULL, c->oobinfo); | 579 | brokenbuf); |
463 | ret = -EIO; | 580 | ret = -EIO; |
464 | } else | 581 | } else |
465 | #endif | 582 | #endif |
466 | 583 | ||
467 | if (jffs2_cleanmarker_oob(c)) | ||
468 | ret = c->mtd->write_ecc(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf, NULL, c->oobinfo); | ||
469 | else | ||
470 | ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf); | 584 | ret = c->mtd->write(c->mtd, c->wbuf_ofs, c->wbuf_pagesize, &retlen, c->wbuf); |
471 | 585 | ||
472 | if (ret || retlen != c->wbuf_pagesize) { | 586 | if (ret || retlen != c->wbuf_pagesize) { |
@@ -483,32 +597,34 @@ static int __jffs2_flush_wbuf(struct jffs2_sb_info *c, int pad) | |||
483 | return ret; | 597 | return ret; |
484 | } | 598 | } |
485 | 599 | ||
486 | spin_lock(&c->erase_completion_lock); | ||
487 | |||
488 | /* Adjust free size of the block if we padded. */ | 600 | /* Adjust free size of the block if we padded. */ |
489 | if (pad) { | 601 | if (pad) { |
490 | struct jffs2_eraseblock *jeb; | 602 | uint32_t waste = c->wbuf_pagesize - c->wbuf_len; |
491 | |||
492 | jeb = &c->blocks[c->wbuf_ofs / c->sector_size]; | ||
493 | 603 | ||
494 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", | 604 | D1(printk(KERN_DEBUG "jffs2_flush_wbuf() adjusting free_size of %sblock at %08x\n", |
495 | (jeb==c->nextblock)?"next":"", jeb->offset)); | 605 | (wbuf_jeb==c->nextblock)?"next":"", wbuf_jeb->offset)); |
496 | 606 | ||
497 | /* wbuf_pagesize - wbuf_len is the amount of space that's to be | 607 | /* wbuf_pagesize - wbuf_len is the amount of space that's to be |
498 | padded. If there is less free space in the block than that, | 608 | padded. If there is less free space in the block than that, |
499 | something screwed up */ | 609 | something screwed up */ |
500 | if (jeb->free_size < (c->wbuf_pagesize - c->wbuf_len)) { | 610 | if (wbuf_jeb->free_size < waste) { |
501 | printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", | 611 | printk(KERN_CRIT "jffs2_flush_wbuf(): Accounting error. wbuf at 0x%08x has 0x%03x bytes, 0x%03x left.\n", |
502 | c->wbuf_ofs, c->wbuf_len, c->wbuf_pagesize-c->wbuf_len); | 612 | c->wbuf_ofs, c->wbuf_len, waste); |
503 | printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", | 613 | printk(KERN_CRIT "jffs2_flush_wbuf(): But free_size for block at 0x%08x is only 0x%08x\n", |
504 | jeb->offset, jeb->free_size); | 614 | wbuf_jeb->offset, wbuf_jeb->free_size); |
505 | BUG(); | 615 | BUG(); |
506 | } | 616 | } |
507 | jeb->free_size -= (c->wbuf_pagesize - c->wbuf_len); | 617 | |
508 | c->free_size -= (c->wbuf_pagesize - c->wbuf_len); | 618 | spin_lock(&c->erase_completion_lock); |
509 | jeb->wasted_size += (c->wbuf_pagesize - c->wbuf_len); | 619 | |
510 | c->wasted_size += (c->wbuf_pagesize - c->wbuf_len); | 620 | jffs2_link_node_ref(c, wbuf_jeb, (c->wbuf_ofs + c->wbuf_len) | REF_OBSOLETE, waste, NULL); |
511 | } | 621 | /* FIXME: that made it count as dirty. Convert to wasted */ |
622 | wbuf_jeb->dirty_size -= waste; | ||
623 | c->dirty_size -= waste; | ||
624 | wbuf_jeb->wasted_size += waste; | ||
625 | c->wasted_size += waste; | ||
626 | } else | ||
627 | spin_lock(&c->erase_completion_lock); | ||
512 | 628 | ||
513 | /* Stick any now-obsoleted blocks on the erase_pending_list */ | 629 | /* Stick any now-obsoleted blocks on the erase_pending_list */ |
514 | jffs2_refile_wbuf_blocks(c); | 630 | jffs2_refile_wbuf_blocks(c); |
@@ -603,20 +719,30 @@ int jffs2_flush_wbuf_pad(struct jffs2_sb_info *c) | |||
603 | 719 | ||
604 | return ret; | 720 | return ret; |
605 | } | 721 | } |
606 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsigned long count, loff_t to, size_t *retlen, uint32_t ino) | 722 | |
723 | static size_t jffs2_fill_wbuf(struct jffs2_sb_info *c, const uint8_t *buf, | ||
724 | size_t len) | ||
607 | { | 725 | { |
608 | struct kvec outvecs[3]; | 726 | if (len && !c->wbuf_len && (len >= c->wbuf_pagesize)) |
609 | uint32_t totlen = 0; | 727 | return 0; |
610 | uint32_t split_ofs = 0; | 728 | |
611 | uint32_t old_totlen; | 729 | if (len > (c->wbuf_pagesize - c->wbuf_len)) |
612 | int ret, splitvec = -1; | 730 | len = c->wbuf_pagesize - c->wbuf_len; |
613 | int invec, outvec; | 731 | memcpy(c->wbuf + c->wbuf_len, buf, len); |
614 | size_t wbuf_retlen; | 732 | c->wbuf_len += (uint32_t) len; |
615 | unsigned char *wbuf_ptr; | 733 | return len; |
616 | size_t donelen = 0; | 734 | } |
735 | |||
736 | int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, | ||
737 | unsigned long count, loff_t to, size_t *retlen, | ||
738 | uint32_t ino) | ||
739 | { | ||
740 | struct jffs2_eraseblock *jeb; | ||
741 | size_t wbuf_retlen, donelen = 0; | ||
617 | uint32_t outvec_to = to; | 742 | uint32_t outvec_to = to; |
743 | int ret, invec; | ||
618 | 744 | ||
619 | /* If not NAND flash, don't bother */ | 745 | /* If not writebuffered flash, don't bother */ |
620 | if (!jffs2_is_writebuffered(c)) | 746 | if (!jffs2_is_writebuffered(c)) |
621 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); | 747 | return jffs2_flash_direct_writev(c, invecs, count, to, retlen); |
622 | 748 | ||
@@ -629,34 +755,22 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
629 | memset(c->wbuf,0xff,c->wbuf_pagesize); | 755 | memset(c->wbuf,0xff,c->wbuf_pagesize); |
630 | } | 756 | } |
631 | 757 | ||
632 | /* Fixup the wbuf if we are moving to a new eraseblock. The checks below | 758 | /* |
633 | fail for ECC'd NOR because cleanmarker == 16, so a block starts at | 759 | * Sanity checks on target address. It's permitted to write |
634 | xxx0010. */ | 760 | * at PAD(c->wbuf_len+c->wbuf_ofs), and it's permitted to |
635 | if (jffs2_nor_ecc(c)) { | 761 | * write at the beginning of a new erase block. Anything else, |
636 | if (((c->wbuf_ofs % c->sector_size) == 0) && !c->wbuf_len) { | 762 | * and you die. New block starts at xxx000c (0-b = block |
637 | c->wbuf_ofs = PAGE_DIV(to); | 763 | * header) |
638 | c->wbuf_len = PAGE_MOD(to); | 764 | */ |
639 | memset(c->wbuf,0xff,c->wbuf_pagesize); | ||
640 | } | ||
641 | } | ||
642 | |||
643 | /* Sanity checks on target address. | ||
644 | It's permitted to write at PAD(c->wbuf_len+c->wbuf_ofs), | ||
645 | and it's permitted to write at the beginning of a new | ||
646 | erase block. Anything else, and you die. | ||
647 | New block starts at xxx000c (0-b = block header) | ||
648 | */ | ||
649 | if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) { | 765 | if (SECTOR_ADDR(to) != SECTOR_ADDR(c->wbuf_ofs)) { |
650 | /* It's a write to a new block */ | 766 | /* It's a write to a new block */ |
651 | if (c->wbuf_len) { | 767 | if (c->wbuf_len) { |
652 | D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx causes flush of wbuf at 0x%08x\n", (unsigned long)to, c->wbuf_ofs)); | 768 | D1(printk(KERN_DEBUG "jffs2_flash_writev() to 0x%lx " |
769 | "causes flush of wbuf at 0x%08x\n", | ||
770 | (unsigned long)to, c->wbuf_ofs)); | ||
653 | ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); | 771 | ret = __jffs2_flush_wbuf(c, PAD_NOACCOUNT); |
654 | if (ret) { | 772 | if (ret) |
655 | /* the underlying layer has to check wbuf_len to do the cleanup */ | 773 | goto outerr; |
656 | D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); | ||
657 | *retlen = 0; | ||
658 | goto exit; | ||
659 | } | ||
660 | } | 774 | } |
661 | /* set pointer to new block */ | 775 | /* set pointer to new block */ |
662 | c->wbuf_ofs = PAGE_DIV(to); | 776 | c->wbuf_ofs = PAGE_DIV(to); |
@@ -665,165 +779,70 @@ int jffs2_flash_writev(struct jffs2_sb_info *c, const struct kvec *invecs, unsig | |||
665 | 779 | ||
666 | if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { | 780 | if (to != PAD(c->wbuf_ofs + c->wbuf_len)) { |
667 | /* We're not writing immediately after the writebuffer. Bad. */ | 781 | /* We're not writing immediately after the writebuffer. Bad. */ |
668 | printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write to %08lx\n", (unsigned long)to); | 782 | printk(KERN_CRIT "jffs2_flash_writev(): Non-contiguous write " |
783 | "to %08lx\n", (unsigned long)to); | ||
669 | if (c->wbuf_len) | 784 | if (c->wbuf_len) |
670 | printk(KERN_CRIT "wbuf was previously %08x-%08x\n", | 785 | printk(KERN_CRIT "wbuf was previously %08x-%08x\n", |
671 | c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len); | 786 | c->wbuf_ofs, c->wbuf_ofs+c->wbuf_len); |
672 | BUG(); | 787 | BUG(); |
673 | } | 788 | } |
674 | 789 | ||
675 | /* Note outvecs[3] above. We know count is never greater than 2 */ | 790 | /* adjust alignment offset */ |
676 | if (count > 2) { | 791 | if (c->wbuf_len != PAGE_MOD(to)) { |
677 | printk(KERN_CRIT "jffs2_flash_writev(): count is %ld\n", count); | 792 | c->wbuf_len = PAGE_MOD(to); |
678 | BUG(); | 793 | /* take care of alignment to next page */ |
679 | } | 794 | if (!c->wbuf_len) { |
680 | 795 | c->wbuf_len = c->wbuf_pagesize; | |
681 | invec = 0; | 796 | ret = __jffs2_flush_wbuf(c, NOPAD); |
682 | outvec = 0; | 797 | if (ret) |
683 | 798 | goto outerr; | |
684 | /* Fill writebuffer first, if already in use */ | ||
685 | if (c->wbuf_len) { | ||
686 | uint32_t invec_ofs = 0; | ||
687 | |||
688 | /* adjust alignment offset */ | ||
689 | if (c->wbuf_len != PAGE_MOD(to)) { | ||
690 | c->wbuf_len = PAGE_MOD(to); | ||
691 | /* take care of alignment to next page */ | ||
692 | if (!c->wbuf_len) | ||
693 | c->wbuf_len = c->wbuf_pagesize; | ||
694 | } | ||
695 | |||
696 | while(c->wbuf_len < c->wbuf_pagesize) { | ||
697 | uint32_t thislen; | ||
698 | |||
699 | if (invec == count) | ||
700 | goto alldone; | ||
701 | |||
702 | thislen = c->wbuf_pagesize - c->wbuf_len; | ||
703 | |||
704 | if (thislen >= invecs[invec].iov_len) | ||
705 | thislen = invecs[invec].iov_len; | ||
706 | |||
707 | invec_ofs = thislen; | ||
708 | |||
709 | memcpy(c->wbuf + c->wbuf_len, invecs[invec].iov_base, thislen); | ||
710 | c->wbuf_len += thislen; | ||
711 | donelen += thislen; | ||
712 | /* Get next invec, if actual did not fill the buffer */ | ||
713 | if (c->wbuf_len < c->wbuf_pagesize) | ||
714 | invec++; | ||
715 | } | ||
716 | |||
717 | /* write buffer is full, flush buffer */ | ||
718 | ret = __jffs2_flush_wbuf(c, NOPAD); | ||
719 | if (ret) { | ||
720 | /* the underlying layer has to check wbuf_len to do the cleanup */ | ||
721 | D1(printk(KERN_WARNING "jffs2_flush_wbuf() called from jffs2_flash_writev() failed %d\n", ret)); | ||
722 | /* Retlen zero to make sure our caller doesn't mark the space dirty. | ||
723 | We've already done everything that's necessary */ | ||
724 | *retlen = 0; | ||
725 | goto exit; | ||
726 | } | ||
727 | outvec_to += donelen; | ||
728 | c->wbuf_ofs = outvec_to; | ||
729 | |||
730 | /* All invecs done ? */ | ||
731 | if (invec == count) | ||
732 | goto alldone; | ||
733 | |||
734 | /* Set up the first outvec, containing the remainder of the | ||
735 | invec we partially used */ | ||
736 | if (invecs[invec].iov_len > invec_ofs) { | ||
737 | outvecs[0].iov_base = invecs[invec].iov_base+invec_ofs; | ||
738 | totlen = outvecs[0].iov_len = invecs[invec].iov_len-invec_ofs; | ||
739 | if (totlen > c->wbuf_pagesize) { | ||
740 | splitvec = outvec; | ||
741 | split_ofs = outvecs[0].iov_len - PAGE_MOD(totlen); | ||
742 | } | ||
743 | outvec++; | ||
744 | } | ||
745 | invec++; | ||
746 | } | ||
747 | |||
748 | /* OK, now we've flushed the wbuf and the start of the bits | ||
749 | we have been asked to write, now to write the rest.... */ | ||
750 | |||
751 | /* totlen holds the amount of data still to be written */ | ||
752 | old_totlen = totlen; | ||
753 | for ( ; invec < count; invec++,outvec++ ) { | ||
754 | outvecs[outvec].iov_base = invecs[invec].iov_base; | ||
755 | totlen += outvecs[outvec].iov_len = invecs[invec].iov_len; | ||
756 | if (PAGE_DIV(totlen) != PAGE_DIV(old_totlen)) { | ||
757 | splitvec = outvec; | ||
758 | split_ofs = outvecs[outvec].iov_len - PAGE_MOD(totlen); | ||
759 | old_totlen = totlen; | ||
760 | } | 799 | } |
761 | } | 800 | } |
762 | 801 | ||
763 | /* Now the outvecs array holds all the remaining data to write */ | 802 | for (invec = 0; invec < count; invec++) { |
764 | /* Up to splitvec,split_ofs is to be written immediately. The rest | 803 | int vlen = invecs[invec].iov_len; |
765 | goes into the (now-empty) wbuf */ | 804 | uint8_t *v = invecs[invec].iov_base; |
766 | |||
767 | if (splitvec != -1) { | ||
768 | uint32_t remainder; | ||
769 | |||
770 | remainder = outvecs[splitvec].iov_len - split_ofs; | ||
771 | outvecs[splitvec].iov_len = split_ofs; | ||
772 | |||
773 | /* We did cross a page boundary, so we write some now */ | ||
774 | if (jffs2_cleanmarker_oob(c)) | ||
775 | ret = c->mtd->writev_ecc(c->mtd, outvecs, splitvec+1, outvec_to, &wbuf_retlen, NULL, c->oobinfo); | ||
776 | else | ||
777 | ret = jffs2_flash_direct_writev(c, outvecs, splitvec+1, outvec_to, &wbuf_retlen); | ||
778 | |||
779 | if (ret < 0 || wbuf_retlen != PAGE_DIV(totlen)) { | ||
780 | /* At this point we have no problem, | ||
781 | c->wbuf is empty. However refile nextblock to avoid | ||
782 | writing again to same address. | ||
783 | */ | ||
784 | struct jffs2_eraseblock *jeb; | ||
785 | 805 | ||
786 | spin_lock(&c->erase_completion_lock); | 806 | wbuf_retlen = jffs2_fill_wbuf(c, v, vlen); |
787 | 807 | ||
788 | jeb = &c->blocks[outvec_to / c->sector_size]; | 808 | if (c->wbuf_len == c->wbuf_pagesize) { |
789 | jffs2_block_refile(c, jeb, REFILE_ANYWAY); | 809 | ret = __jffs2_flush_wbuf(c, NOPAD); |
790 | 810 | if (ret) | |
791 | *retlen = 0; | 811 | goto outerr; |
792 | spin_unlock(&c->erase_completion_lock); | ||
793 | goto exit; | ||
794 | } | 812 | } |
795 | 813 | vlen -= wbuf_retlen; | |
814 | outvec_to += wbuf_retlen; | ||
796 | donelen += wbuf_retlen; | 815 | donelen += wbuf_retlen; |
797 | c->wbuf_ofs = PAGE_DIV(outvec_to) + PAGE_DIV(totlen); | 816 | v += wbuf_retlen; |
798 | 817 | ||
799 | if (remainder) { | 818 | if (vlen >= c->wbuf_pagesize) { |
800 | outvecs[splitvec].iov_base += split_ofs; | 819 | ret = c->mtd->write(c->mtd, outvec_to, PAGE_DIV(vlen), |
801 | outvecs[splitvec].iov_len = remainder; | 820 | &wbuf_retlen, v); |
802 | } else { | 821 | if (ret < 0 || wbuf_retlen != PAGE_DIV(vlen)) |
803 | splitvec++; | 822 | goto outfile; |
823 | |||
824 | vlen -= wbuf_retlen; | ||
825 | outvec_to += wbuf_retlen; | ||
826 | c->wbuf_ofs = outvec_to; | ||
827 | donelen += wbuf_retlen; | ||
828 | v += wbuf_retlen; | ||
804 | } | 829 | } |
805 | 830 | ||
806 | } else { | 831 | wbuf_retlen = jffs2_fill_wbuf(c, v, vlen); |
807 | splitvec = 0; | 832 | if (c->wbuf_len == c->wbuf_pagesize) { |
808 | } | 833 | ret = __jffs2_flush_wbuf(c, NOPAD); |
809 | 834 | if (ret) | |
810 | /* Now splitvec points to the start of the bits we have to copy | 835 | goto outerr; |
811 | into the wbuf */ | 836 | } |
812 | wbuf_ptr = c->wbuf; | ||
813 | 837 | ||
814 | for ( ; splitvec < outvec; splitvec++) { | 838 | outvec_to += wbuf_retlen; |
815 | /* Don't copy the wbuf into itself */ | 839 | donelen += wbuf_retlen; |
816 | if (outvecs[splitvec].iov_base == c->wbuf) | ||
817 | continue; | ||
818 | memcpy(wbuf_ptr, outvecs[splitvec].iov_base, outvecs[splitvec].iov_len); | ||
819 | wbuf_ptr += outvecs[splitvec].iov_len; | ||
820 | donelen += outvecs[splitvec].iov_len; | ||
821 | } | 840 | } |
822 | c->wbuf_len = wbuf_ptr - c->wbuf; | ||
823 | 841 | ||
824 | /* If there's a remainder in the wbuf and it's a non-GC write, | 842 | /* |
825 | remember that the wbuf affects this ino */ | 843 | * If there's a remainder in the wbuf and it's a non-GC write, |
826 | alldone: | 844 | * remember that the wbuf affects this ino |
845 | */ | ||
827 | *retlen = donelen; | 846 | *retlen = donelen; |
828 | 847 | ||
829 | if (jffs2_sum_active()) { | 848 | if (jffs2_sum_active()) { |
@@ -836,8 +855,24 @@ alldone: | |||
836 | jffs2_wbuf_dirties_inode(c, ino); | 855 | jffs2_wbuf_dirties_inode(c, ino); |
837 | 856 | ||
838 | ret = 0; | 857 | ret = 0; |
858 | up_write(&c->wbuf_sem); | ||
859 | return ret; | ||
839 | 860 | ||
840 | exit: | 861 | outfile: |
862 | /* | ||
863 | * At this point we have no problem, c->wbuf is empty. However | ||
864 | * refile nextblock to avoid writing again to same address. | ||
865 | */ | ||
866 | |||
867 | spin_lock(&c->erase_completion_lock); | ||
868 | |||
869 | jeb = &c->blocks[outvec_to / c->sector_size]; | ||
870 | jffs2_block_refile(c, jeb, REFILE_ANYWAY); | ||
871 | |||
872 | spin_unlock(&c->erase_completion_lock); | ||
873 | |||
874 | outerr: | ||
875 | *retlen = 0; | ||
841 | up_write(&c->wbuf_sem); | 876 | up_write(&c->wbuf_sem); |
842 | return ret; | 877 | return ret; |
843 | } | 878 | } |
@@ -846,7 +881,8 @@ exit: | |||
846 | * This is the entry for flash write. | 881 | * This is the entry for flash write. |
847 | * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev | 882 | * Check, if we work on NAND FLASH, if so build an kvec and write it via vritev |
848 | */ | 883 | */ |
849 | int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *retlen, const u_char *buf) | 884 | int jffs2_flash_write(struct jffs2_sb_info *c, loff_t ofs, size_t len, |
885 | size_t *retlen, const u_char *buf) | ||
850 | { | 886 | { |
851 | struct kvec vecs[1]; | 887 | struct kvec vecs[1]; |
852 | 888 | ||
@@ -871,25 +907,23 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
871 | 907 | ||
872 | /* Read flash */ | 908 | /* Read flash */ |
873 | down_read(&c->wbuf_sem); | 909 | down_read(&c->wbuf_sem); |
874 | if (jffs2_cleanmarker_oob(c)) | 910 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); |
875 | ret = c->mtd->read_ecc(c->mtd, ofs, len, retlen, buf, NULL, c->oobinfo); | 911 | |
876 | else | 912 | if ( (ret == -EBADMSG || ret == -EUCLEAN) && (*retlen == len) ) { |
877 | ret = c->mtd->read(c->mtd, ofs, len, retlen, buf); | 913 | if (ret == -EBADMSG) |
878 | 914 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx)" | |
879 | if ( (ret == -EBADMSG) && (*retlen == len) ) { | 915 | " returned ECC error\n", len, ofs); |
880 | printk(KERN_WARNING "mtd->read(0x%zx bytes from 0x%llx) returned ECC error\n", | ||
881 | len, ofs); | ||
882 | /* | 916 | /* |
883 | * We have the raw data without ECC correction in the buffer, maybe | 917 | * We have the raw data without ECC correction in the buffer, |
884 | * we are lucky and all data or parts are correct. We check the node. | 918 | * maybe we are lucky and all data or parts are correct. We |
885 | * If data are corrupted node check will sort it out. | 919 | * check the node. If data are corrupted node check will sort |
886 | * We keep this block, it will fail on write or erase and the we | 920 | * it out. We keep this block, it will fail on write or erase |
887 | * mark it bad. Or should we do that now? But we should give him a chance. | 921 | * and the we mark it bad. Or should we do that now? But we |
888 | * Maybe we had a system crash or power loss before the ecc write or | 922 | * should give him a chance. Maybe we had a system crash or |
889 | * a erase was completed. | 923 | * power loss before the ecc write or a erase was completed. |
890 | * So we return success. :) | 924 | * So we return success. :) |
891 | */ | 925 | */ |
892 | ret = 0; | 926 | ret = 0; |
893 | } | 927 | } |
894 | 928 | ||
895 | /* if no writebuffer available or write buffer empty, return */ | 929 | /* if no writebuffer available or write buffer empty, return */ |
@@ -911,7 +945,7 @@ int jffs2_flash_read(struct jffs2_sb_info *c, loff_t ofs, size_t len, size_t *re | |||
911 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ | 945 | orbf = (c->wbuf_ofs - ofs); /* offset in read buffer */ |
912 | if (orbf > len) /* is write beyond write buffer ? */ | 946 | if (orbf > len) /* is write beyond write buffer ? */ |
913 | goto exit; | 947 | goto exit; |
914 | lwbf = len - orbf; /* number of bytes to copy */ | 948 | lwbf = len - orbf; /* number of bytes to copy */ |
915 | if (lwbf > c->wbuf_len) | 949 | if (lwbf > c->wbuf_len) |
916 | lwbf = c->wbuf_len; | 950 | lwbf = c->wbuf_len; |
917 | } | 951 | } |
@@ -923,158 +957,159 @@ exit: | |||
923 | return ret; | 957 | return ret; |
924 | } | 958 | } |
925 | 959 | ||
960 | #define NR_OOB_SCAN_PAGES 4 | ||
961 | |||
926 | /* | 962 | /* |
927 | * Check, if the out of band area is empty | 963 | * Check, if the out of band area is empty |
928 | */ | 964 | */ |
929 | int jffs2_check_oob_empty( struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb, int mode) | 965 | int jffs2_check_oob_empty(struct jffs2_sb_info *c, |
966 | struct jffs2_eraseblock *jeb, int mode) | ||
930 | { | 967 | { |
931 | unsigned char *buf; | 968 | int i, page, ret; |
932 | int ret = 0; | 969 | int oobsize = c->mtd->oobsize; |
933 | int i,len,page; | 970 | struct mtd_oob_ops ops; |
934 | size_t retlen; | 971 | |
935 | int oob_size; | 972 | ops.len = NR_OOB_SCAN_PAGES * oobsize; |
936 | 973 | ops.ooblen = oobsize; | |
937 | /* allocate a buffer for all oob data in this sector */ | 974 | ops.oobbuf = c->oobbuf; |
938 | oob_size = c->mtd->oobsize; | 975 | ops.ooboffs = 0; |
939 | len = 4 * oob_size; | 976 | ops.datbuf = NULL; |
940 | buf = kmalloc(len, GFP_KERNEL); | 977 | ops.mode = MTD_OOB_PLACE; |
941 | if (!buf) { | 978 | |
942 | printk(KERN_NOTICE "jffs2_check_oob_empty(): allocation of temporary data buffer for oob check failed\n"); | 979 | ret = c->mtd->read_oob(c->mtd, jeb->offset, &ops); |
943 | return -ENOMEM; | ||
944 | } | ||
945 | /* | ||
946 | * if mode = 0, we scan for a total empty oob area, else we have | ||
947 | * to take care of the cleanmarker in the first page of the block | ||
948 | */ | ||
949 | ret = jffs2_flash_read_oob(c, jeb->offset, len , &retlen, buf); | ||
950 | if (ret) { | 980 | if (ret) { |
951 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); | 981 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " |
952 | goto out; | 982 | "failed %d for block at %08x\n", ret, jeb->offset)); |
983 | return ret; | ||
953 | } | 984 | } |
954 | 985 | ||
955 | if (retlen < len) { | 986 | if (ops.retlen < ops.len) { |
956 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB return short read " | 987 | D1(printk(KERN_WARNING "jffs2_check_oob_empty(): Read OOB " |
957 | "(%zd bytes not %d) for block at %08x\n", retlen, len, jeb->offset)); | 988 | "returned short read (%zd bytes not %d) for block " |
958 | ret = -EIO; | 989 | "at %08x\n", ops.retlen, ops.len, jeb->offset)); |
959 | goto out; | 990 | return -EIO; |
960 | } | 991 | } |
961 | 992 | ||
962 | /* Special check for first page */ | 993 | /* Special check for first page */ |
963 | for(i = 0; i < oob_size ; i++) { | 994 | for(i = 0; i < oobsize ; i++) { |
964 | /* Yeah, we know about the cleanmarker. */ | 995 | /* Yeah, we know about the cleanmarker. */ |
965 | if (mode && i >= c->fsdata_pos && | 996 | if (mode && i >= c->fsdata_pos && |
966 | i < c->fsdata_pos + c->fsdata_len) | 997 | i < c->fsdata_pos + c->fsdata_len) |
967 | continue; | 998 | continue; |
968 | 999 | ||
969 | if (buf[i] != 0xFF) { | 1000 | if (ops.oobbuf[i] != 0xFF) { |
970 | D2(printk(KERN_DEBUG "Found %02x at %x in OOB for %08x\n", | 1001 | D2(printk(KERN_DEBUG "Found %02x at %x in OOB for " |
971 | buf[i], i, jeb->offset)); | 1002 | "%08x\n", ops.oobbuf[i], i, jeb->offset)); |
972 | ret = 1; | 1003 | return 1; |
973 | goto out; | ||
974 | } | 1004 | } |
975 | } | 1005 | } |
976 | 1006 | ||
977 | /* we know, we are aligned :) */ | 1007 | /* we know, we are aligned :) */ |
978 | for (page = oob_size; page < len; page += sizeof(long)) { | 1008 | for (page = oobsize; page < ops.len; page += sizeof(long)) { |
979 | unsigned long dat = *(unsigned long *)(&buf[page]); | 1009 | long dat = *(long *)(&ops.oobbuf[page]); |
980 | if(dat != -1) { | 1010 | if(dat != -1) |
981 | ret = 1; | 1011 | return 1; |
982 | goto out; | ||
983 | } | ||
984 | } | 1012 | } |
985 | 1013 | return 0; | |
986 | out: | ||
987 | kfree(buf); | ||
988 | |||
989 | return ret; | ||
990 | } | 1014 | } |
991 | 1015 | ||
992 | /* | 1016 | /* |
993 | * Scan for a valid cleanmarker and for bad blocks | 1017 | * Scan for a valid cleanmarker and for bad blocks |
994 | * For virtual blocks (concatenated physical blocks) check the cleanmarker | 1018 | */ |
995 | * only in the first page of the first physical block, but scan for bad blocks in all | 1019 | int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, |
996 | * physical blocks | 1020 | struct jffs2_eraseblock *jeb) |
997 | */ | ||
998 | int jffs2_check_nand_cleanmarker (struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | ||
999 | { | 1021 | { |
1000 | struct jffs2_unknown_node n; | 1022 | struct jffs2_unknown_node n; |
1001 | unsigned char buf[2 * NAND_MAX_OOBSIZE]; | 1023 | struct mtd_oob_ops ops; |
1002 | unsigned char *p; | 1024 | int oobsize = c->mtd->oobsize; |
1003 | int ret, i, cnt, retval = 0; | 1025 | unsigned char *p,*b; |
1004 | size_t retlen, offset; | 1026 | int i, ret; |
1005 | int oob_size; | 1027 | size_t offset = jeb->offset; |
1006 | 1028 | ||
1007 | offset = jeb->offset; | 1029 | /* Check first if the block is bad. */ |
1008 | oob_size = c->mtd->oobsize; | 1030 | if (c->mtd->block_isbad(c->mtd, offset)) { |
1009 | 1031 | D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker()" | |
1010 | /* Loop through the physical blocks */ | 1032 | ": Bad block at %08x\n", jeb->offset)); |
1011 | for (cnt = 0; cnt < (c->sector_size / c->mtd->erasesize); cnt++) { | 1033 | return 2; |
1012 | /* Check first if the block is bad. */ | 1034 | } |
1013 | if (c->mtd->block_isbad (c->mtd, offset)) { | ||
1014 | D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Bad block at %08x\n", jeb->offset)); | ||
1015 | return 2; | ||
1016 | } | ||
1017 | /* | ||
1018 | * We read oob data from page 0 and 1 of the block. | ||
1019 | * page 0 contains cleanmarker and badblock info | ||
1020 | * page 1 contains failure count of this block | ||
1021 | */ | ||
1022 | ret = c->mtd->read_oob (c->mtd, offset, oob_size << 1, &retlen, buf); | ||
1023 | 1035 | ||
1024 | if (ret) { | 1036 | ops.len = oobsize; |
1025 | D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB failed %d for block at %08x\n", ret, jeb->offset)); | 1037 | ops.ooblen = oobsize; |
1026 | return ret; | 1038 | ops.oobbuf = c->oobbuf; |
1027 | } | 1039 | ops.ooboffs = 0; |
1028 | if (retlen < (oob_size << 1)) { | 1040 | ops.datbuf = NULL; |
1029 | D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): Read OOB return short read (%zd bytes not %d) for block at %08x\n", retlen, oob_size << 1, jeb->offset)); | 1041 | ops.mode = MTD_OOB_PLACE; |
1030 | return -EIO; | ||
1031 | } | ||
1032 | 1042 | ||
1033 | /* Check cleanmarker only on the first physical block */ | 1043 | ret = c->mtd->read_oob(c->mtd, offset, &ops); |
1034 | if (!cnt) { | 1044 | if (ret) { |
1035 | n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); | 1045 | D1 (printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): " |
1036 | n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); | 1046 | "Read OOB failed %d for block at %08x\n", |
1037 | n.totlen = cpu_to_je32 (8); | 1047 | ret, jeb->offset)); |
1038 | p = (unsigned char *) &n; | 1048 | return ret; |
1049 | } | ||
1039 | 1050 | ||
1040 | for (i = 0; i < c->fsdata_len; i++) { | 1051 | if (ops.retlen < ops.len) { |
1041 | if (buf[c->fsdata_pos + i] != p[i]) { | 1052 | D1 (printk (KERN_WARNING "jffs2_check_nand_cleanmarker(): " |
1042 | retval = 1; | 1053 | "Read OOB return short read (%zd bytes not %d) " |
1043 | } | 1054 | "for block at %08x\n", ops.retlen, ops.len, |
1044 | } | 1055 | jeb->offset)); |
1045 | D1(if (retval == 1) { | 1056 | return -EIO; |
1046 | printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): Cleanmarker node not detected in block at %08x\n", jeb->offset); | ||
1047 | printk(KERN_WARNING "OOB at %08x was ", offset); | ||
1048 | for (i=0; i < oob_size; i++) { | ||
1049 | printk("%02x ", buf[i]); | ||
1050 | } | ||
1051 | printk("\n"); | ||
1052 | }) | ||
1053 | } | ||
1054 | offset += c->mtd->erasesize; | ||
1055 | } | 1057 | } |
1056 | return retval; | 1058 | |
1059 | n.magic = cpu_to_je16 (JFFS2_MAGIC_BITMASK); | ||
1060 | n.nodetype = cpu_to_je16 (JFFS2_NODETYPE_CLEANMARKER); | ||
1061 | n.totlen = cpu_to_je32 (8); | ||
1062 | p = (unsigned char *) &n; | ||
1063 | b = c->oobbuf + c->fsdata_pos; | ||
1064 | |||
1065 | for (i = c->fsdata_len; i; i--) { | ||
1066 | if (*b++ != *p++) | ||
1067 | ret = 1; | ||
1068 | } | ||
1069 | |||
1070 | D1(if (ret == 1) { | ||
1071 | printk(KERN_WARNING "jffs2_check_nand_cleanmarker(): " | ||
1072 | "Cleanmarker node not detected in block at %08x\n", | ||
1073 | offset); | ||
1074 | printk(KERN_WARNING "OOB at %08zx was ", offset); | ||
1075 | for (i=0; i < oobsize; i++) | ||
1076 | printk("%02x ", c->oobbuf[i]); | ||
1077 | printk("\n"); | ||
1078 | }); | ||
1079 | return ret; | ||
1057 | } | 1080 | } |
1058 | 1081 | ||
1059 | int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb) | 1082 | int jffs2_write_nand_cleanmarker(struct jffs2_sb_info *c, |
1083 | struct jffs2_eraseblock *jeb) | ||
1060 | { | 1084 | { |
1061 | struct jffs2_unknown_node n; | 1085 | struct jffs2_unknown_node n; |
1062 | int ret; | 1086 | int ret; |
1063 | size_t retlen; | 1087 | struct mtd_oob_ops ops; |
1064 | 1088 | ||
1065 | n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | 1089 | n.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); |
1066 | n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); | 1090 | n.nodetype = cpu_to_je16(JFFS2_NODETYPE_CLEANMARKER); |
1067 | n.totlen = cpu_to_je32(8); | 1091 | n.totlen = cpu_to_je32(8); |
1068 | 1092 | ||
1069 | ret = jffs2_flash_write_oob(c, jeb->offset + c->fsdata_pos, c->fsdata_len, &retlen, (unsigned char *)&n); | 1093 | ops.len = c->fsdata_len; |
1094 | ops.ooblen = c->fsdata_len;; | ||
1095 | ops.oobbuf = (uint8_t *)&n; | ||
1096 | ops.ooboffs = c->fsdata_pos; | ||
1097 | ops.datbuf = NULL; | ||
1098 | ops.mode = MTD_OOB_PLACE; | ||
1099 | |||
1100 | ret = c->mtd->write_oob(c->mtd, jeb->offset, &ops); | ||
1070 | 1101 | ||
1071 | if (ret) { | 1102 | if (ret) { |
1072 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Write failed for block at %08x: error %d\n", jeb->offset, ret)); | 1103 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " |
1104 | "Write failed for block at %08x: error %d\n", | ||
1105 | jeb->offset, ret)); | ||
1073 | return ret; | 1106 | return ret; |
1074 | } | 1107 | } |
1075 | if (retlen != c->fsdata_len) { | 1108 | if (ops.retlen != ops.len) { |
1076 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): Short write for block at %08x: %zd not %d\n", jeb->offset, retlen, c->fsdata_len)); | 1109 | D1(printk(KERN_WARNING "jffs2_write_nand_cleanmarker(): " |
1077 | return ret; | 1110 | "Short write for block at %08x: %zd not %d\n", |
1111 | jeb->offset, ops.retlen, ops.len)); | ||
1112 | return -EIO; | ||
1078 | } | 1113 | } |
1079 | return 0; | 1114 | return 0; |
1080 | } | 1115 | } |
@@ -1108,18 +1143,9 @@ int jffs2_write_nand_badblock(struct jffs2_sb_info *c, struct jffs2_eraseblock * | |||
1108 | return 1; | 1143 | return 1; |
1109 | } | 1144 | } |
1110 | 1145 | ||
1111 | #define NAND_JFFS2_OOB16_FSDALEN 8 | ||
1112 | |||
1113 | static struct nand_oobinfo jffs2_oobinfo_docecc = { | ||
1114 | .useecc = MTD_NANDECC_PLACE, | ||
1115 | .eccbytes = 6, | ||
1116 | .eccpos = {0,1,2,3,4,5} | ||
1117 | }; | ||
1118 | |||
1119 | |||
1120 | static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) | 1146 | static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) |
1121 | { | 1147 | { |
1122 | struct nand_oobinfo *oinfo = &c->mtd->oobinfo; | 1148 | struct nand_ecclayout *oinfo = c->mtd->ecclayout; |
1123 | 1149 | ||
1124 | /* Do this only, if we have an oob buffer */ | 1150 | /* Do this only, if we have an oob buffer */ |
1125 | if (!c->mtd->oobsize) | 1151 | if (!c->mtd->oobsize) |
@@ -1129,33 +1155,23 @@ static int jffs2_nand_set_oobinfo(struct jffs2_sb_info *c) | |||
1129 | c->cleanmarker_size = 0; | 1155 | c->cleanmarker_size = 0; |
1130 | 1156 | ||
1131 | /* Should we use autoplacement ? */ | 1157 | /* Should we use autoplacement ? */ |
1132 | if (oinfo && oinfo->useecc == MTD_NANDECC_AUTOPLACE) { | 1158 | if (!oinfo) { |
1133 | D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n")); | 1159 | D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); |
1134 | /* Get the position of the free bytes */ | 1160 | return -EINVAL; |
1135 | if (!oinfo->oobfree[0][1]) { | 1161 | } |
1136 | printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep. Autoplacement selected and no empty space in oob\n"); | ||
1137 | return -ENOSPC; | ||
1138 | } | ||
1139 | c->fsdata_pos = oinfo->oobfree[0][0]; | ||
1140 | c->fsdata_len = oinfo->oobfree[0][1]; | ||
1141 | if (c->fsdata_len > 8) | ||
1142 | c->fsdata_len = 8; | ||
1143 | } else { | ||
1144 | /* This is just a legacy fallback and should go away soon */ | ||
1145 | switch(c->mtd->ecctype) { | ||
1146 | case MTD_ECC_RS_DiskOnChip: | ||
1147 | printk(KERN_WARNING "JFFS2 using DiskOnChip hardware ECC without autoplacement. Fix it!\n"); | ||
1148 | c->oobinfo = &jffs2_oobinfo_docecc; | ||
1149 | c->fsdata_pos = 6; | ||
1150 | c->fsdata_len = NAND_JFFS2_OOB16_FSDALEN; | ||
1151 | c->badblock_pos = 15; | ||
1152 | break; | ||
1153 | 1162 | ||
1154 | default: | 1163 | D1(printk(KERN_DEBUG "JFFS2 using autoplace on NAND\n")); |
1155 | D1(printk(KERN_DEBUG "JFFS2 on NAND. No autoplacment info found\n")); | 1164 | /* Get the position of the free bytes */ |
1156 | return -EINVAL; | 1165 | if (!oinfo->oobfree[0].length) { |
1157 | } | 1166 | printk (KERN_WARNING "jffs2_nand_set_oobinfo(): Eeep." |
1167 | " Autoplacement selected and no empty space in oob\n"); | ||
1168 | return -ENOSPC; | ||
1158 | } | 1169 | } |
1170 | c->fsdata_pos = oinfo->oobfree[0].offset; | ||
1171 | c->fsdata_len = oinfo->oobfree[0].length; | ||
1172 | if (c->fsdata_len > 8) | ||
1173 | c->fsdata_len = 8; | ||
1174 | |||
1159 | return 0; | 1175 | return 0; |
1160 | } | 1176 | } |
1161 | 1177 | ||
@@ -1165,13 +1181,17 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | |||
1165 | 1181 | ||
1166 | /* Initialise write buffer */ | 1182 | /* Initialise write buffer */ |
1167 | init_rwsem(&c->wbuf_sem); | 1183 | init_rwsem(&c->wbuf_sem); |
1168 | c->wbuf_pagesize = c->mtd->oobblock; | 1184 | c->wbuf_pagesize = c->mtd->writesize; |
1169 | c->wbuf_ofs = 0xFFFFFFFF; | 1185 | c->wbuf_ofs = 0xFFFFFFFF; |
1170 | 1186 | ||
1171 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | 1187 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); |
1172 | if (!c->wbuf) | 1188 | if (!c->wbuf) |
1173 | return -ENOMEM; | 1189 | return -ENOMEM; |
1174 | 1190 | ||
1191 | c->oobbuf = kmalloc(NR_OOB_SCAN_PAGES * c->mtd->oobsize, GFP_KERNEL); | ||
1192 | if (!c->oobbuf) | ||
1193 | return -ENOMEM; | ||
1194 | |||
1175 | res = jffs2_nand_set_oobinfo(c); | 1195 | res = jffs2_nand_set_oobinfo(c); |
1176 | 1196 | ||
1177 | #ifdef BREAKME | 1197 | #ifdef BREAKME |
@@ -1189,6 +1209,7 @@ int jffs2_nand_flash_setup(struct jffs2_sb_info *c) | |||
1189 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) | 1209 | void jffs2_nand_flash_cleanup(struct jffs2_sb_info *c) |
1190 | { | 1210 | { |
1191 | kfree(c->wbuf); | 1211 | kfree(c->wbuf); |
1212 | kfree(c->oobbuf); | ||
1192 | } | 1213 | } |
1193 | 1214 | ||
1194 | int jffs2_dataflash_setup(struct jffs2_sb_info *c) { | 1215 | int jffs2_dataflash_setup(struct jffs2_sb_info *c) { |
@@ -1236,33 +1257,14 @@ void jffs2_dataflash_cleanup(struct jffs2_sb_info *c) { | |||
1236 | kfree(c->wbuf); | 1257 | kfree(c->wbuf); |
1237 | } | 1258 | } |
1238 | 1259 | ||
1239 | int jffs2_nor_ecc_flash_setup(struct jffs2_sb_info *c) { | ||
1240 | /* Cleanmarker is actually larger on the flashes */ | ||
1241 | c->cleanmarker_size = 16; | ||
1242 | |||
1243 | /* Initialize write buffer */ | ||
1244 | init_rwsem(&c->wbuf_sem); | ||
1245 | c->wbuf_pagesize = c->mtd->eccsize; | ||
1246 | c->wbuf_ofs = 0xFFFFFFFF; | ||
1247 | |||
1248 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | ||
1249 | if (!c->wbuf) | ||
1250 | return -ENOMEM; | ||
1251 | |||
1252 | return 0; | ||
1253 | } | ||
1254 | |||
1255 | void jffs2_nor_ecc_flash_cleanup(struct jffs2_sb_info *c) { | ||
1256 | kfree(c->wbuf); | ||
1257 | } | ||
1258 | |||
1259 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { | 1260 | int jffs2_nor_wbuf_flash_setup(struct jffs2_sb_info *c) { |
1260 | /* Cleanmarker currently occupies a whole programming region */ | 1261 | /* Cleanmarker currently occupies whole programming regions, |
1261 | c->cleanmarker_size = MTD_PROGREGION_SIZE(c->mtd); | 1262 | * either one or 2 for 8Byte STMicro flashes. */ |
1263 | c->cleanmarker_size = max(16u, c->mtd->writesize); | ||
1262 | 1264 | ||
1263 | /* Initialize write buffer */ | 1265 | /* Initialize write buffer */ |
1264 | init_rwsem(&c->wbuf_sem); | 1266 | init_rwsem(&c->wbuf_sem); |
1265 | c->wbuf_pagesize = MTD_PROGREGION_SIZE(c->mtd); | 1267 | c->wbuf_pagesize = c->mtd->writesize; |
1266 | c->wbuf_ofs = 0xFFFFFFFF; | 1268 | c->wbuf_ofs = 0xFFFFFFFF; |
1267 | 1269 | ||
1268 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); | 1270 | c->wbuf = kmalloc(c->wbuf_pagesize, GFP_KERNEL); |
diff --git a/fs/jffs2/write.c b/fs/jffs2/write.c index 1342f0158e9b..67176792e138 100644 --- a/fs/jffs2/write.c +++ b/fs/jffs2/write.c | |||
@@ -37,7 +37,6 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint | |||
37 | f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; | 37 | f->inocache->nodes = (struct jffs2_raw_node_ref *)f->inocache; |
38 | f->inocache->state = INO_STATE_PRESENT; | 38 | f->inocache->state = INO_STATE_PRESENT; |
39 | 39 | ||
40 | |||
41 | jffs2_add_ino_cache(c, f->inocache); | 40 | jffs2_add_ino_cache(c, f->inocache); |
42 | D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); | 41 | D1(printk(KERN_DEBUG "jffs2_do_new_inode(): Assigned ino# %d\n", f->inocache->ino)); |
43 | ri->ino = cpu_to_je32(f->inocache->ino); | 42 | ri->ino = cpu_to_je32(f->inocache->ino); |
@@ -57,12 +56,14 @@ int jffs2_do_new_inode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, uint | |||
57 | /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, | 56 | /* jffs2_write_dnode - given a raw_inode, allocate a full_dnode for it, |
58 | write it to the flash, link it into the existing inode/fragment list */ | 57 | write it to the flash, link it into the existing inode/fragment list */ |
59 | 58 | ||
60 | struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_inode *ri, const unsigned char *data, uint32_t datalen, uint32_t flash_ofs, int alloc_mode) | 59 | struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
60 | struct jffs2_raw_inode *ri, const unsigned char *data, | ||
61 | uint32_t datalen, int alloc_mode) | ||
61 | 62 | ||
62 | { | 63 | { |
63 | struct jffs2_raw_node_ref *raw; | ||
64 | struct jffs2_full_dnode *fn; | 64 | struct jffs2_full_dnode *fn; |
65 | size_t retlen; | 65 | size_t retlen; |
66 | uint32_t flash_ofs; | ||
66 | struct kvec vecs[2]; | 67 | struct kvec vecs[2]; |
67 | int ret; | 68 | int ret; |
68 | int retried = 0; | 69 | int retried = 0; |
@@ -78,34 +79,21 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
78 | vecs[1].iov_base = (unsigned char *)data; | 79 | vecs[1].iov_base = (unsigned char *)data; |
79 | vecs[1].iov_len = datalen; | 80 | vecs[1].iov_len = datalen; |
80 | 81 | ||
81 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | ||
82 | |||
83 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { | 82 | if (je32_to_cpu(ri->totlen) != sizeof(*ri) + datalen) { |
84 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); | 83 | printk(KERN_WARNING "jffs2_write_dnode: ri->totlen (0x%08x) != sizeof(*ri) (0x%08zx) + datalen (0x%08x)\n", je32_to_cpu(ri->totlen), sizeof(*ri), datalen); |
85 | } | 84 | } |
86 | raw = jffs2_alloc_raw_node_ref(); | ||
87 | if (!raw) | ||
88 | return ERR_PTR(-ENOMEM); | ||
89 | 85 | ||
90 | fn = jffs2_alloc_full_dnode(); | 86 | fn = jffs2_alloc_full_dnode(); |
91 | if (!fn) { | 87 | if (!fn) |
92 | jffs2_free_raw_node_ref(raw); | ||
93 | return ERR_PTR(-ENOMEM); | 88 | return ERR_PTR(-ENOMEM); |
94 | } | ||
95 | |||
96 | fn->ofs = je32_to_cpu(ri->offset); | ||
97 | fn->size = je32_to_cpu(ri->dsize); | ||
98 | fn->frags = 0; | ||
99 | 89 | ||
100 | /* check number of valid vecs */ | 90 | /* check number of valid vecs */ |
101 | if (!datalen || !data) | 91 | if (!datalen || !data) |
102 | cnt = 1; | 92 | cnt = 1; |
103 | retry: | 93 | retry: |
104 | fn->raw = raw; | 94 | flash_ofs = write_ofs(c); |
105 | 95 | ||
106 | raw->flash_offset = flash_ofs; | 96 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
107 | raw->__totlen = PAD(sizeof(*ri)+datalen); | ||
108 | raw->next_phys = NULL; | ||
109 | 97 | ||
110 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { | 98 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(ri->version) < f->highest_version)) { |
111 | BUG_ON(!retried); | 99 | BUG_ON(!retried); |
@@ -125,22 +113,16 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
125 | 113 | ||
126 | /* Mark the space as dirtied */ | 114 | /* Mark the space as dirtied */ |
127 | if (retlen) { | 115 | if (retlen) { |
128 | /* Doesn't belong to any inode */ | ||
129 | raw->next_in_ino = NULL; | ||
130 | |||
131 | /* Don't change raw->size to match retlen. We may have | 116 | /* Don't change raw->size to match retlen. We may have |
132 | written the node header already, and only the data will | 117 | written the node header already, and only the data will |
133 | seem corrupted, in which case the scan would skip over | 118 | seem corrupted, in which case the scan would skip over |
134 | any node we write before the original intended end of | 119 | any node we write before the original intended end of |
135 | this node */ | 120 | this node */ |
136 | raw->flash_offset |= REF_OBSOLETE; | 121 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*ri)+datalen), NULL); |
137 | jffs2_add_physical_node_ref(c, raw); | ||
138 | jffs2_mark_node_obsolete(c, raw); | ||
139 | } else { | 122 | } else { |
140 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 123 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
141 | jffs2_free_raw_node_ref(raw); | ||
142 | } | 124 | } |
143 | if (!retried && alloc_mode != ALLOC_NORETRY && (raw = jffs2_alloc_raw_node_ref())) { | 125 | if (!retried && alloc_mode != ALLOC_NORETRY) { |
144 | /* Try to reallocate space and retry */ | 126 | /* Try to reallocate space and retry */ |
145 | uint32_t dummy; | 127 | uint32_t dummy; |
146 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 128 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
@@ -153,19 +135,20 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
153 | jffs2_dbg_acct_paranoia_check(c, jeb); | 135 | jffs2_dbg_acct_paranoia_check(c, jeb); |
154 | 136 | ||
155 | if (alloc_mode == ALLOC_GC) { | 137 | if (alloc_mode == ALLOC_GC) { |
156 | ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &flash_ofs, | 138 | ret = jffs2_reserve_space_gc(c, sizeof(*ri) + datalen, &dummy, |
157 | &dummy, JFFS2_SUMMARY_INODE_SIZE); | 139 | JFFS2_SUMMARY_INODE_SIZE); |
158 | } else { | 140 | } else { |
159 | /* Locking pain */ | 141 | /* Locking pain */ |
160 | up(&f->sem); | 142 | up(&f->sem); |
161 | jffs2_complete_reservation(c); | 143 | jffs2_complete_reservation(c); |
162 | 144 | ||
163 | ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &flash_ofs, | 145 | ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &dummy, |
164 | &dummy, alloc_mode, JFFS2_SUMMARY_INODE_SIZE); | 146 | alloc_mode, JFFS2_SUMMARY_INODE_SIZE); |
165 | down(&f->sem); | 147 | down(&f->sem); |
166 | } | 148 | } |
167 | 149 | ||
168 | if (!ret) { | 150 | if (!ret) { |
151 | flash_ofs = write_ofs(c); | ||
169 | D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); | 152 | D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); |
170 | 153 | ||
171 | jffs2_dbg_acct_sanity_check(c,jeb); | 154 | jffs2_dbg_acct_sanity_check(c,jeb); |
@@ -174,7 +157,6 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
174 | goto retry; | 157 | goto retry; |
175 | } | 158 | } |
176 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 159 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
177 | jffs2_free_raw_node_ref(raw); | ||
178 | } | 160 | } |
179 | /* Release the full_dnode which is now useless, and return */ | 161 | /* Release the full_dnode which is now useless, and return */ |
180 | jffs2_free_full_dnode(fn); | 162 | jffs2_free_full_dnode(fn); |
@@ -188,20 +170,17 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
188 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || | 170 | if ((je32_to_cpu(ri->dsize) >= PAGE_CACHE_SIZE) || |
189 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && | 171 | ( ((je32_to_cpu(ri->offset)&(PAGE_CACHE_SIZE-1))==0) && |
190 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { | 172 | (je32_to_cpu(ri->dsize)+je32_to_cpu(ri->offset) == je32_to_cpu(ri->isize)))) { |
191 | raw->flash_offset |= REF_PRISTINE; | 173 | flash_ofs |= REF_PRISTINE; |
192 | } else { | 174 | } else { |
193 | raw->flash_offset |= REF_NORMAL; | 175 | flash_ofs |= REF_NORMAL; |
194 | } | 176 | } |
195 | jffs2_add_physical_node_ref(c, raw); | 177 | fn->raw = jffs2_add_physical_node_ref(c, flash_ofs, PAD(sizeof(*ri)+datalen), f->inocache); |
196 | 178 | fn->ofs = je32_to_cpu(ri->offset); | |
197 | /* Link into per-inode list */ | 179 | fn->size = je32_to_cpu(ri->dsize); |
198 | spin_lock(&c->erase_completion_lock); | 180 | fn->frags = 0; |
199 | raw->next_in_ino = f->inocache->nodes; | ||
200 | f->inocache->nodes = raw; | ||
201 | spin_unlock(&c->erase_completion_lock); | ||
202 | 181 | ||
203 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", | 182 | D1(printk(KERN_DEBUG "jffs2_write_dnode wrote node at 0x%08x(%d) with dsize 0x%x, csize 0x%x, node_crc 0x%08x, data_crc 0x%08x, totlen 0x%08x\n", |
204 | flash_ofs, ref_flags(raw), je32_to_cpu(ri->dsize), | 183 | flash_ofs & ~3, flash_ofs & 3, je32_to_cpu(ri->dsize), |
205 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), | 184 | je32_to_cpu(ri->csize), je32_to_cpu(ri->node_crc), |
206 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); | 185 | je32_to_cpu(ri->data_crc), je32_to_cpu(ri->totlen))); |
207 | 186 | ||
@@ -212,12 +191,14 @@ struct jffs2_full_dnode *jffs2_write_dnode(struct jffs2_sb_info *c, struct jffs2 | |||
212 | return fn; | 191 | return fn; |
213 | } | 192 | } |
214 | 193 | ||
215 | struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, struct jffs2_raw_dirent *rd, const unsigned char *name, uint32_t namelen, uint32_t flash_ofs, int alloc_mode) | 194 | struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jffs2_inode_info *f, |
195 | struct jffs2_raw_dirent *rd, const unsigned char *name, | ||
196 | uint32_t namelen, int alloc_mode) | ||
216 | { | 197 | { |
217 | struct jffs2_raw_node_ref *raw; | ||
218 | struct jffs2_full_dirent *fd; | 198 | struct jffs2_full_dirent *fd; |
219 | size_t retlen; | 199 | size_t retlen; |
220 | struct kvec vecs[2]; | 200 | struct kvec vecs[2]; |
201 | uint32_t flash_ofs; | ||
221 | int retried = 0; | 202 | int retried = 0; |
222 | int ret; | 203 | int ret; |
223 | 204 | ||
@@ -228,26 +209,16 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
228 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { | 209 | D1(if(je32_to_cpu(rd->hdr_crc) != crc32(0, rd, sizeof(struct jffs2_unknown_node)-4)) { |
229 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); | 210 | printk(KERN_CRIT "Eep. CRC not correct in jffs2_write_dirent()\n"); |
230 | BUG(); | 211 | BUG(); |
231 | } | 212 | }); |
232 | ); | ||
233 | 213 | ||
234 | vecs[0].iov_base = rd; | 214 | vecs[0].iov_base = rd; |
235 | vecs[0].iov_len = sizeof(*rd); | 215 | vecs[0].iov_len = sizeof(*rd); |
236 | vecs[1].iov_base = (unsigned char *)name; | 216 | vecs[1].iov_base = (unsigned char *)name; |
237 | vecs[1].iov_len = namelen; | 217 | vecs[1].iov_len = namelen; |
238 | 218 | ||
239 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); | ||
240 | |||
241 | raw = jffs2_alloc_raw_node_ref(); | ||
242 | |||
243 | if (!raw) | ||
244 | return ERR_PTR(-ENOMEM); | ||
245 | |||
246 | fd = jffs2_alloc_full_dirent(namelen+1); | 219 | fd = jffs2_alloc_full_dirent(namelen+1); |
247 | if (!fd) { | 220 | if (!fd) |
248 | jffs2_free_raw_node_ref(raw); | ||
249 | return ERR_PTR(-ENOMEM); | 221 | return ERR_PTR(-ENOMEM); |
250 | } | ||
251 | 222 | ||
252 | fd->version = je32_to_cpu(rd->version); | 223 | fd->version = je32_to_cpu(rd->version); |
253 | fd->ino = je32_to_cpu(rd->ino); | 224 | fd->ino = je32_to_cpu(rd->ino); |
@@ -257,11 +228,9 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
257 | fd->name[namelen]=0; | 228 | fd->name[namelen]=0; |
258 | 229 | ||
259 | retry: | 230 | retry: |
260 | fd->raw = raw; | 231 | flash_ofs = write_ofs(c); |
261 | 232 | ||
262 | raw->flash_offset = flash_ofs; | 233 | jffs2_dbg_prewrite_paranoia_check(c, flash_ofs, vecs[0].iov_len + vecs[1].iov_len); |
263 | raw->__totlen = PAD(sizeof(*rd)+namelen); | ||
264 | raw->next_phys = NULL; | ||
265 | 234 | ||
266 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { | 235 | if ((alloc_mode!=ALLOC_GC) && (je32_to_cpu(rd->version) < f->highest_version)) { |
267 | BUG_ON(!retried); | 236 | BUG_ON(!retried); |
@@ -280,15 +249,11 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
280 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); | 249 | sizeof(*rd)+namelen, flash_ofs, ret, retlen); |
281 | /* Mark the space as dirtied */ | 250 | /* Mark the space as dirtied */ |
282 | if (retlen) { | 251 | if (retlen) { |
283 | raw->next_in_ino = NULL; | 252 | jffs2_add_physical_node_ref(c, flash_ofs | REF_OBSOLETE, PAD(sizeof(*rd)+namelen), NULL); |
284 | raw->flash_offset |= REF_OBSOLETE; | ||
285 | jffs2_add_physical_node_ref(c, raw); | ||
286 | jffs2_mark_node_obsolete(c, raw); | ||
287 | } else { | 253 | } else { |
288 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", raw->flash_offset); | 254 | printk(KERN_NOTICE "Not marking the space at 0x%08x as dirty because the flash driver returned retlen zero\n", flash_ofs); |
289 | jffs2_free_raw_node_ref(raw); | ||
290 | } | 255 | } |
291 | if (!retried && (raw = jffs2_alloc_raw_node_ref())) { | 256 | if (!retried) { |
292 | /* Try to reallocate space and retry */ | 257 | /* Try to reallocate space and retry */ |
293 | uint32_t dummy; | 258 | uint32_t dummy; |
294 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; | 259 | struct jffs2_eraseblock *jeb = &c->blocks[flash_ofs / c->sector_size]; |
@@ -301,39 +266,33 @@ struct jffs2_full_dirent *jffs2_write_dirent(struct jffs2_sb_info *c, struct jff | |||
301 | jffs2_dbg_acct_paranoia_check(c, jeb); | 266 | jffs2_dbg_acct_paranoia_check(c, jeb); |
302 | 267 | ||
303 | if (alloc_mode == ALLOC_GC) { | 268 | if (alloc_mode == ALLOC_GC) { |
304 | ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &flash_ofs, | 269 | ret = jffs2_reserve_space_gc(c, sizeof(*rd) + namelen, &dummy, |
305 | &dummy, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 270 | JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
306 | } else { | 271 | } else { |
307 | /* Locking pain */ | 272 | /* Locking pain */ |
308 | up(&f->sem); | 273 | up(&f->sem); |
309 | jffs2_complete_reservation(c); | 274 | jffs2_complete_reservation(c); |
310 | 275 | ||
311 | ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &flash_ofs, | 276 | ret = jffs2_reserve_space(c, sizeof(*rd) + namelen, &dummy, |
312 | &dummy, alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 277 | alloc_mode, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
313 | down(&f->sem); | 278 | down(&f->sem); |
314 | } | 279 | } |
315 | 280 | ||
316 | if (!ret) { | 281 | if (!ret) { |
282 | flash_ofs = write_ofs(c); | ||
317 | D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); | 283 | D1(printk(KERN_DEBUG "Allocated space at 0x%08x to retry failed write.\n", flash_ofs)); |
318 | jffs2_dbg_acct_sanity_check(c,jeb); | 284 | jffs2_dbg_acct_sanity_check(c,jeb); |
319 | jffs2_dbg_acct_paranoia_check(c, jeb); | 285 | jffs2_dbg_acct_paranoia_check(c, jeb); |
320 | goto retry; | 286 | goto retry; |
321 | } | 287 | } |
322 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); | 288 | D1(printk(KERN_DEBUG "Failed to allocate space to retry failed write: %d!\n", ret)); |
323 | jffs2_free_raw_node_ref(raw); | ||
324 | } | 289 | } |
325 | /* Release the full_dnode which is now useless, and return */ | 290 | /* Release the full_dnode which is now useless, and return */ |
326 | jffs2_free_full_dirent(fd); | 291 | jffs2_free_full_dirent(fd); |
327 | return ERR_PTR(ret?ret:-EIO); | 292 | return ERR_PTR(ret?ret:-EIO); |
328 | } | 293 | } |
329 | /* Mark the space used */ | 294 | /* Mark the space used */ |
330 | raw->flash_offset |= REF_PRISTINE; | 295 | fd->raw = jffs2_add_physical_node_ref(c, flash_ofs | REF_PRISTINE, PAD(sizeof(*rd)+namelen), f->inocache); |
331 | jffs2_add_physical_node_ref(c, raw); | ||
332 | |||
333 | spin_lock(&c->erase_completion_lock); | ||
334 | raw->next_in_ino = f->inocache->nodes; | ||
335 | f->inocache->nodes = raw; | ||
336 | spin_unlock(&c->erase_completion_lock); | ||
337 | 296 | ||
338 | if (retried) { | 297 | if (retried) { |
339 | jffs2_dbg_acct_sanity_check(c,NULL); | 298 | jffs2_dbg_acct_sanity_check(c,NULL); |
@@ -359,14 +318,14 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
359 | struct jffs2_full_dnode *fn; | 318 | struct jffs2_full_dnode *fn; |
360 | unsigned char *comprbuf = NULL; | 319 | unsigned char *comprbuf = NULL; |
361 | uint16_t comprtype = JFFS2_COMPR_NONE; | 320 | uint16_t comprtype = JFFS2_COMPR_NONE; |
362 | uint32_t phys_ofs, alloclen; | 321 | uint32_t alloclen; |
363 | uint32_t datalen, cdatalen; | 322 | uint32_t datalen, cdatalen; |
364 | int retried = 0; | 323 | int retried = 0; |
365 | 324 | ||
366 | retry: | 325 | retry: |
367 | D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); | 326 | D2(printk(KERN_DEBUG "jffs2_commit_write() loop: 0x%x to write to 0x%x\n", writelen, offset)); |
368 | 327 | ||
369 | ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, &phys_ofs, | 328 | ret = jffs2_reserve_space(c, sizeof(*ri) + JFFS2_MIN_DATA_LEN, |
370 | &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); | 329 | &alloclen, ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE); |
371 | if (ret) { | 330 | if (ret) { |
372 | D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); | 331 | D1(printk(KERN_DEBUG "jffs2_reserve_space returned %d\n", ret)); |
@@ -394,7 +353,7 @@ int jffs2_write_inode_range(struct jffs2_sb_info *c, struct jffs2_inode_info *f, | |||
394 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 353 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
395 | ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); | 354 | ri->data_crc = cpu_to_je32(crc32(0, comprbuf, cdatalen)); |
396 | 355 | ||
397 | fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, phys_ofs, ALLOC_NORETRY); | 356 | fn = jffs2_write_dnode(c, f, ri, comprbuf, cdatalen, ALLOC_NORETRY); |
398 | 357 | ||
399 | jffs2_free_comprbuf(comprbuf, buf); | 358 | jffs2_free_comprbuf(comprbuf, buf); |
400 | 359 | ||
@@ -448,13 +407,13 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
448 | struct jffs2_raw_dirent *rd; | 407 | struct jffs2_raw_dirent *rd; |
449 | struct jffs2_full_dnode *fn; | 408 | struct jffs2_full_dnode *fn; |
450 | struct jffs2_full_dirent *fd; | 409 | struct jffs2_full_dirent *fd; |
451 | uint32_t alloclen, phys_ofs; | 410 | uint32_t alloclen; |
452 | int ret; | 411 | int ret; |
453 | 412 | ||
454 | /* Try to reserve enough space for both node and dirent. | 413 | /* Try to reserve enough space for both node and dirent. |
455 | * Just the node will do for now, though | 414 | * Just the node will do for now, though |
456 | */ | 415 | */ |
457 | ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL, | 416 | ret = jffs2_reserve_space(c, sizeof(*ri), &alloclen, ALLOC_NORMAL, |
458 | JFFS2_SUMMARY_INODE_SIZE); | 417 | JFFS2_SUMMARY_INODE_SIZE); |
459 | D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); | 418 | D1(printk(KERN_DEBUG "jffs2_do_create(): reserved 0x%x bytes\n", alloclen)); |
460 | if (ret) { | 419 | if (ret) { |
@@ -465,7 +424,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
465 | ri->data_crc = cpu_to_je32(0); | 424 | ri->data_crc = cpu_to_je32(0); |
466 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); | 425 | ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8)); |
467 | 426 | ||
468 | fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL); | 427 | fn = jffs2_write_dnode(c, f, ri, NULL, 0, ALLOC_NORMAL); |
469 | 428 | ||
470 | D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", | 429 | D1(printk(KERN_DEBUG "jffs2_do_create created file with mode 0x%x\n", |
471 | jemode_to_cpu(ri->mode))); | 430 | jemode_to_cpu(ri->mode))); |
@@ -484,7 +443,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
484 | 443 | ||
485 | up(&f->sem); | 444 | up(&f->sem); |
486 | jffs2_complete_reservation(c); | 445 | jffs2_complete_reservation(c); |
487 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 446 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
488 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 447 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
489 | 448 | ||
490 | if (ret) { | 449 | if (ret) { |
@@ -516,7 +475,7 @@ int jffs2_do_create(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, str | |||
516 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 475 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
517 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | 476 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); |
518 | 477 | ||
519 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); | 478 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); |
520 | 479 | ||
521 | jffs2_free_raw_dirent(rd); | 480 | jffs2_free_raw_dirent(rd); |
522 | 481 | ||
@@ -545,7 +504,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
545 | { | 504 | { |
546 | struct jffs2_raw_dirent *rd; | 505 | struct jffs2_raw_dirent *rd; |
547 | struct jffs2_full_dirent *fd; | 506 | struct jffs2_full_dirent *fd; |
548 | uint32_t alloclen, phys_ofs; | 507 | uint32_t alloclen; |
549 | int ret; | 508 | int ret; |
550 | 509 | ||
551 | if (1 /* alternative branch needs testing */ || | 510 | if (1 /* alternative branch needs testing */ || |
@@ -556,7 +515,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
556 | if (!rd) | 515 | if (!rd) |
557 | return -ENOMEM; | 516 | return -ENOMEM; |
558 | 517 | ||
559 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 518 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
560 | ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 519 | ALLOC_DELETION, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
561 | if (ret) { | 520 | if (ret) { |
562 | jffs2_free_raw_dirent(rd); | 521 | jffs2_free_raw_dirent(rd); |
@@ -580,7 +539,7 @@ int jffs2_do_unlink(struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, | |||
580 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 539 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
581 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | 540 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); |
582 | 541 | ||
583 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_DELETION); | 542 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_DELETION); |
584 | 543 | ||
585 | jffs2_free_raw_dirent(rd); | 544 | jffs2_free_raw_dirent(rd); |
586 | 545 | ||
@@ -659,14 +618,14 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint | |||
659 | { | 618 | { |
660 | struct jffs2_raw_dirent *rd; | 619 | struct jffs2_raw_dirent *rd; |
661 | struct jffs2_full_dirent *fd; | 620 | struct jffs2_full_dirent *fd; |
662 | uint32_t alloclen, phys_ofs; | 621 | uint32_t alloclen; |
663 | int ret; | 622 | int ret; |
664 | 623 | ||
665 | rd = jffs2_alloc_raw_dirent(); | 624 | rd = jffs2_alloc_raw_dirent(); |
666 | if (!rd) | 625 | if (!rd) |
667 | return -ENOMEM; | 626 | return -ENOMEM; |
668 | 627 | ||
669 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, | 628 | ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &alloclen, |
670 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); | 629 | ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(namelen)); |
671 | if (ret) { | 630 | if (ret) { |
672 | jffs2_free_raw_dirent(rd); | 631 | jffs2_free_raw_dirent(rd); |
@@ -692,7 +651,7 @@ int jffs2_do_link (struct jffs2_sb_info *c, struct jffs2_inode_info *dir_f, uint | |||
692 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); | 651 | rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8)); |
693 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); | 652 | rd->name_crc = cpu_to_je32(crc32(0, name, namelen)); |
694 | 653 | ||
695 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, phys_ofs, ALLOC_NORMAL); | 654 | fd = jffs2_write_dirent(c, dir_f, rd, name, namelen, ALLOC_NORMAL); |
696 | 655 | ||
697 | jffs2_free_raw_dirent(rd); | 656 | jffs2_free_raw_dirent(rd); |
698 | 657 | ||
diff --git a/fs/jffs2/xattr.c b/fs/jffs2/xattr.c new file mode 100644 index 000000000000..2d82e250be34 --- /dev/null +++ b/fs/jffs2/xattr.c | |||
@@ -0,0 +1,1238 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/slab.h> | ||
13 | #include <linux/fs.h> | ||
14 | #include <linux/time.h> | ||
15 | #include <linux/pagemap.h> | ||
16 | #include <linux/highmem.h> | ||
17 | #include <linux/crc32.h> | ||
18 | #include <linux/jffs2.h> | ||
19 | #include <linux/xattr.h> | ||
20 | #include <linux/mtd/mtd.h> | ||
21 | #include "nodelist.h" | ||
22 | /* -------- xdatum related functions ---------------- | ||
23 | * xattr_datum_hashkey(xprefix, xname, xvalue, xsize) | ||
24 | * is used to calcurate xdatum hashkey. The reminder of hashkey into XATTRINDEX_HASHSIZE is | ||
25 | * the index of the xattr name/value pair cache (c->xattrindex). | ||
26 | * unload_xattr_datum(c, xd) | ||
27 | * is used to release xattr name/value pair and detach from c->xattrindex. | ||
28 | * reclaim_xattr_datum(c) | ||
29 | * is used to reclaim xattr name/value pairs on the xattr name/value pair cache when | ||
30 | * memory usage by cache is over c->xdatum_mem_threshold. Currentry, this threshold | ||
31 | * is hard coded as 32KiB. | ||
32 | * delete_xattr_datum_node(c, xd) | ||
33 | * is used to delete a jffs2 node is dominated by xdatum. When EBS(Erase Block Summary) is | ||
34 | * enabled, it overwrites the obsolete node by myself. | ||
35 | * delete_xattr_datum(c, xd) | ||
36 | * is used to delete jffs2_xattr_datum object. It must be called with 0-value of reference | ||
37 | * counter. (It means how many jffs2_xattr_ref object refers this xdatum.) | ||
38 | * do_verify_xattr_datum(c, xd) | ||
39 | * is used to load the xdatum informations without name/value pair from the medium. | ||
40 | * It's necessary once, because those informations are not collected during mounting | ||
41 | * process when EBS is enabled. | ||
42 | * 0 will be returned, if success. An negative return value means recoverable error, and | ||
43 | * positive return value means unrecoverable error. Thus, caller must remove this xdatum | ||
44 | * and xref when it returned positive value. | ||
45 | * do_load_xattr_datum(c, xd) | ||
46 | * is used to load name/value pair from the medium. | ||
47 | * The meanings of return value is same as do_verify_xattr_datum(). | ||
48 | * load_xattr_datum(c, xd) | ||
49 | * is used to be as a wrapper of do_verify_xattr_datum() and do_load_xattr_datum(). | ||
50 | * If xd need to call do_verify_xattr_datum() at first, it's called before calling | ||
51 | * do_load_xattr_datum(). The meanings of return value is same as do_verify_xattr_datum(). | ||
52 | * save_xattr_datum(c, xd) | ||
53 | * is used to write xdatum to medium. xd->version will be incremented. | ||
54 | * create_xattr_datum(c, xprefix, xname, xvalue, xsize) | ||
55 | * is used to create new xdatum and write to medium. | ||
56 | * -------------------------------------------------- */ | ||
57 | |||
58 | static uint32_t xattr_datum_hashkey(int xprefix, const char *xname, const char *xvalue, int xsize) | ||
59 | { | ||
60 | int name_len = strlen(xname); | ||
61 | |||
62 | return crc32(xprefix, xname, name_len) ^ crc32(xprefix, xvalue, xsize); | ||
63 | } | ||
64 | |||
65 | static void unload_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
66 | { | ||
67 | /* must be called under down_write(xattr_sem) */ | ||
68 | D1(dbg_xattr("%s: xid=%u, version=%u\n", __FUNCTION__, xd->xid, xd->version)); | ||
69 | if (xd->xname) { | ||
70 | c->xdatum_mem_usage -= (xd->name_len + 1 + xd->value_len); | ||
71 | kfree(xd->xname); | ||
72 | } | ||
73 | |||
74 | list_del_init(&xd->xindex); | ||
75 | xd->hashkey = 0; | ||
76 | xd->xname = NULL; | ||
77 | xd->xvalue = NULL; | ||
78 | } | ||
79 | |||
80 | static void reclaim_xattr_datum(struct jffs2_sb_info *c) | ||
81 | { | ||
82 | /* must be called under down_write(xattr_sem) */ | ||
83 | struct jffs2_xattr_datum *xd, *_xd; | ||
84 | uint32_t target, before; | ||
85 | static int index = 0; | ||
86 | int count; | ||
87 | |||
88 | if (c->xdatum_mem_threshold > c->xdatum_mem_usage) | ||
89 | return; | ||
90 | |||
91 | before = c->xdatum_mem_usage; | ||
92 | target = c->xdatum_mem_usage * 4 / 5; /* 20% reduction */ | ||
93 | for (count = 0; count < XATTRINDEX_HASHSIZE; count++) { | ||
94 | list_for_each_entry_safe(xd, _xd, &c->xattrindex[index], xindex) { | ||
95 | if (xd->flags & JFFS2_XFLAGS_HOT) { | ||
96 | xd->flags &= ~JFFS2_XFLAGS_HOT; | ||
97 | } else if (!(xd->flags & JFFS2_XFLAGS_BIND)) { | ||
98 | unload_xattr_datum(c, xd); | ||
99 | } | ||
100 | if (c->xdatum_mem_usage <= target) | ||
101 | goto out; | ||
102 | } | ||
103 | index = (index+1) % XATTRINDEX_HASHSIZE; | ||
104 | } | ||
105 | out: | ||
106 | JFFS2_NOTICE("xdatum_mem_usage from %u byte to %u byte (%u byte reclaimed)\n", | ||
107 | before, c->xdatum_mem_usage, before - c->xdatum_mem_usage); | ||
108 | } | ||
109 | |||
110 | static void delete_xattr_datum_node(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
111 | { | ||
112 | /* must be called under down_write(xattr_sem) */ | ||
113 | struct jffs2_raw_xattr rx; | ||
114 | size_t length; | ||
115 | int rc; | ||
116 | |||
117 | if (!xd->node) { | ||
118 | JFFS2_WARNING("xdatum (xid=%u) is removed twice.\n", xd->xid); | ||
119 | return; | ||
120 | } | ||
121 | if (jffs2_sum_active()) { | ||
122 | memset(&rx, 0xff, sizeof(struct jffs2_raw_xattr)); | ||
123 | rc = jffs2_flash_read(c, ref_offset(xd->node), | ||
124 | sizeof(struct jffs2_unknown_node), | ||
125 | &length, (char *)&rx); | ||
126 | if (rc || length != sizeof(struct jffs2_unknown_node)) { | ||
127 | JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", | ||
128 | rc, sizeof(struct jffs2_unknown_node), | ||
129 | length, ref_offset(xd->node)); | ||
130 | } | ||
131 | rc = jffs2_flash_write(c, ref_offset(xd->node), sizeof(rx), | ||
132 | &length, (char *)&rx); | ||
133 | if (rc || length != sizeof(struct jffs2_raw_xattr)) { | ||
134 | JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu ar %#08x\n", | ||
135 | rc, sizeof(rx), length, ref_offset(xd->node)); | ||
136 | } | ||
137 | } | ||
138 | spin_lock(&c->erase_completion_lock); | ||
139 | xd->node->next_in_ino = NULL; | ||
140 | spin_unlock(&c->erase_completion_lock); | ||
141 | jffs2_mark_node_obsolete(c, xd->node); | ||
142 | xd->node = NULL; | ||
143 | } | ||
144 | |||
145 | static void delete_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
146 | { | ||
147 | /* must be called under down_write(xattr_sem) */ | ||
148 | BUG_ON(xd->refcnt); | ||
149 | |||
150 | unload_xattr_datum(c, xd); | ||
151 | if (xd->node) { | ||
152 | delete_xattr_datum_node(c, xd); | ||
153 | xd->node = NULL; | ||
154 | } | ||
155 | jffs2_free_xattr_datum(xd); | ||
156 | } | ||
157 | |||
158 | static int do_verify_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
159 | { | ||
160 | /* must be called under down_write(xattr_sem) */ | ||
161 | struct jffs2_eraseblock *jeb; | ||
162 | struct jffs2_raw_xattr rx; | ||
163 | size_t readlen; | ||
164 | uint32_t crc, totlen; | ||
165 | int rc; | ||
166 | |||
167 | BUG_ON(!xd->node); | ||
168 | BUG_ON(ref_flags(xd->node) != REF_UNCHECKED); | ||
169 | |||
170 | rc = jffs2_flash_read(c, ref_offset(xd->node), sizeof(rx), &readlen, (char *)&rx); | ||
171 | if (rc || readlen != sizeof(rx)) { | ||
172 | JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", | ||
173 | rc, sizeof(rx), readlen, ref_offset(xd->node)); | ||
174 | return rc ? rc : -EIO; | ||
175 | } | ||
176 | crc = crc32(0, &rx, sizeof(rx) - 4); | ||
177 | if (crc != je32_to_cpu(rx.node_crc)) { | ||
178 | if (je32_to_cpu(rx.node_crc) != 0xffffffff) | ||
179 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
180 | ref_offset(xd->node), je32_to_cpu(rx.hdr_crc), crc); | ||
181 | return EIO; | ||
182 | } | ||
183 | totlen = PAD(sizeof(rx) + rx.name_len + 1 + je16_to_cpu(rx.value_len)); | ||
184 | if (je16_to_cpu(rx.magic) != JFFS2_MAGIC_BITMASK | ||
185 | || je16_to_cpu(rx.nodetype) != JFFS2_NODETYPE_XATTR | ||
186 | || je32_to_cpu(rx.totlen) != totlen | ||
187 | || je32_to_cpu(rx.xid) != xd->xid | ||
188 | || je32_to_cpu(rx.version) != xd->version) { | ||
189 | JFFS2_ERROR("inconsistent xdatum at %#08x, magic=%#04x/%#04x, " | ||
190 | "nodetype=%#04x/%#04x, totlen=%u/%u, xid=%u/%u, version=%u/%u\n", | ||
191 | ref_offset(xd->node), je16_to_cpu(rx.magic), JFFS2_MAGIC_BITMASK, | ||
192 | je16_to_cpu(rx.nodetype), JFFS2_NODETYPE_XATTR, | ||
193 | je32_to_cpu(rx.totlen), totlen, | ||
194 | je32_to_cpu(rx.xid), xd->xid, | ||
195 | je32_to_cpu(rx.version), xd->version); | ||
196 | return EIO; | ||
197 | } | ||
198 | xd->xprefix = rx.xprefix; | ||
199 | xd->name_len = rx.name_len; | ||
200 | xd->value_len = je16_to_cpu(rx.value_len); | ||
201 | xd->data_crc = je32_to_cpu(rx.data_crc); | ||
202 | |||
203 | /* This JFFS2_NODETYPE_XATTR node is checked */ | ||
204 | jeb = &c->blocks[ref_offset(xd->node) / c->sector_size]; | ||
205 | totlen = PAD(je32_to_cpu(rx.totlen)); | ||
206 | |||
207 | spin_lock(&c->erase_completion_lock); | ||
208 | c->unchecked_size -= totlen; c->used_size += totlen; | ||
209 | jeb->unchecked_size -= totlen; jeb->used_size += totlen; | ||
210 | xd->node->flash_offset = ref_offset(xd->node) | REF_PRISTINE; | ||
211 | spin_unlock(&c->erase_completion_lock); | ||
212 | |||
213 | /* unchecked xdatum is chained with c->xattr_unchecked */ | ||
214 | list_del_init(&xd->xindex); | ||
215 | |||
216 | dbg_xattr("success on verfying xdatum (xid=%u, version=%u)\n", | ||
217 | xd->xid, xd->version); | ||
218 | |||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | static int do_load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
223 | { | ||
224 | /* must be called under down_write(xattr_sem) */ | ||
225 | char *data; | ||
226 | size_t readlen; | ||
227 | uint32_t crc, length; | ||
228 | int i, ret, retry = 0; | ||
229 | |||
230 | BUG_ON(!xd->node); | ||
231 | BUG_ON(ref_flags(xd->node) != REF_PRISTINE); | ||
232 | BUG_ON(!list_empty(&xd->xindex)); | ||
233 | retry: | ||
234 | length = xd->name_len + 1 + xd->value_len; | ||
235 | data = kmalloc(length, GFP_KERNEL); | ||
236 | if (!data) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | ret = jffs2_flash_read(c, ref_offset(xd->node)+sizeof(struct jffs2_raw_xattr), | ||
240 | length, &readlen, data); | ||
241 | |||
242 | if (ret || length!=readlen) { | ||
243 | JFFS2_WARNING("jffs2_flash_read() returned %d, request=%d, readlen=%zu, at %#08x\n", | ||
244 | ret, length, readlen, ref_offset(xd->node)); | ||
245 | kfree(data); | ||
246 | return ret ? ret : -EIO; | ||
247 | } | ||
248 | |||
249 | data[xd->name_len] = '\0'; | ||
250 | crc = crc32(0, data, length); | ||
251 | if (crc != xd->data_crc) { | ||
252 | JFFS2_WARNING("node CRC failed (JFFS2_NODETYPE_XREF)" | ||
253 | " at %#08x, read: 0x%08x calculated: 0x%08x\n", | ||
254 | ref_offset(xd->node), xd->data_crc, crc); | ||
255 | kfree(data); | ||
256 | return EIO; | ||
257 | } | ||
258 | |||
259 | xd->flags |= JFFS2_XFLAGS_HOT; | ||
260 | xd->xname = data; | ||
261 | xd->xvalue = data + xd->name_len+1; | ||
262 | |||
263 | c->xdatum_mem_usage += length; | ||
264 | |||
265 | xd->hashkey = xattr_datum_hashkey(xd->xprefix, xd->xname, xd->xvalue, xd->value_len); | ||
266 | i = xd->hashkey % XATTRINDEX_HASHSIZE; | ||
267 | list_add(&xd->xindex, &c->xattrindex[i]); | ||
268 | if (!retry) { | ||
269 | retry = 1; | ||
270 | reclaim_xattr_datum(c); | ||
271 | if (!xd->xname) | ||
272 | goto retry; | ||
273 | } | ||
274 | |||
275 | dbg_xattr("success on loading xdatum (xid=%u, xprefix=%u, xname='%s')\n", | ||
276 | xd->xid, xd->xprefix, xd->xname); | ||
277 | |||
278 | return 0; | ||
279 | } | ||
280 | |||
281 | static int load_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
282 | { | ||
283 | /* must be called under down_write(xattr_sem); | ||
284 | * rc < 0 : recoverable error, try again | ||
285 | * rc = 0 : success | ||
286 | * rc > 0 : Unrecoverable error, this node should be deleted. | ||
287 | */ | ||
288 | int rc = 0; | ||
289 | BUG_ON(xd->xname); | ||
290 | if (!xd->node) | ||
291 | return EIO; | ||
292 | if (unlikely(ref_flags(xd->node) != REF_PRISTINE)) { | ||
293 | rc = do_verify_xattr_datum(c, xd); | ||
294 | if (rc > 0) { | ||
295 | list_del_init(&xd->xindex); | ||
296 | delete_xattr_datum_node(c, xd); | ||
297 | } | ||
298 | } | ||
299 | if (!rc) | ||
300 | rc = do_load_xattr_datum(c, xd); | ||
301 | return rc; | ||
302 | } | ||
303 | |||
304 | static int save_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
305 | { | ||
306 | /* must be called under down_write(xattr_sem) */ | ||
307 | struct jffs2_raw_node_ref *raw; | ||
308 | struct jffs2_raw_xattr rx; | ||
309 | struct kvec vecs[2]; | ||
310 | size_t length; | ||
311 | int rc, totlen; | ||
312 | uint32_t phys_ofs = write_ofs(c); | ||
313 | |||
314 | BUG_ON(!xd->xname); | ||
315 | |||
316 | vecs[0].iov_base = ℞ | ||
317 | vecs[0].iov_len = PAD(sizeof(rx)); | ||
318 | vecs[1].iov_base = xd->xname; | ||
319 | vecs[1].iov_len = xd->name_len + 1 + xd->value_len; | ||
320 | totlen = vecs[0].iov_len + vecs[1].iov_len; | ||
321 | |||
322 | /* Setup raw-xattr */ | ||
323 | rx.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | ||
324 | rx.nodetype = cpu_to_je16(JFFS2_NODETYPE_XATTR); | ||
325 | rx.totlen = cpu_to_je32(PAD(totlen)); | ||
326 | rx.hdr_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_unknown_node) - 4)); | ||
327 | |||
328 | rx.xid = cpu_to_je32(xd->xid); | ||
329 | rx.version = cpu_to_je32(++xd->version); | ||
330 | rx.xprefix = xd->xprefix; | ||
331 | rx.name_len = xd->name_len; | ||
332 | rx.value_len = cpu_to_je16(xd->value_len); | ||
333 | rx.data_crc = cpu_to_je32(crc32(0, vecs[1].iov_base, vecs[1].iov_len)); | ||
334 | rx.node_crc = cpu_to_je32(crc32(0, &rx, sizeof(struct jffs2_raw_xattr) - 4)); | ||
335 | |||
336 | rc = jffs2_flash_writev(c, vecs, 2, phys_ofs, &length, 0); | ||
337 | if (rc || totlen != length) { | ||
338 | JFFS2_WARNING("jffs2_flash_writev()=%d, req=%u, wrote=%zu, at %#08x\n", | ||
339 | rc, totlen, length, phys_ofs); | ||
340 | rc = rc ? rc : -EIO; | ||
341 | if (length) | ||
342 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(totlen), NULL); | ||
343 | |||
344 | return rc; | ||
345 | } | ||
346 | |||
347 | /* success */ | ||
348 | raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(totlen), NULL); | ||
349 | /* FIXME */ raw->next_in_ino = (void *)xd; | ||
350 | |||
351 | if (xd->node) | ||
352 | delete_xattr_datum_node(c, xd); | ||
353 | xd->node = raw; | ||
354 | |||
355 | dbg_xattr("success on saving xdatum (xid=%u, version=%u, xprefix=%u, xname='%s')\n", | ||
356 | xd->xid, xd->version, xd->xprefix, xd->xname); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static struct jffs2_xattr_datum *create_xattr_datum(struct jffs2_sb_info *c, | ||
362 | int xprefix, const char *xname, | ||
363 | const char *xvalue, int xsize) | ||
364 | { | ||
365 | /* must be called under down_write(xattr_sem) */ | ||
366 | struct jffs2_xattr_datum *xd; | ||
367 | uint32_t hashkey, name_len; | ||
368 | char *data; | ||
369 | int i, rc; | ||
370 | |||
371 | /* Search xattr_datum has same xname/xvalue by index */ | ||
372 | hashkey = xattr_datum_hashkey(xprefix, xname, xvalue, xsize); | ||
373 | i = hashkey % XATTRINDEX_HASHSIZE; | ||
374 | list_for_each_entry(xd, &c->xattrindex[i], xindex) { | ||
375 | if (xd->hashkey==hashkey | ||
376 | && xd->xprefix==xprefix | ||
377 | && xd->value_len==xsize | ||
378 | && !strcmp(xd->xname, xname) | ||
379 | && !memcmp(xd->xvalue, xvalue, xsize)) { | ||
380 | xd->refcnt++; | ||
381 | return xd; | ||
382 | } | ||
383 | } | ||
384 | |||
385 | /* Not found, Create NEW XATTR-Cache */ | ||
386 | name_len = strlen(xname); | ||
387 | |||
388 | xd = jffs2_alloc_xattr_datum(); | ||
389 | if (!xd) | ||
390 | return ERR_PTR(-ENOMEM); | ||
391 | |||
392 | data = kmalloc(name_len + 1 + xsize, GFP_KERNEL); | ||
393 | if (!data) { | ||
394 | jffs2_free_xattr_datum(xd); | ||
395 | return ERR_PTR(-ENOMEM); | ||
396 | } | ||
397 | strcpy(data, xname); | ||
398 | memcpy(data + name_len + 1, xvalue, xsize); | ||
399 | |||
400 | xd->refcnt = 1; | ||
401 | xd->xid = ++c->highest_xid; | ||
402 | xd->flags |= JFFS2_XFLAGS_HOT; | ||
403 | xd->xprefix = xprefix; | ||
404 | |||
405 | xd->hashkey = hashkey; | ||
406 | xd->xname = data; | ||
407 | xd->xvalue = data + name_len + 1; | ||
408 | xd->name_len = name_len; | ||
409 | xd->value_len = xsize; | ||
410 | xd->data_crc = crc32(0, data, xd->name_len + 1 + xd->value_len); | ||
411 | |||
412 | rc = save_xattr_datum(c, xd); | ||
413 | if (rc) { | ||
414 | kfree(xd->xname); | ||
415 | jffs2_free_xattr_datum(xd); | ||
416 | return ERR_PTR(rc); | ||
417 | } | ||
418 | |||
419 | /* Insert Hash Index */ | ||
420 | i = hashkey % XATTRINDEX_HASHSIZE; | ||
421 | list_add(&xd->xindex, &c->xattrindex[i]); | ||
422 | |||
423 | c->xdatum_mem_usage += (xd->name_len + 1 + xd->value_len); | ||
424 | reclaim_xattr_datum(c); | ||
425 | |||
426 | return xd; | ||
427 | } | ||
428 | |||
429 | /* -------- xref related functions ------------------ | ||
430 | * verify_xattr_ref(c, ref) | ||
431 | * is used to load xref information from medium. Because summary data does not | ||
432 | * contain xid/ino, it's necessary to verify once while mounting process. | ||
433 | * delete_xattr_ref_node(c, ref) | ||
434 | * is used to delete a jffs2 node is dominated by xref. When EBS is enabled, | ||
435 | * it overwrites the obsolete node by myself. | ||
436 | * delete_xattr_ref(c, ref) | ||
437 | * is used to delete jffs2_xattr_ref object. If the reference counter of xdatum | ||
438 | * is refered by this xref become 0, delete_xattr_datum() is called later. | ||
439 | * save_xattr_ref(c, ref) | ||
440 | * is used to write xref to medium. | ||
441 | * create_xattr_ref(c, ic, xd) | ||
442 | * is used to create a new xref and write to medium. | ||
443 | * jffs2_xattr_delete_inode(c, ic) | ||
444 | * is called to remove xrefs related to obsolete inode when inode is unlinked. | ||
445 | * jffs2_xattr_free_inode(c, ic) | ||
446 | * is called to release xattr related objects when unmounting. | ||
447 | * check_xattr_ref_inode(c, ic) | ||
448 | * is used to confirm inode does not have duplicate xattr name/value pair. | ||
449 | * -------------------------------------------------- */ | ||
450 | static int verify_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | ||
451 | { | ||
452 | struct jffs2_eraseblock *jeb; | ||
453 | struct jffs2_raw_xref rr; | ||
454 | size_t readlen; | ||
455 | uint32_t crc, totlen; | ||
456 | int rc; | ||
457 | |||
458 | BUG_ON(ref_flags(ref->node) != REF_UNCHECKED); | ||
459 | |||
460 | rc = jffs2_flash_read(c, ref_offset(ref->node), sizeof(rr), &readlen, (char *)&rr); | ||
461 | if (rc || sizeof(rr) != readlen) { | ||
462 | JFFS2_WARNING("jffs2_flash_read()=%d, req=%zu, read=%zu, at %#08x\n", | ||
463 | rc, sizeof(rr), readlen, ref_offset(ref->node)); | ||
464 | return rc ? rc : -EIO; | ||
465 | } | ||
466 | /* obsolete node */ | ||
467 | crc = crc32(0, &rr, sizeof(rr) - 4); | ||
468 | if (crc != je32_to_cpu(rr.node_crc)) { | ||
469 | if (je32_to_cpu(rr.node_crc) != 0xffffffff) | ||
470 | JFFS2_ERROR("node CRC failed at %#08x, read=%#08x, calc=%#08x\n", | ||
471 | ref_offset(ref->node), je32_to_cpu(rr.node_crc), crc); | ||
472 | return EIO; | ||
473 | } | ||
474 | if (je16_to_cpu(rr.magic) != JFFS2_MAGIC_BITMASK | ||
475 | || je16_to_cpu(rr.nodetype) != JFFS2_NODETYPE_XREF | ||
476 | || je32_to_cpu(rr.totlen) != PAD(sizeof(rr))) { | ||
477 | JFFS2_ERROR("inconsistent xref at %#08x, magic=%#04x/%#04x, " | ||
478 | "nodetype=%#04x/%#04x, totlen=%u/%zu\n", | ||
479 | ref_offset(ref->node), je16_to_cpu(rr.magic), JFFS2_MAGIC_BITMASK, | ||
480 | je16_to_cpu(rr.nodetype), JFFS2_NODETYPE_XREF, | ||
481 | je32_to_cpu(rr.totlen), PAD(sizeof(rr))); | ||
482 | return EIO; | ||
483 | } | ||
484 | ref->ino = je32_to_cpu(rr.ino); | ||
485 | ref->xid = je32_to_cpu(rr.xid); | ||
486 | |||
487 | /* fixup superblock/eraseblock info */ | ||
488 | jeb = &c->blocks[ref_offset(ref->node) / c->sector_size]; | ||
489 | totlen = PAD(sizeof(rr)); | ||
490 | |||
491 | spin_lock(&c->erase_completion_lock); | ||
492 | c->unchecked_size -= totlen; c->used_size += totlen; | ||
493 | jeb->unchecked_size -= totlen; jeb->used_size += totlen; | ||
494 | ref->node->flash_offset = ref_offset(ref->node) | REF_PRISTINE; | ||
495 | spin_unlock(&c->erase_completion_lock); | ||
496 | |||
497 | dbg_xattr("success on verifying xref (ino=%u, xid=%u) at %#08x\n", | ||
498 | ref->ino, ref->xid, ref_offset(ref->node)); | ||
499 | return 0; | ||
500 | } | ||
501 | |||
502 | static void delete_xattr_ref_node(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | ||
503 | { | ||
504 | struct jffs2_raw_xref rr; | ||
505 | size_t length; | ||
506 | int rc; | ||
507 | |||
508 | if (jffs2_sum_active()) { | ||
509 | memset(&rr, 0xff, sizeof(rr)); | ||
510 | rc = jffs2_flash_read(c, ref_offset(ref->node), | ||
511 | sizeof(struct jffs2_unknown_node), | ||
512 | &length, (char *)&rr); | ||
513 | if (rc || length != sizeof(struct jffs2_unknown_node)) { | ||
514 | JFFS2_ERROR("jffs2_flash_read()=%d, req=%zu, read=%zu at %#08x\n", | ||
515 | rc, sizeof(struct jffs2_unknown_node), | ||
516 | length, ref_offset(ref->node)); | ||
517 | } | ||
518 | rc = jffs2_flash_write(c, ref_offset(ref->node), sizeof(rr), | ||
519 | &length, (char *)&rr); | ||
520 | if (rc || length != sizeof(struct jffs2_raw_xref)) { | ||
521 | JFFS2_ERROR("jffs2_flash_write()=%d, req=%zu, wrote=%zu at %#08x\n", | ||
522 | rc, sizeof(rr), length, ref_offset(ref->node)); | ||
523 | } | ||
524 | } | ||
525 | spin_lock(&c->erase_completion_lock); | ||
526 | ref->node->next_in_ino = NULL; | ||
527 | spin_unlock(&c->erase_completion_lock); | ||
528 | jffs2_mark_node_obsolete(c, ref->node); | ||
529 | ref->node = NULL; | ||
530 | } | ||
531 | |||
532 | static void delete_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | ||
533 | { | ||
534 | /* must be called under down_write(xattr_sem) */ | ||
535 | struct jffs2_xattr_datum *xd; | ||
536 | |||
537 | BUG_ON(!ref->node); | ||
538 | delete_xattr_ref_node(c, ref); | ||
539 | |||
540 | xd = ref->xd; | ||
541 | xd->refcnt--; | ||
542 | if (!xd->refcnt) | ||
543 | delete_xattr_datum(c, xd); | ||
544 | jffs2_free_xattr_ref(ref); | ||
545 | } | ||
546 | |||
547 | static int save_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | ||
548 | { | ||
549 | /* must be called under down_write(xattr_sem) */ | ||
550 | struct jffs2_raw_node_ref *raw; | ||
551 | struct jffs2_raw_xref rr; | ||
552 | size_t length; | ||
553 | uint32_t phys_ofs = write_ofs(c); | ||
554 | int ret; | ||
555 | |||
556 | rr.magic = cpu_to_je16(JFFS2_MAGIC_BITMASK); | ||
557 | rr.nodetype = cpu_to_je16(JFFS2_NODETYPE_XREF); | ||
558 | rr.totlen = cpu_to_je32(PAD(sizeof(rr))); | ||
559 | rr.hdr_crc = cpu_to_je32(crc32(0, &rr, sizeof(struct jffs2_unknown_node) - 4)); | ||
560 | |||
561 | rr.ino = cpu_to_je32(ref->ic->ino); | ||
562 | rr.xid = cpu_to_je32(ref->xd->xid); | ||
563 | rr.node_crc = cpu_to_je32(crc32(0, &rr, sizeof(rr) - 4)); | ||
564 | |||
565 | ret = jffs2_flash_write(c, phys_ofs, sizeof(rr), &length, (char *)&rr); | ||
566 | if (ret || sizeof(rr) != length) { | ||
567 | JFFS2_WARNING("jffs2_flash_write() returned %d, request=%zu, retlen=%zu, at %#08x\n", | ||
568 | ret, sizeof(rr), length, phys_ofs); | ||
569 | ret = ret ? ret : -EIO; | ||
570 | if (length) | ||
571 | jffs2_add_physical_node_ref(c, phys_ofs | REF_OBSOLETE, PAD(sizeof(rr)), NULL); | ||
572 | |||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | raw = jffs2_add_physical_node_ref(c, phys_ofs | REF_PRISTINE, PAD(sizeof(rr)), NULL); | ||
577 | /* FIXME */ raw->next_in_ino = (void *)ref; | ||
578 | if (ref->node) | ||
579 | delete_xattr_ref_node(c, ref); | ||
580 | ref->node = raw; | ||
581 | |||
582 | dbg_xattr("success on saving xref (ino=%u, xid=%u)\n", ref->ic->ino, ref->xd->xid); | ||
583 | |||
584 | return 0; | ||
585 | } | ||
586 | |||
587 | static struct jffs2_xattr_ref *create_xattr_ref(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic, | ||
588 | struct jffs2_xattr_datum *xd) | ||
589 | { | ||
590 | /* must be called under down_write(xattr_sem) */ | ||
591 | struct jffs2_xattr_ref *ref; | ||
592 | int ret; | ||
593 | |||
594 | ref = jffs2_alloc_xattr_ref(); | ||
595 | if (!ref) | ||
596 | return ERR_PTR(-ENOMEM); | ||
597 | ref->ic = ic; | ||
598 | ref->xd = xd; | ||
599 | |||
600 | ret = save_xattr_ref(c, ref); | ||
601 | if (ret) { | ||
602 | jffs2_free_xattr_ref(ref); | ||
603 | return ERR_PTR(ret); | ||
604 | } | ||
605 | |||
606 | /* Chain to inode */ | ||
607 | ref->next = ic->xref; | ||
608 | ic->xref = ref; | ||
609 | |||
610 | return ref; /* success */ | ||
611 | } | ||
612 | |||
613 | void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) | ||
614 | { | ||
615 | /* It's called from jffs2_clear_inode() on inode removing. | ||
616 | When an inode with XATTR is removed, those XATTRs must be removed. */ | ||
617 | struct jffs2_xattr_ref *ref, *_ref; | ||
618 | |||
619 | if (!ic || ic->nlink > 0) | ||
620 | return; | ||
621 | |||
622 | down_write(&c->xattr_sem); | ||
623 | for (ref = ic->xref; ref; ref = _ref) { | ||
624 | _ref = ref->next; | ||
625 | delete_xattr_ref(c, ref); | ||
626 | } | ||
627 | ic->xref = NULL; | ||
628 | up_write(&c->xattr_sem); | ||
629 | } | ||
630 | |||
631 | void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) | ||
632 | { | ||
633 | /* It's called from jffs2_free_ino_caches() until unmounting FS. */ | ||
634 | struct jffs2_xattr_datum *xd; | ||
635 | struct jffs2_xattr_ref *ref, *_ref; | ||
636 | |||
637 | down_write(&c->xattr_sem); | ||
638 | for (ref = ic->xref; ref; ref = _ref) { | ||
639 | _ref = ref->next; | ||
640 | xd = ref->xd; | ||
641 | xd->refcnt--; | ||
642 | if (!xd->refcnt) { | ||
643 | unload_xattr_datum(c, xd); | ||
644 | jffs2_free_xattr_datum(xd); | ||
645 | } | ||
646 | jffs2_free_xattr_ref(ref); | ||
647 | } | ||
648 | ic->xref = NULL; | ||
649 | up_write(&c->xattr_sem); | ||
650 | } | ||
651 | |||
652 | static int check_xattr_ref_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic) | ||
653 | { | ||
654 | /* success of check_xattr_ref_inode() means taht inode (ic) dose not have | ||
655 | * duplicate name/value pairs. If duplicate name/value pair would be found, | ||
656 | * one will be removed. | ||
657 | */ | ||
658 | struct jffs2_xattr_ref *ref, *cmp, **pref; | ||
659 | int rc = 0; | ||
660 | |||
661 | if (likely(ic->flags & INO_FLAGS_XATTR_CHECKED)) | ||
662 | return 0; | ||
663 | down_write(&c->xattr_sem); | ||
664 | retry: | ||
665 | rc = 0; | ||
666 | for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { | ||
667 | if (!ref->xd->xname) { | ||
668 | rc = load_xattr_datum(c, ref->xd); | ||
669 | if (unlikely(rc > 0)) { | ||
670 | *pref = ref->next; | ||
671 | delete_xattr_ref(c, ref); | ||
672 | goto retry; | ||
673 | } else if (unlikely(rc < 0)) | ||
674 | goto out; | ||
675 | } | ||
676 | for (cmp=ref->next, pref=&ref->next; cmp; pref=&cmp->next, cmp=cmp->next) { | ||
677 | if (!cmp->xd->xname) { | ||
678 | ref->xd->flags |= JFFS2_XFLAGS_BIND; | ||
679 | rc = load_xattr_datum(c, cmp->xd); | ||
680 | ref->xd->flags &= ~JFFS2_XFLAGS_BIND; | ||
681 | if (unlikely(rc > 0)) { | ||
682 | *pref = cmp->next; | ||
683 | delete_xattr_ref(c, cmp); | ||
684 | goto retry; | ||
685 | } else if (unlikely(rc < 0)) | ||
686 | goto out; | ||
687 | } | ||
688 | if (ref->xd->xprefix == cmp->xd->xprefix | ||
689 | && !strcmp(ref->xd->xname, cmp->xd->xname)) { | ||
690 | *pref = cmp->next; | ||
691 | delete_xattr_ref(c, cmp); | ||
692 | goto retry; | ||
693 | } | ||
694 | } | ||
695 | } | ||
696 | ic->flags |= INO_FLAGS_XATTR_CHECKED; | ||
697 | out: | ||
698 | up_write(&c->xattr_sem); | ||
699 | |||
700 | return rc; | ||
701 | } | ||
702 | |||
703 | /* -------- xattr subsystem functions --------------- | ||
704 | * jffs2_init_xattr_subsystem(c) | ||
705 | * is used to initialize semaphore and list_head, and some variables. | ||
706 | * jffs2_find_xattr_datum(c, xid) | ||
707 | * is used to lookup xdatum while scanning process. | ||
708 | * jffs2_clear_xattr_subsystem(c) | ||
709 | * is used to release any xattr related objects. | ||
710 | * jffs2_build_xattr_subsystem(c) | ||
711 | * is used to associate xdatum and xref while super block building process. | ||
712 | * jffs2_setup_xattr_datum(c, xid, version) | ||
713 | * is used to insert xdatum while scanning process. | ||
714 | * -------------------------------------------------- */ | ||
715 | void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c) | ||
716 | { | ||
717 | int i; | ||
718 | |||
719 | for (i=0; i < XATTRINDEX_HASHSIZE; i++) | ||
720 | INIT_LIST_HEAD(&c->xattrindex[i]); | ||
721 | INIT_LIST_HEAD(&c->xattr_unchecked); | ||
722 | c->xref_temp = NULL; | ||
723 | |||
724 | init_rwsem(&c->xattr_sem); | ||
725 | c->xdatum_mem_usage = 0; | ||
726 | c->xdatum_mem_threshold = 32 * 1024; /* Default 32KB */ | ||
727 | } | ||
728 | |||
729 | static struct jffs2_xattr_datum *jffs2_find_xattr_datum(struct jffs2_sb_info *c, uint32_t xid) | ||
730 | { | ||
731 | struct jffs2_xattr_datum *xd; | ||
732 | int i = xid % XATTRINDEX_HASHSIZE; | ||
733 | |||
734 | /* It's only used in scanning/building process. */ | ||
735 | BUG_ON(!(c->flags & (JFFS2_SB_FLAG_SCANNING|JFFS2_SB_FLAG_BUILDING))); | ||
736 | |||
737 | list_for_each_entry(xd, &c->xattrindex[i], xindex) { | ||
738 | if (xd->xid==xid) | ||
739 | return xd; | ||
740 | } | ||
741 | return NULL; | ||
742 | } | ||
743 | |||
744 | void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c) | ||
745 | { | ||
746 | struct jffs2_xattr_datum *xd, *_xd; | ||
747 | struct jffs2_xattr_ref *ref, *_ref; | ||
748 | int i; | ||
749 | |||
750 | for (ref=c->xref_temp; ref; ref = _ref) { | ||
751 | _ref = ref->next; | ||
752 | jffs2_free_xattr_ref(ref); | ||
753 | } | ||
754 | c->xref_temp = NULL; | ||
755 | |||
756 | for (i=0; i < XATTRINDEX_HASHSIZE; i++) { | ||
757 | list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { | ||
758 | list_del(&xd->xindex); | ||
759 | if (xd->xname) | ||
760 | kfree(xd->xname); | ||
761 | jffs2_free_xattr_datum(xd); | ||
762 | } | ||
763 | } | ||
764 | } | ||
765 | |||
766 | void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c) | ||
767 | { | ||
768 | struct jffs2_xattr_ref *ref, *_ref; | ||
769 | struct jffs2_xattr_datum *xd, *_xd; | ||
770 | struct jffs2_inode_cache *ic; | ||
771 | int i, xdatum_count =0, xdatum_unchecked_count = 0, xref_count = 0; | ||
772 | |||
773 | BUG_ON(!(c->flags & JFFS2_SB_FLAG_BUILDING)); | ||
774 | |||
775 | /* Phase.1 */ | ||
776 | for (ref=c->xref_temp; ref; ref=_ref) { | ||
777 | _ref = ref->next; | ||
778 | /* checking REF_UNCHECKED nodes */ | ||
779 | if (ref_flags(ref->node) != REF_PRISTINE) { | ||
780 | if (verify_xattr_ref(c, ref)) { | ||
781 | delete_xattr_ref_node(c, ref); | ||
782 | jffs2_free_xattr_ref(ref); | ||
783 | continue; | ||
784 | } | ||
785 | } | ||
786 | /* At this point, ref->xid and ref->ino contain XID and inode number. | ||
787 | ref->xd and ref->ic are not valid yet. */ | ||
788 | xd = jffs2_find_xattr_datum(c, ref->xid); | ||
789 | ic = jffs2_get_ino_cache(c, ref->ino); | ||
790 | if (!xd || !ic) { | ||
791 | if (ref_flags(ref->node) != REF_UNCHECKED) | ||
792 | JFFS2_WARNING("xref(ino=%u, xid=%u) is orphan. \n", | ||
793 | ref->ino, ref->xid); | ||
794 | delete_xattr_ref_node(c, ref); | ||
795 | jffs2_free_xattr_ref(ref); | ||
796 | continue; | ||
797 | } | ||
798 | ref->xd = xd; | ||
799 | ref->ic = ic; | ||
800 | xd->refcnt++; | ||
801 | ref->next = ic->xref; | ||
802 | ic->xref = ref; | ||
803 | xref_count++; | ||
804 | } | ||
805 | c->xref_temp = NULL; | ||
806 | /* After this, ref->xid/ino are NEVER used. */ | ||
807 | |||
808 | /* Phase.2 */ | ||
809 | for (i=0; i < XATTRINDEX_HASHSIZE; i++) { | ||
810 | list_for_each_entry_safe(xd, _xd, &c->xattrindex[i], xindex) { | ||
811 | list_del_init(&xd->xindex); | ||
812 | if (!xd->refcnt) { | ||
813 | if (ref_flags(xd->node) != REF_UNCHECKED) | ||
814 | JFFS2_WARNING("orphan xdatum(xid=%u, version=%u) at %#08x\n", | ||
815 | xd->xid, xd->version, ref_offset(xd->node)); | ||
816 | delete_xattr_datum(c, xd); | ||
817 | continue; | ||
818 | } | ||
819 | if (ref_flags(xd->node) != REF_PRISTINE) { | ||
820 | dbg_xattr("unchecked xdatum(xid=%u) at %#08x\n", | ||
821 | xd->xid, ref_offset(xd->node)); | ||
822 | list_add(&xd->xindex, &c->xattr_unchecked); | ||
823 | xdatum_unchecked_count++; | ||
824 | } | ||
825 | xdatum_count++; | ||
826 | } | ||
827 | } | ||
828 | /* build complete */ | ||
829 | JFFS2_NOTICE("complete building xattr subsystem, %u of xdatum (%u unchecked) and " | ||
830 | "%u of xref found.\n", xdatum_count, xdatum_unchecked_count, xref_count); | ||
831 | } | ||
832 | |||
833 | struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, | ||
834 | uint32_t xid, uint32_t version) | ||
835 | { | ||
836 | struct jffs2_xattr_datum *xd, *_xd; | ||
837 | |||
838 | _xd = jffs2_find_xattr_datum(c, xid); | ||
839 | if (_xd) { | ||
840 | dbg_xattr("duplicate xdatum (xid=%u, version=%u/%u) at %#08x\n", | ||
841 | xid, version, _xd->version, ref_offset(_xd->node)); | ||
842 | if (version < _xd->version) | ||
843 | return ERR_PTR(-EEXIST); | ||
844 | } | ||
845 | xd = jffs2_alloc_xattr_datum(); | ||
846 | if (!xd) | ||
847 | return ERR_PTR(-ENOMEM); | ||
848 | xd->xid = xid; | ||
849 | xd->version = version; | ||
850 | if (xd->xid > c->highest_xid) | ||
851 | c->highest_xid = xd->xid; | ||
852 | list_add_tail(&xd->xindex, &c->xattrindex[xid % XATTRINDEX_HASHSIZE]); | ||
853 | |||
854 | if (_xd) { | ||
855 | list_del_init(&_xd->xindex); | ||
856 | delete_xattr_datum_node(c, _xd); | ||
857 | jffs2_free_xattr_datum(_xd); | ||
858 | } | ||
859 | return xd; | ||
860 | } | ||
861 | |||
862 | /* -------- xattr subsystem functions --------------- | ||
863 | * xprefix_to_handler(xprefix) | ||
864 | * is used to translate xprefix into xattr_handler. | ||
865 | * jffs2_listxattr(dentry, buffer, size) | ||
866 | * is an implementation of listxattr handler on jffs2. | ||
867 | * do_jffs2_getxattr(inode, xprefix, xname, buffer, size) | ||
868 | * is an implementation of getxattr handler on jffs2. | ||
869 | * do_jffs2_setxattr(inode, xprefix, xname, buffer, size, flags) | ||
870 | * is an implementation of setxattr handler on jffs2. | ||
871 | * -------------------------------------------------- */ | ||
872 | struct xattr_handler *jffs2_xattr_handlers[] = { | ||
873 | &jffs2_user_xattr_handler, | ||
874 | #ifdef CONFIG_JFFS2_FS_SECURITY | ||
875 | &jffs2_security_xattr_handler, | ||
876 | #endif | ||
877 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
878 | &jffs2_acl_access_xattr_handler, | ||
879 | &jffs2_acl_default_xattr_handler, | ||
880 | #endif | ||
881 | &jffs2_trusted_xattr_handler, | ||
882 | NULL | ||
883 | }; | ||
884 | |||
885 | static struct xattr_handler *xprefix_to_handler(int xprefix) { | ||
886 | struct xattr_handler *ret; | ||
887 | |||
888 | switch (xprefix) { | ||
889 | case JFFS2_XPREFIX_USER: | ||
890 | ret = &jffs2_user_xattr_handler; | ||
891 | break; | ||
892 | #ifdef CONFIG_JFFS2_FS_SECURITY | ||
893 | case JFFS2_XPREFIX_SECURITY: | ||
894 | ret = &jffs2_security_xattr_handler; | ||
895 | break; | ||
896 | #endif | ||
897 | #ifdef CONFIG_JFFS2_FS_POSIX_ACL | ||
898 | case JFFS2_XPREFIX_ACL_ACCESS: | ||
899 | ret = &jffs2_acl_access_xattr_handler; | ||
900 | break; | ||
901 | case JFFS2_XPREFIX_ACL_DEFAULT: | ||
902 | ret = &jffs2_acl_default_xattr_handler; | ||
903 | break; | ||
904 | #endif | ||
905 | case JFFS2_XPREFIX_TRUSTED: | ||
906 | ret = &jffs2_trusted_xattr_handler; | ||
907 | break; | ||
908 | default: | ||
909 | ret = NULL; | ||
910 | break; | ||
911 | } | ||
912 | return ret; | ||
913 | } | ||
914 | |||
915 | ssize_t jffs2_listxattr(struct dentry *dentry, char *buffer, size_t size) | ||
916 | { | ||
917 | struct inode *inode = dentry->d_inode; | ||
918 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
919 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); | ||
920 | struct jffs2_inode_cache *ic = f->inocache; | ||
921 | struct jffs2_xattr_ref *ref, **pref; | ||
922 | struct jffs2_xattr_datum *xd; | ||
923 | struct xattr_handler *xhandle; | ||
924 | ssize_t len, rc; | ||
925 | int retry = 0; | ||
926 | |||
927 | rc = check_xattr_ref_inode(c, ic); | ||
928 | if (unlikely(rc)) | ||
929 | return rc; | ||
930 | |||
931 | down_read(&c->xattr_sem); | ||
932 | retry: | ||
933 | len = 0; | ||
934 | for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { | ||
935 | BUG_ON(ref->ic != ic); | ||
936 | xd = ref->xd; | ||
937 | if (!xd->xname) { | ||
938 | /* xdatum is unchached */ | ||
939 | if (!retry) { | ||
940 | retry = 1; | ||
941 | up_read(&c->xattr_sem); | ||
942 | down_write(&c->xattr_sem); | ||
943 | goto retry; | ||
944 | } else { | ||
945 | rc = load_xattr_datum(c, xd); | ||
946 | if (unlikely(rc > 0)) { | ||
947 | *pref = ref->next; | ||
948 | delete_xattr_ref(c, ref); | ||
949 | goto retry; | ||
950 | } else if (unlikely(rc < 0)) | ||
951 | goto out; | ||
952 | } | ||
953 | } | ||
954 | xhandle = xprefix_to_handler(xd->xprefix); | ||
955 | if (!xhandle) | ||
956 | continue; | ||
957 | if (buffer) { | ||
958 | rc = xhandle->list(inode, buffer+len, size-len, xd->xname, xd->name_len); | ||
959 | } else { | ||
960 | rc = xhandle->list(inode, NULL, 0, xd->xname, xd->name_len); | ||
961 | } | ||
962 | if (rc < 0) | ||
963 | goto out; | ||
964 | len += rc; | ||
965 | } | ||
966 | rc = len; | ||
967 | out: | ||
968 | if (!retry) { | ||
969 | up_read(&c->xattr_sem); | ||
970 | } else { | ||
971 | up_write(&c->xattr_sem); | ||
972 | } | ||
973 | return rc; | ||
974 | } | ||
975 | |||
976 | int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, | ||
977 | char *buffer, size_t size) | ||
978 | { | ||
979 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
980 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); | ||
981 | struct jffs2_inode_cache *ic = f->inocache; | ||
982 | struct jffs2_xattr_datum *xd; | ||
983 | struct jffs2_xattr_ref *ref, **pref; | ||
984 | int rc, retry = 0; | ||
985 | |||
986 | rc = check_xattr_ref_inode(c, ic); | ||
987 | if (unlikely(rc)) | ||
988 | return rc; | ||
989 | |||
990 | down_read(&c->xattr_sem); | ||
991 | retry: | ||
992 | for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { | ||
993 | BUG_ON(ref->ic!=ic); | ||
994 | |||
995 | xd = ref->xd; | ||
996 | if (xd->xprefix != xprefix) | ||
997 | continue; | ||
998 | if (!xd->xname) { | ||
999 | /* xdatum is unchached */ | ||
1000 | if (!retry) { | ||
1001 | retry = 1; | ||
1002 | up_read(&c->xattr_sem); | ||
1003 | down_write(&c->xattr_sem); | ||
1004 | goto retry; | ||
1005 | } else { | ||
1006 | rc = load_xattr_datum(c, xd); | ||
1007 | if (unlikely(rc > 0)) { | ||
1008 | *pref = ref->next; | ||
1009 | delete_xattr_ref(c, ref); | ||
1010 | goto retry; | ||
1011 | } else if (unlikely(rc < 0)) { | ||
1012 | goto out; | ||
1013 | } | ||
1014 | } | ||
1015 | } | ||
1016 | if (!strcmp(xname, xd->xname)) { | ||
1017 | rc = xd->value_len; | ||
1018 | if (buffer) { | ||
1019 | if (size < rc) { | ||
1020 | rc = -ERANGE; | ||
1021 | } else { | ||
1022 | memcpy(buffer, xd->xvalue, rc); | ||
1023 | } | ||
1024 | } | ||
1025 | goto out; | ||
1026 | } | ||
1027 | } | ||
1028 | rc = -ENODATA; | ||
1029 | out: | ||
1030 | if (!retry) { | ||
1031 | up_read(&c->xattr_sem); | ||
1032 | } else { | ||
1033 | up_write(&c->xattr_sem); | ||
1034 | } | ||
1035 | return rc; | ||
1036 | } | ||
1037 | |||
1038 | int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, | ||
1039 | const char *buffer, size_t size, int flags) | ||
1040 | { | ||
1041 | struct jffs2_inode_info *f = JFFS2_INODE_INFO(inode); | ||
1042 | struct jffs2_sb_info *c = JFFS2_SB_INFO(inode->i_sb); | ||
1043 | struct jffs2_inode_cache *ic = f->inocache; | ||
1044 | struct jffs2_xattr_datum *xd; | ||
1045 | struct jffs2_xattr_ref *ref, *newref, **pref; | ||
1046 | uint32_t length, request; | ||
1047 | int rc; | ||
1048 | |||
1049 | rc = check_xattr_ref_inode(c, ic); | ||
1050 | if (unlikely(rc)) | ||
1051 | return rc; | ||
1052 | |||
1053 | request = PAD(sizeof(struct jffs2_raw_xattr) + strlen(xname) + 1 + size); | ||
1054 | rc = jffs2_reserve_space(c, request, &length, | ||
1055 | ALLOC_NORMAL, JFFS2_SUMMARY_XATTR_SIZE); | ||
1056 | if (rc) { | ||
1057 | JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); | ||
1058 | return rc; | ||
1059 | } | ||
1060 | |||
1061 | /* Find existing xattr */ | ||
1062 | down_write(&c->xattr_sem); | ||
1063 | retry: | ||
1064 | for (ref=ic->xref, pref=&ic->xref; ref; pref=&ref->next, ref=ref->next) { | ||
1065 | xd = ref->xd; | ||
1066 | if (xd->xprefix != xprefix) | ||
1067 | continue; | ||
1068 | if (!xd->xname) { | ||
1069 | rc = load_xattr_datum(c, xd); | ||
1070 | if (unlikely(rc > 0)) { | ||
1071 | *pref = ref->next; | ||
1072 | delete_xattr_ref(c, ref); | ||
1073 | goto retry; | ||
1074 | } else if (unlikely(rc < 0)) | ||
1075 | goto out; | ||
1076 | } | ||
1077 | if (!strcmp(xd->xname, xname)) { | ||
1078 | if (flags & XATTR_CREATE) { | ||
1079 | rc = -EEXIST; | ||
1080 | goto out; | ||
1081 | } | ||
1082 | if (!buffer) { | ||
1083 | *pref = ref->next; | ||
1084 | delete_xattr_ref(c, ref); | ||
1085 | rc = 0; | ||
1086 | goto out; | ||
1087 | } | ||
1088 | goto found; | ||
1089 | } | ||
1090 | } | ||
1091 | /* not found */ | ||
1092 | if (flags & XATTR_REPLACE) { | ||
1093 | rc = -ENODATA; | ||
1094 | goto out; | ||
1095 | } | ||
1096 | if (!buffer) { | ||
1097 | rc = -EINVAL; | ||
1098 | goto out; | ||
1099 | } | ||
1100 | found: | ||
1101 | xd = create_xattr_datum(c, xprefix, xname, buffer, size); | ||
1102 | if (IS_ERR(xd)) { | ||
1103 | rc = PTR_ERR(xd); | ||
1104 | goto out; | ||
1105 | } | ||
1106 | up_write(&c->xattr_sem); | ||
1107 | jffs2_complete_reservation(c); | ||
1108 | |||
1109 | /* create xattr_ref */ | ||
1110 | request = PAD(sizeof(struct jffs2_raw_xref)); | ||
1111 | rc = jffs2_reserve_space(c, request, &length, | ||
1112 | ALLOC_NORMAL, JFFS2_SUMMARY_XREF_SIZE); | ||
1113 | if (rc) { | ||
1114 | JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, request); | ||
1115 | down_write(&c->xattr_sem); | ||
1116 | xd->refcnt--; | ||
1117 | if (!xd->refcnt) | ||
1118 | delete_xattr_datum(c, xd); | ||
1119 | up_write(&c->xattr_sem); | ||
1120 | return rc; | ||
1121 | } | ||
1122 | down_write(&c->xattr_sem); | ||
1123 | if (ref) | ||
1124 | *pref = ref->next; | ||
1125 | newref = create_xattr_ref(c, ic, xd); | ||
1126 | if (IS_ERR(newref)) { | ||
1127 | if (ref) { | ||
1128 | ref->next = ic->xref; | ||
1129 | ic->xref = ref; | ||
1130 | } | ||
1131 | rc = PTR_ERR(newref); | ||
1132 | xd->refcnt--; | ||
1133 | if (!xd->refcnt) | ||
1134 | delete_xattr_datum(c, xd); | ||
1135 | } else if (ref) { | ||
1136 | delete_xattr_ref(c, ref); | ||
1137 | } | ||
1138 | out: | ||
1139 | up_write(&c->xattr_sem); | ||
1140 | jffs2_complete_reservation(c); | ||
1141 | return rc; | ||
1142 | } | ||
1143 | |||
1144 | /* -------- garbage collector functions ------------- | ||
1145 | * jffs2_garbage_collect_xattr_datum(c, xd) | ||
1146 | * is used to move xdatum into new node. | ||
1147 | * jffs2_garbage_collect_xattr_ref(c, ref) | ||
1148 | * is used to move xref into new node. | ||
1149 | * jffs2_verify_xattr(c) | ||
1150 | * is used to call do_verify_xattr_datum() before garbage collecting. | ||
1151 | * -------------------------------------------------- */ | ||
1152 | int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd) | ||
1153 | { | ||
1154 | uint32_t totlen, length, old_ofs; | ||
1155 | int rc = -EINVAL; | ||
1156 | |||
1157 | down_write(&c->xattr_sem); | ||
1158 | BUG_ON(!xd->node); | ||
1159 | |||
1160 | old_ofs = ref_offset(xd->node); | ||
1161 | totlen = ref_totlen(c, c->gcblock, xd->node); | ||
1162 | if (totlen < sizeof(struct jffs2_raw_xattr)) | ||
1163 | goto out; | ||
1164 | |||
1165 | if (!xd->xname) { | ||
1166 | rc = load_xattr_datum(c, xd); | ||
1167 | if (unlikely(rc > 0)) { | ||
1168 | delete_xattr_datum_node(c, xd); | ||
1169 | rc = 0; | ||
1170 | goto out; | ||
1171 | } else if (unlikely(rc < 0)) | ||
1172 | goto out; | ||
1173 | } | ||
1174 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XATTR_SIZE); | ||
1175 | if (rc || length < totlen) { | ||
1176 | JFFS2_WARNING("jffs2_reserve_space()=%d, request=%u\n", rc, totlen); | ||
1177 | rc = rc ? rc : -EBADFD; | ||
1178 | goto out; | ||
1179 | } | ||
1180 | rc = save_xattr_datum(c, xd); | ||
1181 | if (!rc) | ||
1182 | dbg_xattr("xdatum (xid=%u, version=%u) GC'ed from %#08x to %08x\n", | ||
1183 | xd->xid, xd->version, old_ofs, ref_offset(xd->node)); | ||
1184 | out: | ||
1185 | up_write(&c->xattr_sem); | ||
1186 | return rc; | ||
1187 | } | ||
1188 | |||
1189 | |||
1190 | int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref) | ||
1191 | { | ||
1192 | uint32_t totlen, length, old_ofs; | ||
1193 | int rc = -EINVAL; | ||
1194 | |||
1195 | down_write(&c->xattr_sem); | ||
1196 | BUG_ON(!ref->node); | ||
1197 | |||
1198 | old_ofs = ref_offset(ref->node); | ||
1199 | totlen = ref_totlen(c, c->gcblock, ref->node); | ||
1200 | if (totlen != sizeof(struct jffs2_raw_xref)) | ||
1201 | goto out; | ||
1202 | |||
1203 | rc = jffs2_reserve_space_gc(c, totlen, &length, JFFS2_SUMMARY_XREF_SIZE); | ||
1204 | if (rc || length < totlen) { | ||
1205 | JFFS2_WARNING("%s: jffs2_reserve_space() = %d, request = %u\n", | ||
1206 | __FUNCTION__, rc, totlen); | ||
1207 | rc = rc ? rc : -EBADFD; | ||
1208 | goto out; | ||
1209 | } | ||
1210 | rc = save_xattr_ref(c, ref); | ||
1211 | if (!rc) | ||
1212 | dbg_xattr("xref (ino=%u, xid=%u) GC'ed from %#08x to %08x\n", | ||
1213 | ref->ic->ino, ref->xd->xid, old_ofs, ref_offset(ref->node)); | ||
1214 | out: | ||
1215 | up_write(&c->xattr_sem); | ||
1216 | return rc; | ||
1217 | } | ||
1218 | |||
1219 | int jffs2_verify_xattr(struct jffs2_sb_info *c) | ||
1220 | { | ||
1221 | struct jffs2_xattr_datum *xd, *_xd; | ||
1222 | int rc; | ||
1223 | |||
1224 | down_write(&c->xattr_sem); | ||
1225 | list_for_each_entry_safe(xd, _xd, &c->xattr_unchecked, xindex) { | ||
1226 | rc = do_verify_xattr_datum(c, xd); | ||
1227 | if (rc == 0) { | ||
1228 | list_del_init(&xd->xindex); | ||
1229 | break; | ||
1230 | } else if (rc > 0) { | ||
1231 | list_del_init(&xd->xindex); | ||
1232 | delete_xattr_datum_node(c, xd); | ||
1233 | } | ||
1234 | } | ||
1235 | up_write(&c->xattr_sem); | ||
1236 | |||
1237 | return list_empty(&c->xattr_unchecked) ? 1 : 0; | ||
1238 | } | ||
diff --git a/fs/jffs2/xattr.h b/fs/jffs2/xattr.h new file mode 100644 index 000000000000..2c199856c582 --- /dev/null +++ b/fs/jffs2/xattr.h | |||
@@ -0,0 +1,116 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #ifndef _JFFS2_FS_XATTR_H_ | ||
12 | #define _JFFS2_FS_XATTR_H_ | ||
13 | |||
14 | #include <linux/xattr.h> | ||
15 | #include <linux/list.h> | ||
16 | |||
17 | #define JFFS2_XFLAGS_HOT (0x01) /* This datum is HOT */ | ||
18 | #define JFFS2_XFLAGS_BIND (0x02) /* This datum is not reclaimed */ | ||
19 | |||
20 | struct jffs2_xattr_datum | ||
21 | { | ||
22 | void *always_null; | ||
23 | struct jffs2_raw_node_ref *node; | ||
24 | uint8_t class; | ||
25 | uint8_t flags; | ||
26 | uint16_t xprefix; /* see JFFS2_XATTR_PREFIX_* */ | ||
27 | |||
28 | struct list_head xindex; /* chained from c->xattrindex[n] */ | ||
29 | uint32_t refcnt; /* # of xattr_ref refers this */ | ||
30 | uint32_t xid; | ||
31 | uint32_t version; | ||
32 | |||
33 | uint32_t data_crc; | ||
34 | uint32_t hashkey; | ||
35 | char *xname; /* XATTR name without prefix */ | ||
36 | uint32_t name_len; /* length of xname */ | ||
37 | char *xvalue; /* XATTR value */ | ||
38 | uint32_t value_len; /* length of xvalue */ | ||
39 | }; | ||
40 | |||
41 | struct jffs2_inode_cache; | ||
42 | struct jffs2_xattr_ref | ||
43 | { | ||
44 | void *always_null; | ||
45 | struct jffs2_raw_node_ref *node; | ||
46 | uint8_t class; | ||
47 | uint8_t flags; /* Currently unused */ | ||
48 | u16 unused; | ||
49 | |||
50 | union { | ||
51 | struct jffs2_inode_cache *ic; /* reference to jffs2_inode_cache */ | ||
52 | uint32_t ino; /* only used in scanning/building */ | ||
53 | }; | ||
54 | union { | ||
55 | struct jffs2_xattr_datum *xd; /* reference to jffs2_xattr_datum */ | ||
56 | uint32_t xid; /* only used in sccanning/building */ | ||
57 | }; | ||
58 | struct jffs2_xattr_ref *next; /* chained from ic->xref_list */ | ||
59 | }; | ||
60 | |||
61 | #ifdef CONFIG_JFFS2_FS_XATTR | ||
62 | |||
63 | extern void jffs2_init_xattr_subsystem(struct jffs2_sb_info *c); | ||
64 | extern void jffs2_build_xattr_subsystem(struct jffs2_sb_info *c); | ||
65 | extern void jffs2_clear_xattr_subsystem(struct jffs2_sb_info *c); | ||
66 | |||
67 | extern struct jffs2_xattr_datum *jffs2_setup_xattr_datum(struct jffs2_sb_info *c, | ||
68 | uint32_t xid, uint32_t version); | ||
69 | |||
70 | extern void jffs2_xattr_delete_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); | ||
71 | extern void jffs2_xattr_free_inode(struct jffs2_sb_info *c, struct jffs2_inode_cache *ic); | ||
72 | |||
73 | extern int jffs2_garbage_collect_xattr_datum(struct jffs2_sb_info *c, struct jffs2_xattr_datum *xd); | ||
74 | extern int jffs2_garbage_collect_xattr_ref(struct jffs2_sb_info *c, struct jffs2_xattr_ref *ref); | ||
75 | extern int jffs2_verify_xattr(struct jffs2_sb_info *c); | ||
76 | |||
77 | extern int do_jffs2_getxattr(struct inode *inode, int xprefix, const char *xname, | ||
78 | char *buffer, size_t size); | ||
79 | extern int do_jffs2_setxattr(struct inode *inode, int xprefix, const char *xname, | ||
80 | const char *buffer, size_t size, int flags); | ||
81 | |||
82 | extern struct xattr_handler *jffs2_xattr_handlers[]; | ||
83 | extern struct xattr_handler jffs2_user_xattr_handler; | ||
84 | extern struct xattr_handler jffs2_trusted_xattr_handler; | ||
85 | |||
86 | extern ssize_t jffs2_listxattr(struct dentry *, char *, size_t); | ||
87 | #define jffs2_getxattr generic_getxattr | ||
88 | #define jffs2_setxattr generic_setxattr | ||
89 | #define jffs2_removexattr generic_removexattr | ||
90 | |||
91 | #else | ||
92 | |||
93 | #define jffs2_init_xattr_subsystem(c) | ||
94 | #define jffs2_build_xattr_subsystem(c) | ||
95 | #define jffs2_clear_xattr_subsystem(c) | ||
96 | |||
97 | #define jffs2_xattr_delete_inode(c, ic) | ||
98 | #define jffs2_xattr_free_inode(c, ic) | ||
99 | #define jffs2_verify_xattr(c) (1) | ||
100 | |||
101 | #define jffs2_xattr_handlers NULL | ||
102 | #define jffs2_listxattr NULL | ||
103 | #define jffs2_getxattr NULL | ||
104 | #define jffs2_setxattr NULL | ||
105 | #define jffs2_removexattr NULL | ||
106 | |||
107 | #endif /* CONFIG_JFFS2_FS_XATTR */ | ||
108 | |||
109 | #ifdef CONFIG_JFFS2_FS_SECURITY | ||
110 | extern int jffs2_init_security(struct inode *inode, struct inode *dir); | ||
111 | extern struct xattr_handler jffs2_security_xattr_handler; | ||
112 | #else | ||
113 | #define jffs2_init_security(inode,dir) (0) | ||
114 | #endif /* CONFIG_JFFS2_FS_SECURITY */ | ||
115 | |||
116 | #endif /* _JFFS2_FS_XATTR_H_ */ | ||
diff --git a/fs/jffs2/xattr_trusted.c b/fs/jffs2/xattr_trusted.c new file mode 100644 index 000000000000..ed046e19dbfa --- /dev/null +++ b/fs/jffs2/xattr_trusted.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/jffs2.h> | ||
14 | #include <linux/xattr.h> | ||
15 | #include <linux/mtd/mtd.h> | ||
16 | #include "nodelist.h" | ||
17 | |||
18 | static int jffs2_trusted_getxattr(struct inode *inode, const char *name, | ||
19 | void *buffer, size_t size) | ||
20 | { | ||
21 | if (!strcmp(name, "")) | ||
22 | return -EINVAL; | ||
23 | return do_jffs2_getxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size); | ||
24 | } | ||
25 | |||
26 | static int jffs2_trusted_setxattr(struct inode *inode, const char *name, const void *buffer, | ||
27 | size_t size, int flags) | ||
28 | { | ||
29 | if (!strcmp(name, "")) | ||
30 | return -EINVAL; | ||
31 | return do_jffs2_setxattr(inode, JFFS2_XPREFIX_TRUSTED, name, buffer, size, flags); | ||
32 | } | ||
33 | |||
34 | static size_t jffs2_trusted_listxattr(struct inode *inode, char *list, size_t list_size, | ||
35 | const char *name, size_t name_len) | ||
36 | { | ||
37 | size_t retlen = XATTR_TRUSTED_PREFIX_LEN + name_len + 1; | ||
38 | |||
39 | if (list && retlen<=list_size) { | ||
40 | strcpy(list, XATTR_TRUSTED_PREFIX); | ||
41 | strcpy(list + XATTR_TRUSTED_PREFIX_LEN, name); | ||
42 | } | ||
43 | |||
44 | return retlen; | ||
45 | } | ||
46 | |||
47 | struct xattr_handler jffs2_trusted_xattr_handler = { | ||
48 | .prefix = XATTR_TRUSTED_PREFIX, | ||
49 | .list = jffs2_trusted_listxattr, | ||
50 | .set = jffs2_trusted_setxattr, | ||
51 | .get = jffs2_trusted_getxattr | ||
52 | }; | ||
diff --git a/fs/jffs2/xattr_user.c b/fs/jffs2/xattr_user.c new file mode 100644 index 000000000000..2f8e9aa01ea0 --- /dev/null +++ b/fs/jffs2/xattr_user.c | |||
@@ -0,0 +1,52 @@ | |||
1 | /* | ||
2 | * JFFS2 -- Journalling Flash File System, Version 2. | ||
3 | * | ||
4 | * Copyright (C) 2006 NEC Corporation | ||
5 | * | ||
6 | * Created by KaiGai Kohei <kaigai@ak.jp.nec.com> | ||
7 | * | ||
8 | * For licensing information, see the file 'LICENCE' in this directory. | ||
9 | * | ||
10 | */ | ||
11 | #include <linux/kernel.h> | ||
12 | #include <linux/fs.h> | ||
13 | #include <linux/jffs2.h> | ||
14 | #include <linux/xattr.h> | ||
15 | #include <linux/mtd/mtd.h> | ||
16 | #include "nodelist.h" | ||
17 | |||
18 | static int jffs2_user_getxattr(struct inode *inode, const char *name, | ||
19 | void *buffer, size_t size) | ||
20 | { | ||
21 | if (!strcmp(name, "")) | ||
22 | return -EINVAL; | ||
23 | return do_jffs2_getxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size); | ||
24 | } | ||
25 | |||
26 | static int jffs2_user_setxattr(struct inode *inode, const char *name, const void *buffer, | ||
27 | size_t size, int flags) | ||
28 | { | ||
29 | if (!strcmp(name, "")) | ||
30 | return -EINVAL; | ||
31 | return do_jffs2_setxattr(inode, JFFS2_XPREFIX_USER, name, buffer, size, flags); | ||
32 | } | ||
33 | |||
34 | static size_t jffs2_user_listxattr(struct inode *inode, char *list, size_t list_size, | ||
35 | const char *name, size_t name_len) | ||
36 | { | ||
37 | size_t retlen = XATTR_USER_PREFIX_LEN + name_len + 1; | ||
38 | |||
39 | if (list && retlen <= list_size) { | ||
40 | strcpy(list, XATTR_USER_PREFIX); | ||
41 | strcpy(list + XATTR_USER_PREFIX_LEN, name); | ||
42 | } | ||
43 | |||
44 | return retlen; | ||
45 | } | ||
46 | |||
47 | struct xattr_handler jffs2_user_xattr_handler = { | ||
48 | .prefix = XATTR_USER_PREFIX, | ||
49 | .list = jffs2_user_listxattr, | ||
50 | .set = jffs2_user_setxattr, | ||
51 | .get = jffs2_user_getxattr | ||
52 | }; | ||
diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 2b220dd6b4e7..7f6e88039700 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c | |||
@@ -632,10 +632,9 @@ struct metapage *__get_metapage(struct inode *inode, unsigned long lblock, | |||
632 | } | 632 | } |
633 | SetPageUptodate(page); | 633 | SetPageUptodate(page); |
634 | } else { | 634 | } else { |
635 | page = read_cache_page(mapping, page_index, | 635 | page = read_mapping_page(mapping, page_index, NULL); |
636 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
637 | if (IS_ERR(page) || !PageUptodate(page)) { | 636 | if (IS_ERR(page) || !PageUptodate(page)) { |
638 | jfs_err("read_cache_page failed!"); | 637 | jfs_err("read_mapping_page failed!"); |
639 | return NULL; | 638 | return NULL; |
640 | } | 639 | } |
641 | lock_page(page); | 640 | lock_page(page); |
diff --git a/fs/jfs/super.c b/fs/jfs/super.c index db6f41d6dd60..73d2aba084c6 100644 --- a/fs/jfs/super.c +++ b/fs/jfs/super.c | |||
@@ -139,9 +139,9 @@ static void jfs_destroy_inode(struct inode *inode) | |||
139 | kmem_cache_free(jfs_inode_cachep, ji); | 139 | kmem_cache_free(jfs_inode_cachep, ji); |
140 | } | 140 | } |
141 | 141 | ||
142 | static int jfs_statfs(struct super_block *sb, struct kstatfs *buf) | 142 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
143 | { | 143 | { |
144 | struct jfs_sb_info *sbi = JFS_SBI(sb); | 144 | struct jfs_sb_info *sbi = JFS_SBI(dentry->d_sb); |
145 | s64 maxinodes; | 145 | s64 maxinodes; |
146 | struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; | 146 | struct inomap *imap = JFS_IP(sbi->ipimap)->i_imap; |
147 | 147 | ||
@@ -565,10 +565,11 @@ static void jfs_unlockfs(struct super_block *sb) | |||
565 | } | 565 | } |
566 | } | 566 | } |
567 | 567 | ||
568 | static struct super_block *jfs_get_sb(struct file_system_type *fs_type, | 568 | static int jfs_get_sb(struct file_system_type *fs_type, |
569 | int flags, const char *dev_name, void *data) | 569 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
570 | { | 570 | { |
571 | return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super); | 571 | return get_sb_bdev(fs_type, flags, dev_name, data, jfs_fill_super, |
572 | mnt); | ||
572 | } | 573 | } |
573 | 574 | ||
574 | static int jfs_sync_fs(struct super_block *sb, int wait) | 575 | static int jfs_sync_fs(struct super_block *sb, int wait) |
diff --git a/fs/libfs.c b/fs/libfs.c index 7145ba7a48d0..1b1156381787 100644 --- a/fs/libfs.c +++ b/fs/libfs.c | |||
@@ -20,9 +20,9 @@ int simple_getattr(struct vfsmount *mnt, struct dentry *dentry, | |||
20 | return 0; | 20 | return 0; |
21 | } | 21 | } |
22 | 22 | ||
23 | int simple_statfs(struct super_block *sb, struct kstatfs *buf) | 23 | int simple_statfs(struct dentry *dentry, struct kstatfs *buf) |
24 | { | 24 | { |
25 | buf->f_type = sb->s_magic; | 25 | buf->f_type = dentry->d_sb->s_magic; |
26 | buf->f_bsize = PAGE_CACHE_SIZE; | 26 | buf->f_bsize = PAGE_CACHE_SIZE; |
27 | buf->f_namelen = NAME_MAX; | 27 | buf->f_namelen = NAME_MAX; |
28 | return 0; | 28 | return 0; |
@@ -196,9 +196,9 @@ struct inode_operations simple_dir_inode_operations = { | |||
196 | * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that | 196 | * Common helper for pseudo-filesystems (sockfs, pipefs, bdev - stuff that |
197 | * will never be mountable) | 197 | * will never be mountable) |
198 | */ | 198 | */ |
199 | struct super_block * | 199 | int get_sb_pseudo(struct file_system_type *fs_type, char *name, |
200 | get_sb_pseudo(struct file_system_type *fs_type, char *name, | 200 | struct super_operations *ops, unsigned long magic, |
201 | struct super_operations *ops, unsigned long magic) | 201 | struct vfsmount *mnt) |
202 | { | 202 | { |
203 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 203 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
204 | static struct super_operations default_ops = {.statfs = simple_statfs}; | 204 | static struct super_operations default_ops = {.statfs = simple_statfs}; |
@@ -207,7 +207,7 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, | |||
207 | struct qstr d_name = {.name = name, .len = strlen(name)}; | 207 | struct qstr d_name = {.name = name, .len = strlen(name)}; |
208 | 208 | ||
209 | if (IS_ERR(s)) | 209 | if (IS_ERR(s)) |
210 | return s; | 210 | return PTR_ERR(s); |
211 | 211 | ||
212 | s->s_flags = MS_NOUSER; | 212 | s->s_flags = MS_NOUSER; |
213 | s->s_maxbytes = ~0ULL; | 213 | s->s_maxbytes = ~0ULL; |
@@ -232,12 +232,12 @@ get_sb_pseudo(struct file_system_type *fs_type, char *name, | |||
232 | d_instantiate(dentry, root); | 232 | d_instantiate(dentry, root); |
233 | s->s_root = dentry; | 233 | s->s_root = dentry; |
234 | s->s_flags |= MS_ACTIVE; | 234 | s->s_flags |= MS_ACTIVE; |
235 | return s; | 235 | return simple_set_mnt(mnt, s); |
236 | 236 | ||
237 | Enomem: | 237 | Enomem: |
238 | up_write(&s->s_umount); | 238 | up_write(&s->s_umount); |
239 | deactivate_super(s); | 239 | deactivate_super(s); |
240 | return ERR_PTR(-ENOMEM); | 240 | return -ENOMEM; |
241 | } | 241 | } |
242 | 242 | ||
243 | int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) | 243 | int simple_link(struct dentry *old_dentry, struct inode *dir, struct dentry *dentry) |
diff --git a/fs/locks.c b/fs/locks.c index ab61a8b54829..1ad29c9b6252 100644 --- a/fs/locks.c +++ b/fs/locks.c | |||
@@ -703,7 +703,7 @@ EXPORT_SYMBOL(posix_test_lock); | |||
703 | * from a broken NFS client. But broken NFS clients have a lot more to | 703 | * from a broken NFS client. But broken NFS clients have a lot more to |
704 | * worry about than proper deadlock detection anyway... --okir | 704 | * worry about than proper deadlock detection anyway... --okir |
705 | */ | 705 | */ |
706 | int posix_locks_deadlock(struct file_lock *caller_fl, | 706 | static int posix_locks_deadlock(struct file_lock *caller_fl, |
707 | struct file_lock *block_fl) | 707 | struct file_lock *block_fl) |
708 | { | 708 | { |
709 | struct list_head *tmp; | 709 | struct list_head *tmp; |
@@ -722,8 +722,6 @@ next_task: | |||
722 | return 0; | 722 | return 0; |
723 | } | 723 | } |
724 | 724 | ||
725 | EXPORT_SYMBOL(posix_locks_deadlock); | ||
726 | |||
727 | /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks | 725 | /* Try to create a FLOCK lock on filp. We always insert new FLOCK locks |
728 | * at the head of the list, but that's secret knowledge known only to | 726 | * at the head of the list, but that's secret knowledge known only to |
729 | * flock_lock_file and posix_lock_file. | 727 | * flock_lock_file and posix_lock_file. |
@@ -794,7 +792,8 @@ out: | |||
794 | static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) | 792 | static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request, struct file_lock *conflock) |
795 | { | 793 | { |
796 | struct file_lock *fl; | 794 | struct file_lock *fl; |
797 | struct file_lock *new_fl, *new_fl2; | 795 | struct file_lock *new_fl = NULL; |
796 | struct file_lock *new_fl2 = NULL; | ||
798 | struct file_lock *left = NULL; | 797 | struct file_lock *left = NULL; |
799 | struct file_lock *right = NULL; | 798 | struct file_lock *right = NULL; |
800 | struct file_lock **before; | 799 | struct file_lock **before; |
@@ -803,9 +802,15 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request | |||
803 | /* | 802 | /* |
804 | * We may need two file_lock structures for this operation, | 803 | * We may need two file_lock structures for this operation, |
805 | * so we get them in advance to avoid races. | 804 | * so we get them in advance to avoid races. |
805 | * | ||
806 | * In some cases we can be sure, that no new locks will be needed | ||
806 | */ | 807 | */ |
807 | new_fl = locks_alloc_lock(); | 808 | if (!(request->fl_flags & FL_ACCESS) && |
808 | new_fl2 = locks_alloc_lock(); | 809 | (request->fl_type != F_UNLCK || |
810 | request->fl_start != 0 || request->fl_end != OFFSET_MAX)) { | ||
811 | new_fl = locks_alloc_lock(); | ||
812 | new_fl2 = locks_alloc_lock(); | ||
813 | } | ||
809 | 814 | ||
810 | lock_kernel(); | 815 | lock_kernel(); |
811 | if (request->fl_type != F_UNLCK) { | 816 | if (request->fl_type != F_UNLCK) { |
@@ -834,14 +839,7 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request | |||
834 | if (request->fl_flags & FL_ACCESS) | 839 | if (request->fl_flags & FL_ACCESS) |
835 | goto out; | 840 | goto out; |
836 | 841 | ||
837 | error = -ENOLCK; /* "no luck" */ | ||
838 | if (!(new_fl && new_fl2)) | ||
839 | goto out; | ||
840 | |||
841 | /* | 842 | /* |
842 | * We've allocated the new locks in advance, so there are no | ||
843 | * errors possible (and no blocking operations) from here on. | ||
844 | * | ||
845 | * Find the first old lock with the same owner as the new lock. | 843 | * Find the first old lock with the same owner as the new lock. |
846 | */ | 844 | */ |
847 | 845 | ||
@@ -938,10 +936,25 @@ static int __posix_lock_file_conf(struct inode *inode, struct file_lock *request | |||
938 | before = &fl->fl_next; | 936 | before = &fl->fl_next; |
939 | } | 937 | } |
940 | 938 | ||
939 | /* | ||
940 | * The above code only modifies existing locks in case of | ||
941 | * merging or replacing. If new lock(s) need to be inserted | ||
942 | * all modifications are done bellow this, so it's safe yet to | ||
943 | * bail out. | ||
944 | */ | ||
945 | error = -ENOLCK; /* "no luck" */ | ||
946 | if (right && left == right && !new_fl2) | ||
947 | goto out; | ||
948 | |||
941 | error = 0; | 949 | error = 0; |
942 | if (!added) { | 950 | if (!added) { |
943 | if (request->fl_type == F_UNLCK) | 951 | if (request->fl_type == F_UNLCK) |
944 | goto out; | 952 | goto out; |
953 | |||
954 | if (!new_fl) { | ||
955 | error = -ENOLCK; | ||
956 | goto out; | ||
957 | } | ||
945 | locks_copy_lock(new_fl, request); | 958 | locks_copy_lock(new_fl, request); |
946 | locks_insert_lock(before, new_fl); | 959 | locks_insert_lock(before, new_fl); |
947 | new_fl = NULL; | 960 | new_fl = NULL; |
@@ -1881,19 +1894,18 @@ out: | |||
1881 | */ | 1894 | */ |
1882 | void locks_remove_posix(struct file *filp, fl_owner_t owner) | 1895 | void locks_remove_posix(struct file *filp, fl_owner_t owner) |
1883 | { | 1896 | { |
1884 | struct file_lock lock, **before; | 1897 | struct file_lock lock; |
1885 | 1898 | ||
1886 | /* | 1899 | /* |
1887 | * If there are no locks held on this file, we don't need to call | 1900 | * If there are no locks held on this file, we don't need to call |
1888 | * posix_lock_file(). Another process could be setting a lock on this | 1901 | * posix_lock_file(). Another process could be setting a lock on this |
1889 | * file at the same time, but we wouldn't remove that lock anyway. | 1902 | * file at the same time, but we wouldn't remove that lock anyway. |
1890 | */ | 1903 | */ |
1891 | before = &filp->f_dentry->d_inode->i_flock; | 1904 | if (!filp->f_dentry->d_inode->i_flock) |
1892 | if (*before == NULL) | ||
1893 | return; | 1905 | return; |
1894 | 1906 | ||
1895 | lock.fl_type = F_UNLCK; | 1907 | lock.fl_type = F_UNLCK; |
1896 | lock.fl_flags = FL_POSIX; | 1908 | lock.fl_flags = FL_POSIX | FL_CLOSE; |
1897 | lock.fl_start = 0; | 1909 | lock.fl_start = 0; |
1898 | lock.fl_end = OFFSET_MAX; | 1910 | lock.fl_end = OFFSET_MAX; |
1899 | lock.fl_owner = owner; | 1911 | lock.fl_owner = owner; |
@@ -1902,25 +1914,11 @@ void locks_remove_posix(struct file *filp, fl_owner_t owner) | |||
1902 | lock.fl_ops = NULL; | 1914 | lock.fl_ops = NULL; |
1903 | lock.fl_lmops = NULL; | 1915 | lock.fl_lmops = NULL; |
1904 | 1916 | ||
1905 | if (filp->f_op && filp->f_op->lock != NULL) { | 1917 | if (filp->f_op && filp->f_op->lock != NULL) |
1906 | filp->f_op->lock(filp, F_SETLK, &lock); | 1918 | filp->f_op->lock(filp, F_SETLK, &lock); |
1907 | goto out; | 1919 | else |
1908 | } | 1920 | posix_lock_file(filp, &lock); |
1909 | 1921 | ||
1910 | /* Can't use posix_lock_file here; we need to remove it no matter | ||
1911 | * which pid we have. | ||
1912 | */ | ||
1913 | lock_kernel(); | ||
1914 | while (*before != NULL) { | ||
1915 | struct file_lock *fl = *before; | ||
1916 | if (IS_POSIX(fl) && posix_same_owner(fl, &lock)) { | ||
1917 | locks_delete_lock(before); | ||
1918 | continue; | ||
1919 | } | ||
1920 | before = &fl->fl_next; | ||
1921 | } | ||
1922 | unlock_kernel(); | ||
1923 | out: | ||
1924 | if (lock.fl_ops && lock.fl_ops->fl_release_private) | 1922 | if (lock.fl_ops && lock.fl_ops->fl_release_private) |
1925 | lock.fl_ops->fl_release_private(&lock); | 1923 | lock.fl_ops->fl_release_private(&lock); |
1926 | } | 1924 | } |
@@ -2206,63 +2204,6 @@ int lock_may_write(struct inode *inode, loff_t start, unsigned long len) | |||
2206 | 2204 | ||
2207 | EXPORT_SYMBOL(lock_may_write); | 2205 | EXPORT_SYMBOL(lock_may_write); |
2208 | 2206 | ||
2209 | static inline void __steal_locks(struct file *file, fl_owner_t from) | ||
2210 | { | ||
2211 | struct inode *inode = file->f_dentry->d_inode; | ||
2212 | struct file_lock *fl = inode->i_flock; | ||
2213 | |||
2214 | while (fl) { | ||
2215 | if (fl->fl_file == file && fl->fl_owner == from) | ||
2216 | fl->fl_owner = current->files; | ||
2217 | fl = fl->fl_next; | ||
2218 | } | ||
2219 | } | ||
2220 | |||
2221 | /* When getting ready for executing a binary, we make sure that current | ||
2222 | * has a files_struct on its own. Before dropping the old files_struct, | ||
2223 | * we take over ownership of all locks for all file descriptors we own. | ||
2224 | * Note that we may accidentally steal a lock for a file that a sibling | ||
2225 | * has created since the unshare_files() call. | ||
2226 | */ | ||
2227 | void steal_locks(fl_owner_t from) | ||
2228 | { | ||
2229 | struct files_struct *files = current->files; | ||
2230 | int i, j; | ||
2231 | struct fdtable *fdt; | ||
2232 | |||
2233 | if (from == files) | ||
2234 | return; | ||
2235 | |||
2236 | lock_kernel(); | ||
2237 | j = 0; | ||
2238 | |||
2239 | /* | ||
2240 | * We are not taking a ref to the file structures, so | ||
2241 | * we need to acquire ->file_lock. | ||
2242 | */ | ||
2243 | spin_lock(&files->file_lock); | ||
2244 | fdt = files_fdtable(files); | ||
2245 | for (;;) { | ||
2246 | unsigned long set; | ||
2247 | i = j * __NFDBITS; | ||
2248 | if (i >= fdt->max_fdset || i >= fdt->max_fds) | ||
2249 | break; | ||
2250 | set = fdt->open_fds->fds_bits[j++]; | ||
2251 | while (set) { | ||
2252 | if (set & 1) { | ||
2253 | struct file *file = fdt->fd[i]; | ||
2254 | if (file) | ||
2255 | __steal_locks(file, from); | ||
2256 | } | ||
2257 | i++; | ||
2258 | set >>= 1; | ||
2259 | } | ||
2260 | } | ||
2261 | spin_unlock(&files->file_lock); | ||
2262 | unlock_kernel(); | ||
2263 | } | ||
2264 | EXPORT_SYMBOL(steal_locks); | ||
2265 | |||
2266 | static int __init filelock_init(void) | 2207 | static int __init filelock_init(void) |
2267 | { | 2208 | { |
2268 | filelock_cache = kmem_cache_create("file_lock_cache", | 2209 | filelock_cache = kmem_cache_create("file_lock_cache", |
diff --git a/fs/minix/dir.c b/fs/minix/dir.c index 69224d1fe043..2b0a389d1987 100644 --- a/fs/minix/dir.c +++ b/fs/minix/dir.c | |||
@@ -60,8 +60,7 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) | |||
60 | static struct page * dir_get_page(struct inode *dir, unsigned long n) | 60 | static struct page * dir_get_page(struct inode *dir, unsigned long n) |
61 | { | 61 | { |
62 | struct address_space *mapping = dir->i_mapping; | 62 | struct address_space *mapping = dir->i_mapping; |
63 | struct page *page = read_cache_page(mapping, n, | 63 | struct page *page = read_mapping_page(mapping, n, NULL); |
64 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
65 | if (!IS_ERR(page)) { | 64 | if (!IS_ERR(page)) { |
66 | wait_on_page_locked(page); | 65 | wait_on_page_locked(page); |
67 | kmap(page); | 66 | kmap(page); |
diff --git a/fs/minix/inode.c b/fs/minix/inode.c index 2dcccf1d1b7f..a6fb509b7341 100644 --- a/fs/minix/inode.c +++ b/fs/minix/inode.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | static void minix_read_inode(struct inode * inode); | 20 | static void minix_read_inode(struct inode * inode); |
21 | static int minix_write_inode(struct inode * inode, int wait); | 21 | static int minix_write_inode(struct inode * inode, int wait); |
22 | static int minix_statfs(struct super_block *sb, struct kstatfs *buf); | 22 | static int minix_statfs(struct dentry *dentry, struct kstatfs *buf); |
23 | static int minix_remount (struct super_block * sb, int * flags, char * data); | 23 | static int minix_remount (struct super_block * sb, int * flags, char * data); |
24 | 24 | ||
25 | static void minix_delete_inode(struct inode *inode) | 25 | static void minix_delete_inode(struct inode *inode) |
@@ -296,11 +296,11 @@ out_bad_sb: | |||
296 | return -EINVAL; | 296 | return -EINVAL; |
297 | } | 297 | } |
298 | 298 | ||
299 | static int minix_statfs(struct super_block *sb, struct kstatfs *buf) | 299 | static int minix_statfs(struct dentry *dentry, struct kstatfs *buf) |
300 | { | 300 | { |
301 | struct minix_sb_info *sbi = minix_sb(sb); | 301 | struct minix_sb_info *sbi = minix_sb(dentry->d_sb); |
302 | buf->f_type = sb->s_magic; | 302 | buf->f_type = dentry->d_sb->s_magic; |
303 | buf->f_bsize = sb->s_blocksize; | 303 | buf->f_bsize = dentry->d_sb->s_blocksize; |
304 | buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; | 304 | buf->f_blocks = (sbi->s_nzones - sbi->s_firstdatazone) << sbi->s_log_zone_size; |
305 | buf->f_bfree = minix_count_free_blocks(sbi); | 305 | buf->f_bfree = minix_count_free_blocks(sbi); |
306 | buf->f_bavail = buf->f_bfree; | 306 | buf->f_bavail = buf->f_bfree; |
@@ -559,10 +559,11 @@ void minix_truncate(struct inode * inode) | |||
559 | V2_minix_truncate(inode); | 559 | V2_minix_truncate(inode); |
560 | } | 560 | } |
561 | 561 | ||
562 | static struct super_block *minix_get_sb(struct file_system_type *fs_type, | 562 | static int minix_get_sb(struct file_system_type *fs_type, |
563 | int flags, const char *dev_name, void *data) | 563 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
564 | { | 564 | { |
565 | return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super); | 565 | return get_sb_bdev(fs_type, flags, dev_name, data, minix_fill_super, |
566 | mnt); | ||
566 | } | 567 | } |
567 | 568 | ||
568 | static struct file_system_type minix_fs_type = { | 569 | static struct file_system_type minix_fs_type = { |
diff --git a/fs/mpage.c b/fs/mpage.c index 9bf2eb30e6f4..1e4598247d0b 100644 --- a/fs/mpage.c +++ b/fs/mpage.c | |||
@@ -707,9 +707,9 @@ mpage_writepages(struct address_space *mapping, | |||
707 | struct pagevec pvec; | 707 | struct pagevec pvec; |
708 | int nr_pages; | 708 | int nr_pages; |
709 | pgoff_t index; | 709 | pgoff_t index; |
710 | pgoff_t end = -1; /* Inclusive */ | 710 | pgoff_t end; /* Inclusive */ |
711 | int scanned = 0; | 711 | int scanned = 0; |
712 | int is_range = 0; | 712 | int range_whole = 0; |
713 | 713 | ||
714 | if (wbc->nonblocking && bdi_write_congested(bdi)) { | 714 | if (wbc->nonblocking && bdi_write_congested(bdi)) { |
715 | wbc->encountered_congestion = 1; | 715 | wbc->encountered_congestion = 1; |
@@ -721,16 +721,14 @@ mpage_writepages(struct address_space *mapping, | |||
721 | writepage = mapping->a_ops->writepage; | 721 | writepage = mapping->a_ops->writepage; |
722 | 722 | ||
723 | pagevec_init(&pvec, 0); | 723 | pagevec_init(&pvec, 0); |
724 | if (wbc->sync_mode == WB_SYNC_NONE) { | 724 | if (wbc->range_cyclic) { |
725 | index = mapping->writeback_index; /* Start from prev offset */ | 725 | index = mapping->writeback_index; /* Start from prev offset */ |
726 | end = -1; | ||
726 | } else { | 727 | } else { |
727 | index = 0; /* whole-file sweep */ | 728 | index = wbc->range_start >> PAGE_CACHE_SHIFT; |
728 | scanned = 1; | 729 | end = wbc->range_end >> PAGE_CACHE_SHIFT; |
729 | } | 730 | if (wbc->range_start == 0 && wbc->range_end == LLONG_MAX) |
730 | if (wbc->start || wbc->end) { | 731 | range_whole = 1; |
731 | index = wbc->start >> PAGE_CACHE_SHIFT; | ||
732 | end = wbc->end >> PAGE_CACHE_SHIFT; | ||
733 | is_range = 1; | ||
734 | scanned = 1; | 732 | scanned = 1; |
735 | } | 733 | } |
736 | retry: | 734 | retry: |
@@ -759,7 +757,7 @@ retry: | |||
759 | continue; | 757 | continue; |
760 | } | 758 | } |
761 | 759 | ||
762 | if (unlikely(is_range) && page->index > end) { | 760 | if (!wbc->range_cyclic && page->index > end) { |
763 | done = 1; | 761 | done = 1; |
764 | unlock_page(page); | 762 | unlock_page(page); |
765 | continue; | 763 | continue; |
@@ -810,7 +808,7 @@ retry: | |||
810 | index = 0; | 808 | index = 0; |
811 | goto retry; | 809 | goto retry; |
812 | } | 810 | } |
813 | if (!is_range) | 811 | if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0)) |
814 | mapping->writeback_index = index; | 812 | mapping->writeback_index = index; |
815 | if (bio) | 813 | if (bio) |
816 | mpage_bio_submit(WRITE, bio); | 814 | mpage_bio_submit(WRITE, bio); |
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 5b76ccd19e3f..9e44158a7540 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -661,11 +661,12 @@ static int msdos_fill_super(struct super_block *sb, void *data, int silent) | |||
661 | return 0; | 661 | return 0; |
662 | } | 662 | } |
663 | 663 | ||
664 | static struct super_block *msdos_get_sb(struct file_system_type *fs_type, | 664 | static int msdos_get_sb(struct file_system_type *fs_type, |
665 | int flags, const char *dev_name, | 665 | int flags, const char *dev_name, |
666 | void *data) | 666 | void *data, struct vfsmount *mnt) |
667 | { | 667 | { |
668 | return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super); | 668 | return get_sb_bdev(fs_type, flags, dev_name, data, msdos_fill_super, |
669 | mnt); | ||
669 | } | 670 | } |
670 | 671 | ||
671 | static struct file_system_type msdos_fs_type = { | 672 | static struct file_system_type msdos_fs_type = { |
diff --git a/fs/namei.c b/fs/namei.c index d6e2ee251736..bb4a3e40e432 100644 --- a/fs/namei.c +++ b/fs/namei.c | |||
@@ -1127,7 +1127,7 @@ out: | |||
1127 | if (likely(retval == 0)) { | 1127 | if (likely(retval == 0)) { |
1128 | if (unlikely(current->audit_context && nd && nd->dentry && | 1128 | if (unlikely(current->audit_context && nd && nd->dentry && |
1129 | nd->dentry->d_inode)) | 1129 | nd->dentry->d_inode)) |
1130 | audit_inode(name, nd->dentry->d_inode, flags); | 1130 | audit_inode(name, nd->dentry->d_inode); |
1131 | } | 1131 | } |
1132 | out_fail: | 1132 | out_fail: |
1133 | return retval; | 1133 | return retval; |
@@ -2577,8 +2577,7 @@ static char *page_getlink(struct dentry * dentry, struct page **ppage) | |||
2577 | { | 2577 | { |
2578 | struct page * page; | 2578 | struct page * page; |
2579 | struct address_space *mapping = dentry->d_inode->i_mapping; | 2579 | struct address_space *mapping = dentry->d_inode->i_mapping; |
2580 | page = read_cache_page(mapping, 0, (filler_t *)mapping->a_ops->readpage, | 2580 | page = read_mapping_page(mapping, 0, NULL); |
2581 | NULL); | ||
2582 | if (IS_ERR(page)) | 2581 | if (IS_ERR(page)) |
2583 | goto sync_fail; | 2582 | goto sync_fail; |
2584 | wait_on_page_locked(page); | 2583 | wait_on_page_locked(page); |
diff --git a/fs/namespace.c b/fs/namespace.c index bf478addb852..c13072a5f1ee 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
@@ -86,6 +86,15 @@ struct vfsmount *alloc_vfsmnt(const char *name) | |||
86 | return mnt; | 86 | return mnt; |
87 | } | 87 | } |
88 | 88 | ||
89 | int simple_set_mnt(struct vfsmount *mnt, struct super_block *sb) | ||
90 | { | ||
91 | mnt->mnt_sb = sb; | ||
92 | mnt->mnt_root = dget(sb->s_root); | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | EXPORT_SYMBOL(simple_set_mnt); | ||
97 | |||
89 | void free_vfsmnt(struct vfsmount *mnt) | 98 | void free_vfsmnt(struct vfsmount *mnt) |
90 | { | 99 | { |
91 | kfree(mnt->mnt_devname); | 100 | kfree(mnt->mnt_devname); |
diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index a1f3e972c6ef..90d2ea28f333 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c | |||
@@ -39,7 +39,7 @@ | |||
39 | 39 | ||
40 | static void ncp_delete_inode(struct inode *); | 40 | static void ncp_delete_inode(struct inode *); |
41 | static void ncp_put_super(struct super_block *); | 41 | static void ncp_put_super(struct super_block *); |
42 | static int ncp_statfs(struct super_block *, struct kstatfs *); | 42 | static int ncp_statfs(struct dentry *, struct kstatfs *); |
43 | 43 | ||
44 | static kmem_cache_t * ncp_inode_cachep; | 44 | static kmem_cache_t * ncp_inode_cachep; |
45 | 45 | ||
@@ -724,13 +724,14 @@ static void ncp_put_super(struct super_block *sb) | |||
724 | kfree(server); | 724 | kfree(server); |
725 | } | 725 | } |
726 | 726 | ||
727 | static int ncp_statfs(struct super_block *sb, struct kstatfs *buf) | 727 | static int ncp_statfs(struct dentry *dentry, struct kstatfs *buf) |
728 | { | 728 | { |
729 | struct dentry* d; | 729 | struct dentry* d; |
730 | struct inode* i; | 730 | struct inode* i; |
731 | struct ncp_inode_info* ni; | 731 | struct ncp_inode_info* ni; |
732 | struct ncp_server* s; | 732 | struct ncp_server* s; |
733 | struct ncp_volume_info vi; | 733 | struct ncp_volume_info vi; |
734 | struct super_block *sb = dentry->d_sb; | ||
734 | int err; | 735 | int err; |
735 | __u8 dh; | 736 | __u8 dh; |
736 | 737 | ||
@@ -957,10 +958,10 @@ out: | |||
957 | return result; | 958 | return result; |
958 | } | 959 | } |
959 | 960 | ||
960 | static struct super_block *ncp_get_sb(struct file_system_type *fs_type, | 961 | static int ncp_get_sb(struct file_system_type *fs_type, |
961 | int flags, const char *dev_name, void *data) | 962 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
962 | { | 963 | { |
963 | return get_sb_nodev(fs_type, flags, data, ncp_fill_super); | 964 | return get_sb_nodev(fs_type, flags, data, ncp_fill_super, mnt); |
964 | } | 965 | } |
965 | 966 | ||
966 | static struct file_system_type ncp_fs_type = { | 967 | static struct file_system_type ncp_fs_type = { |
diff --git a/fs/nfs/file.c b/fs/nfs/file.c index fade02c15e6e..fa05c027ea11 100644 --- a/fs/nfs/file.c +++ b/fs/nfs/file.c | |||
@@ -43,7 +43,7 @@ static int nfs_file_mmap(struct file *, struct vm_area_struct *); | |||
43 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); | 43 | static ssize_t nfs_file_sendfile(struct file *, loff_t *, size_t, read_actor_t, void *); |
44 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); | 44 | static ssize_t nfs_file_read(struct kiocb *, char __user *, size_t, loff_t); |
45 | static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); | 45 | static ssize_t nfs_file_write(struct kiocb *, const char __user *, size_t, loff_t); |
46 | static int nfs_file_flush(struct file *); | 46 | static int nfs_file_flush(struct file *, fl_owner_t id); |
47 | static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); | 47 | static int nfs_fsync(struct file *, struct dentry *dentry, int datasync); |
48 | static int nfs_check_flags(int flags); | 48 | static int nfs_check_flags(int flags); |
49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); | 49 | static int nfs_lock(struct file *filp, int cmd, struct file_lock *fl); |
@@ -188,7 +188,7 @@ static loff_t nfs_file_llseek(struct file *filp, loff_t offset, int origin) | |||
188 | * | 188 | * |
189 | */ | 189 | */ |
190 | static int | 190 | static int |
191 | nfs_file_flush(struct file *file) | 191 | nfs_file_flush(struct file *file, fl_owner_t id) |
192 | { | 192 | { |
193 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; | 193 | struct nfs_open_context *ctx = (struct nfs_open_context *)file->private_data; |
194 | struct inode *inode = file->f_dentry->d_inode; | 194 | struct inode *inode = file->f_dentry->d_inode; |
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index d0b991a92327..937fbfc381bb 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
@@ -65,7 +65,7 @@ static int nfs_write_inode(struct inode *,int); | |||
65 | static void nfs_delete_inode(struct inode *); | 65 | static void nfs_delete_inode(struct inode *); |
66 | static void nfs_clear_inode(struct inode *); | 66 | static void nfs_clear_inode(struct inode *); |
67 | static void nfs_umount_begin(struct super_block *); | 67 | static void nfs_umount_begin(struct super_block *); |
68 | static int nfs_statfs(struct super_block *, struct kstatfs *); | 68 | static int nfs_statfs(struct dentry *, struct kstatfs *); |
69 | static int nfs_show_options(struct seq_file *, struct vfsmount *); | 69 | static int nfs_show_options(struct seq_file *, struct vfsmount *); |
70 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); | 70 | static int nfs_show_stats(struct seq_file *, struct vfsmount *); |
71 | static void nfs_zap_acl_cache(struct inode *); | 71 | static void nfs_zap_acl_cache(struct inode *); |
@@ -534,8 +534,9 @@ nfs_fill_super(struct super_block *sb, struct nfs_mount_data *data, int silent) | |||
534 | } | 534 | } |
535 | 535 | ||
536 | static int | 536 | static int |
537 | nfs_statfs(struct super_block *sb, struct kstatfs *buf) | 537 | nfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
538 | { | 538 | { |
539 | struct super_block *sb = dentry->d_sb; | ||
539 | struct nfs_server *server = NFS_SB(sb); | 540 | struct nfs_server *server = NFS_SB(sb); |
540 | unsigned char blockbits; | 541 | unsigned char blockbits; |
541 | unsigned long blockres; | 542 | unsigned long blockres; |
@@ -1690,8 +1691,8 @@ static int nfs_compare_super(struct super_block *sb, void *data) | |||
1690 | return !nfs_compare_fh(&old->fh, &server->fh); | 1691 | return !nfs_compare_fh(&old->fh, &server->fh); |
1691 | } | 1692 | } |
1692 | 1693 | ||
1693 | static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | 1694 | static int nfs_get_sb(struct file_system_type *fs_type, |
1694 | int flags, const char *dev_name, void *raw_data) | 1695 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
1695 | { | 1696 | { |
1696 | int error; | 1697 | int error; |
1697 | struct nfs_server *server = NULL; | 1698 | struct nfs_server *server = NULL; |
@@ -1699,14 +1700,14 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1699 | struct nfs_fh *root; | 1700 | struct nfs_fh *root; |
1700 | struct nfs_mount_data *data = raw_data; | 1701 | struct nfs_mount_data *data = raw_data; |
1701 | 1702 | ||
1702 | s = ERR_PTR(-EINVAL); | 1703 | error = -EINVAL; |
1703 | if (data == NULL) { | 1704 | if (data == NULL) { |
1704 | dprintk("%s: missing data argument\n", __FUNCTION__); | 1705 | dprintk("%s: missing data argument\n", __FUNCTION__); |
1705 | goto out_err; | 1706 | goto out_err_noserver; |
1706 | } | 1707 | } |
1707 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { | 1708 | if (data->version <= 0 || data->version > NFS_MOUNT_VERSION) { |
1708 | dprintk("%s: bad mount version\n", __FUNCTION__); | 1709 | dprintk("%s: bad mount version\n", __FUNCTION__); |
1709 | goto out_err; | 1710 | goto out_err_noserver; |
1710 | } | 1711 | } |
1711 | switch (data->version) { | 1712 | switch (data->version) { |
1712 | case 1: | 1713 | case 1: |
@@ -1718,7 +1719,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1718 | dprintk("%s: mount structure version %d does not support NFSv3\n", | 1719 | dprintk("%s: mount structure version %d does not support NFSv3\n", |
1719 | __FUNCTION__, | 1720 | __FUNCTION__, |
1720 | data->version); | 1721 | data->version); |
1721 | goto out_err; | 1722 | goto out_err_noserver; |
1722 | } | 1723 | } |
1723 | data->root.size = NFS2_FHSIZE; | 1724 | data->root.size = NFS2_FHSIZE; |
1724 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); | 1725 | memcpy(data->root.data, data->old_root.data, NFS2_FHSIZE); |
@@ -1727,24 +1728,24 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1727 | dprintk("%s: mount structure version %d does not support strong security\n", | 1728 | dprintk("%s: mount structure version %d does not support strong security\n", |
1728 | __FUNCTION__, | 1729 | __FUNCTION__, |
1729 | data->version); | 1730 | data->version); |
1730 | goto out_err; | 1731 | goto out_err_noserver; |
1731 | } | 1732 | } |
1732 | case 5: | 1733 | case 5: |
1733 | memset(data->context, 0, sizeof(data->context)); | 1734 | memset(data->context, 0, sizeof(data->context)); |
1734 | } | 1735 | } |
1735 | #ifndef CONFIG_NFS_V3 | 1736 | #ifndef CONFIG_NFS_V3 |
1736 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ | 1737 | /* If NFSv3 is not compiled in, return -EPROTONOSUPPORT */ |
1737 | s = ERR_PTR(-EPROTONOSUPPORT); | 1738 | error = -EPROTONOSUPPORT; |
1738 | if (data->flags & NFS_MOUNT_VER3) { | 1739 | if (data->flags & NFS_MOUNT_VER3) { |
1739 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); | 1740 | dprintk("%s: NFSv3 not compiled into kernel\n", __FUNCTION__); |
1740 | goto out_err; | 1741 | goto out_err_noserver; |
1741 | } | 1742 | } |
1742 | #endif /* CONFIG_NFS_V3 */ | 1743 | #endif /* CONFIG_NFS_V3 */ |
1743 | 1744 | ||
1744 | s = ERR_PTR(-ENOMEM); | 1745 | error = -ENOMEM; |
1745 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | 1746 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); |
1746 | if (!server) | 1747 | if (!server) |
1747 | goto out_err; | 1748 | goto out_err_noserver; |
1748 | /* Zero out the NFS state stuff */ | 1749 | /* Zero out the NFS state stuff */ |
1749 | init_nfsv4_state(server); | 1750 | init_nfsv4_state(server); |
1750 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 1751 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
@@ -1754,7 +1755,7 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1754 | root->size = data->root.size; | 1755 | root->size = data->root.size; |
1755 | else | 1756 | else |
1756 | root->size = NFS2_FHSIZE; | 1757 | root->size = NFS2_FHSIZE; |
1757 | s = ERR_PTR(-EINVAL); | 1758 | error = -EINVAL; |
1758 | if (root->size > sizeof(root->data)) { | 1759 | if (root->size > sizeof(root->data)) { |
1759 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); | 1760 | dprintk("%s: invalid root filehandle\n", __FUNCTION__); |
1760 | goto out_err; | 1761 | goto out_err; |
@@ -1770,15 +1771,20 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1770 | } | 1771 | } |
1771 | 1772 | ||
1772 | /* Fire up rpciod if not yet running */ | 1773 | /* Fire up rpciod if not yet running */ |
1773 | s = ERR_PTR(rpciod_up()); | 1774 | error = rpciod_up(); |
1774 | if (IS_ERR(s)) { | 1775 | if (error < 0) { |
1775 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 1776 | dprintk("%s: couldn't start rpciod! Error = %d\n", |
1776 | __FUNCTION__, PTR_ERR(s)); | 1777 | __FUNCTION__, error); |
1777 | goto out_err; | 1778 | goto out_err; |
1778 | } | 1779 | } |
1779 | 1780 | ||
1780 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); | 1781 | s = sget(fs_type, nfs_compare_super, nfs_set_super, server); |
1781 | if (IS_ERR(s) || s->s_root) | 1782 | if (IS_ERR(s)) { |
1783 | error = PTR_ERR(s); | ||
1784 | goto out_err_rpciod; | ||
1785 | } | ||
1786 | |||
1787 | if (s->s_root) | ||
1782 | goto out_rpciod_down; | 1788 | goto out_rpciod_down; |
1783 | 1789 | ||
1784 | s->s_flags = flags; | 1790 | s->s_flags = flags; |
@@ -1787,15 +1793,22 @@ static struct super_block *nfs_get_sb(struct file_system_type *fs_type, | |||
1787 | if (error) { | 1793 | if (error) { |
1788 | up_write(&s->s_umount); | 1794 | up_write(&s->s_umount); |
1789 | deactivate_super(s); | 1795 | deactivate_super(s); |
1790 | return ERR_PTR(error); | 1796 | return error; |
1791 | } | 1797 | } |
1792 | s->s_flags |= MS_ACTIVE; | 1798 | s->s_flags |= MS_ACTIVE; |
1793 | return s; | 1799 | return simple_set_mnt(mnt, s); |
1800 | |||
1794 | out_rpciod_down: | 1801 | out_rpciod_down: |
1795 | rpciod_down(); | 1802 | rpciod_down(); |
1803 | kfree(server); | ||
1804 | return simple_set_mnt(mnt, s); | ||
1805 | |||
1806 | out_err_rpciod: | ||
1807 | rpciod_down(); | ||
1796 | out_err: | 1808 | out_err: |
1797 | kfree(server); | 1809 | kfree(server); |
1798 | return s; | 1810 | out_err_noserver: |
1811 | return error; | ||
1799 | } | 1812 | } |
1800 | 1813 | ||
1801 | static void nfs_kill_super(struct super_block *s) | 1814 | static void nfs_kill_super(struct super_block *s) |
@@ -2032,8 +2045,8 @@ nfs_copy_user_string(char *dst, struct nfs_string *src, int maxlen) | |||
2032 | return dst; | 2045 | return dst; |
2033 | } | 2046 | } |
2034 | 2047 | ||
2035 | static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | 2048 | static int nfs4_get_sb(struct file_system_type *fs_type, |
2036 | int flags, const char *dev_name, void *raw_data) | 2049 | int flags, const char *dev_name, void *raw_data, struct vfsmount *mnt) |
2037 | { | 2050 | { |
2038 | int error; | 2051 | int error; |
2039 | struct nfs_server *server; | 2052 | struct nfs_server *server; |
@@ -2043,16 +2056,16 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2043 | 2056 | ||
2044 | if (data == NULL) { | 2057 | if (data == NULL) { |
2045 | dprintk("%s: missing data argument\n", __FUNCTION__); | 2058 | dprintk("%s: missing data argument\n", __FUNCTION__); |
2046 | return ERR_PTR(-EINVAL); | 2059 | return -EINVAL; |
2047 | } | 2060 | } |
2048 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { | 2061 | if (data->version <= 0 || data->version > NFS4_MOUNT_VERSION) { |
2049 | dprintk("%s: bad mount version\n", __FUNCTION__); | 2062 | dprintk("%s: bad mount version\n", __FUNCTION__); |
2050 | return ERR_PTR(-EINVAL); | 2063 | return -EINVAL; |
2051 | } | 2064 | } |
2052 | 2065 | ||
2053 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); | 2066 | server = kzalloc(sizeof(struct nfs_server), GFP_KERNEL); |
2054 | if (!server) | 2067 | if (!server) |
2055 | return ERR_PTR(-ENOMEM); | 2068 | return -ENOMEM; |
2056 | /* Zero out the NFS state stuff */ | 2069 | /* Zero out the NFS state stuff */ |
2057 | init_nfsv4_state(server); | 2070 | init_nfsv4_state(server); |
2058 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); | 2071 | server->client = server->client_sys = server->client_acl = ERR_PTR(-EINVAL); |
@@ -2074,33 +2087,41 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2074 | 2087 | ||
2075 | /* We now require that the mount process passes the remote address */ | 2088 | /* We now require that the mount process passes the remote address */ |
2076 | if (data->host_addrlen != sizeof(server->addr)) { | 2089 | if (data->host_addrlen != sizeof(server->addr)) { |
2077 | s = ERR_PTR(-EINVAL); | 2090 | error = -EINVAL; |
2078 | goto out_free; | 2091 | goto out_free; |
2079 | } | 2092 | } |
2080 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { | 2093 | if (copy_from_user(&server->addr, data->host_addr, sizeof(server->addr))) { |
2081 | s = ERR_PTR(-EFAULT); | 2094 | error = -EFAULT; |
2082 | goto out_free; | 2095 | goto out_free; |
2083 | } | 2096 | } |
2084 | if (server->addr.sin_family != AF_INET || | 2097 | if (server->addr.sin_family != AF_INET || |
2085 | server->addr.sin_addr.s_addr == INADDR_ANY) { | 2098 | server->addr.sin_addr.s_addr == INADDR_ANY) { |
2086 | dprintk("%s: mount program didn't pass remote IP address!\n", | 2099 | dprintk("%s: mount program didn't pass remote IP address!\n", |
2087 | __FUNCTION__); | 2100 | __FUNCTION__); |
2088 | s = ERR_PTR(-EINVAL); | 2101 | error = -EINVAL; |
2089 | goto out_free; | 2102 | goto out_free; |
2090 | } | 2103 | } |
2091 | 2104 | ||
2092 | /* Fire up rpciod if not yet running */ | 2105 | /* Fire up rpciod if not yet running */ |
2093 | s = ERR_PTR(rpciod_up()); | 2106 | error = rpciod_up(); |
2094 | if (IS_ERR(s)) { | 2107 | if (error < 0) { |
2095 | dprintk("%s: couldn't start rpciod! Error = %ld\n", | 2108 | dprintk("%s: couldn't start rpciod! Error = %d\n", |
2096 | __FUNCTION__, PTR_ERR(s)); | 2109 | __FUNCTION__, error); |
2097 | goto out_free; | 2110 | goto out_free; |
2098 | } | 2111 | } |
2099 | 2112 | ||
2100 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); | 2113 | s = sget(fs_type, nfs4_compare_super, nfs_set_super, server); |
2101 | 2114 | if (IS_ERR(s)) { | |
2102 | if (IS_ERR(s) || s->s_root) | 2115 | error = PTR_ERR(s); |
2103 | goto out_free; | 2116 | goto out_free; |
2117 | } | ||
2118 | |||
2119 | if (s->s_root) { | ||
2120 | kfree(server->mnt_path); | ||
2121 | kfree(server->hostname); | ||
2122 | kfree(server); | ||
2123 | return simple_set_mnt(mnt, s); | ||
2124 | } | ||
2104 | 2125 | ||
2105 | s->s_flags = flags; | 2126 | s->s_flags = flags; |
2106 | 2127 | ||
@@ -2108,17 +2129,17 @@ static struct super_block *nfs4_get_sb(struct file_system_type *fs_type, | |||
2108 | if (error) { | 2129 | if (error) { |
2109 | up_write(&s->s_umount); | 2130 | up_write(&s->s_umount); |
2110 | deactivate_super(s); | 2131 | deactivate_super(s); |
2111 | return ERR_PTR(error); | 2132 | return error; |
2112 | } | 2133 | } |
2113 | s->s_flags |= MS_ACTIVE; | 2134 | s->s_flags |= MS_ACTIVE; |
2114 | return s; | 2135 | return simple_set_mnt(mnt, s); |
2115 | out_err: | 2136 | out_err: |
2116 | s = (struct super_block *)p; | 2137 | error = PTR_ERR(p); |
2117 | out_free: | 2138 | out_free: |
2118 | kfree(server->mnt_path); | 2139 | kfree(server->mnt_path); |
2119 | kfree(server->hostname); | 2140 | kfree(server->hostname); |
2120 | kfree(server); | 2141 | kfree(server); |
2121 | return s; | 2142 | return error; |
2122 | } | 2143 | } |
2123 | 2144 | ||
2124 | static void nfs4_kill_super(struct super_block *sb) | 2145 | static void nfs4_kill_super(struct super_block *sb) |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index de3998f15f10..5446a0861d1d 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1310,7 +1310,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp, | |||
1310 | if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || | 1310 | if ((bmval0 & (FATTR4_WORD0_FILES_FREE | FATTR4_WORD0_FILES_TOTAL)) || |
1311 | (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | | 1311 | (bmval1 & (FATTR4_WORD1_SPACE_AVAIL | FATTR4_WORD1_SPACE_FREE | |
1312 | FATTR4_WORD1_SPACE_TOTAL))) { | 1312 | FATTR4_WORD1_SPACE_TOTAL))) { |
1313 | status = vfs_statfs(dentry->d_inode->i_sb, &statfs); | 1313 | status = vfs_statfs(dentry, &statfs); |
1314 | if (status) | 1314 | if (status) |
1315 | goto out_nfserr; | 1315 | goto out_nfserr; |
1316 | } | 1316 | } |
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3ef017b3b5bd..a1810e6a93e5 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c | |||
@@ -494,10 +494,10 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) | |||
494 | return simple_fill_super(sb, 0x6e667364, nfsd_files); | 494 | return simple_fill_super(sb, 0x6e667364, nfsd_files); |
495 | } | 495 | } |
496 | 496 | ||
497 | static struct super_block *nfsd_get_sb(struct file_system_type *fs_type, | 497 | static int nfsd_get_sb(struct file_system_type *fs_type, |
498 | int flags, const char *dev_name, void *data) | 498 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
499 | { | 499 | { |
500 | return get_sb_single(fs_type, flags, data, nfsd_fill_super); | 500 | return get_sb_single(fs_type, flags, data, nfsd_fill_super, mnt); |
501 | } | 501 | } |
502 | 502 | ||
503 | static struct file_system_type nfsd_fs_type = { | 503 | static struct file_system_type nfsd_fs_type = { |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 1d65f13f458c..245eaa1fb59b 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1737,7 +1737,7 @@ int | |||
1737 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) | 1737 | nfsd_statfs(struct svc_rqst *rqstp, struct svc_fh *fhp, struct kstatfs *stat) |
1738 | { | 1738 | { |
1739 | int err = fh_verify(rqstp, fhp, 0, MAY_NOP); | 1739 | int err = fh_verify(rqstp, fhp, 0, MAY_NOP); |
1740 | if (!err && vfs_statfs(fhp->fh_dentry->d_inode->i_sb,stat)) | 1740 | if (!err && vfs_statfs(fhp->fh_dentry,stat)) |
1741 | err = nfserr_io; | 1741 | err = nfserr_io; |
1742 | return err; | 1742 | return err; |
1743 | } | 1743 | } |
diff --git a/fs/ntfs/aops.h b/fs/ntfs/aops.h index 3b74e66ca2ff..325ce261a107 100644 --- a/fs/ntfs/aops.h +++ b/fs/ntfs/aops.h | |||
@@ -86,8 +86,7 @@ static inline void ntfs_unmap_page(struct page *page) | |||
86 | static inline struct page *ntfs_map_page(struct address_space *mapping, | 86 | static inline struct page *ntfs_map_page(struct address_space *mapping, |
87 | unsigned long index) | 87 | unsigned long index) |
88 | { | 88 | { |
89 | struct page *page = read_cache_page(mapping, index, | 89 | struct page *page = read_mapping_page(mapping, index, NULL); |
90 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
91 | 90 | ||
92 | if (!IS_ERR(page)) { | 91 | if (!IS_ERR(page)) { |
93 | wait_on_page_locked(page); | 92 | wait_on_page_locked(page); |
diff --git a/fs/ntfs/attrib.c b/fs/ntfs/attrib.c index 1663f5c3c6aa..6708e1d68a9e 100644 --- a/fs/ntfs/attrib.c +++ b/fs/ntfs/attrib.c | |||
@@ -2529,8 +2529,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
2529 | end >>= PAGE_CACHE_SHIFT; | 2529 | end >>= PAGE_CACHE_SHIFT; |
2530 | /* If there is a first partial page, need to do it the slow way. */ | 2530 | /* If there is a first partial page, need to do it the slow way. */ |
2531 | if (start_ofs) { | 2531 | if (start_ofs) { |
2532 | page = read_cache_page(mapping, idx, | 2532 | page = read_mapping_page(mapping, idx, NULL); |
2533 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
2534 | if (IS_ERR(page)) { | 2533 | if (IS_ERR(page)) { |
2535 | ntfs_error(vol->sb, "Failed to read first partial " | 2534 | ntfs_error(vol->sb, "Failed to read first partial " |
2536 | "page (sync error, index 0x%lx).", idx); | 2535 | "page (sync error, index 0x%lx).", idx); |
@@ -2600,8 +2599,7 @@ int ntfs_attr_set(ntfs_inode *ni, const s64 ofs, const s64 cnt, const u8 val) | |||
2600 | } | 2599 | } |
2601 | /* If there is a last partial page, need to do it the slow way. */ | 2600 | /* If there is a last partial page, need to do it the slow way. */ |
2602 | if (end_ofs) { | 2601 | if (end_ofs) { |
2603 | page = read_cache_page(mapping, idx, | 2602 | page = read_mapping_page(mapping, idx, NULL); |
2604 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
2605 | if (IS_ERR(page)) { | 2603 | if (IS_ERR(page)) { |
2606 | ntfs_error(vol->sb, "Failed to read last partial page " | 2604 | ntfs_error(vol->sb, "Failed to read last partial page " |
2607 | "(sync error, index 0x%lx).", idx); | 2605 | "(sync error, index 0x%lx).", idx); |
diff --git a/fs/ntfs/file.c b/fs/ntfs/file.c index c63a83e8da98..88292f9e4b9b 100644 --- a/fs/ntfs/file.c +++ b/fs/ntfs/file.c | |||
@@ -231,8 +231,7 @@ do_non_resident_extend: | |||
231 | * Read the page. If the page is not present, this will zero | 231 | * Read the page. If the page is not present, this will zero |
232 | * the uninitialized regions for us. | 232 | * the uninitialized regions for us. |
233 | */ | 233 | */ |
234 | page = read_cache_page(mapping, index, | 234 | page = read_mapping_page(mapping, index, NULL); |
235 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
236 | if (IS_ERR(page)) { | 235 | if (IS_ERR(page)) { |
237 | err = PTR_ERR(page); | 236 | err = PTR_ERR(page); |
238 | goto init_err_out; | 237 | goto init_err_out; |
@@ -1484,14 +1483,15 @@ static inline void ntfs_flush_dcache_pages(struct page **pages, | |||
1484 | unsigned nr_pages) | 1483 | unsigned nr_pages) |
1485 | { | 1484 | { |
1486 | BUG_ON(!nr_pages); | 1485 | BUG_ON(!nr_pages); |
1486 | /* | ||
1487 | * Warning: Do not do the decrement at the same time as the call to | ||
1488 | * flush_dcache_page() because it is a NULL macro on i386 and hence the | ||
1489 | * decrement never happens so the loop never terminates. | ||
1490 | */ | ||
1487 | do { | 1491 | do { |
1488 | /* | 1492 | --nr_pages; |
1489 | * Warning: Do not do the decrement at the same time as the | ||
1490 | * call because flush_dcache_page() is a NULL macro on i386 | ||
1491 | * and hence the decrement never happens. | ||
1492 | */ | ||
1493 | flush_dcache_page(pages[nr_pages]); | 1493 | flush_dcache_page(pages[nr_pages]); |
1494 | } while (--nr_pages > 0); | 1494 | } while (nr_pages > 0); |
1495 | } | 1495 | } |
1496 | 1496 | ||
1497 | /** | 1497 | /** |
diff --git a/fs/ntfs/super.c b/fs/ntfs/super.c index 27833f6df49f..0e14acea3f8b 100644 --- a/fs/ntfs/super.c +++ b/fs/ntfs/super.c | |||
@@ -2601,10 +2601,10 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, | |||
2601 | 2601 | ||
2602 | /** | 2602 | /** |
2603 | * ntfs_statfs - return information about mounted NTFS volume | 2603 | * ntfs_statfs - return information about mounted NTFS volume |
2604 | * @sb: super block of mounted volume | 2604 | * @dentry: dentry from mounted volume |
2605 | * @sfs: statfs structure in which to return the information | 2605 | * @sfs: statfs structure in which to return the information |
2606 | * | 2606 | * |
2607 | * Return information about the mounted NTFS volume @sb in the statfs structure | 2607 | * Return information about the mounted NTFS volume @dentry in the statfs structure |
2608 | * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is | 2608 | * pointed to by @sfs (this is initialized with zeros before ntfs_statfs is |
2609 | * called). We interpret the values to be correct of the moment in time at | 2609 | * called). We interpret the values to be correct of the moment in time at |
2610 | * which we are called. Most values are variable otherwise and this isn't just | 2610 | * which we are called. Most values are variable otherwise and this isn't just |
@@ -2617,8 +2617,9 @@ static unsigned long __get_nr_free_mft_records(ntfs_volume *vol, | |||
2617 | * | 2617 | * |
2618 | * Return 0 on success or -errno on error. | 2618 | * Return 0 on success or -errno on error. |
2619 | */ | 2619 | */ |
2620 | static int ntfs_statfs(struct super_block *sb, struct kstatfs *sfs) | 2620 | static int ntfs_statfs(struct dentry *dentry, struct kstatfs *sfs) |
2621 | { | 2621 | { |
2622 | struct super_block *sb = dentry->d_sb; | ||
2622 | s64 size; | 2623 | s64 size; |
2623 | ntfs_volume *vol = NTFS_SB(sb); | 2624 | ntfs_volume *vol = NTFS_SB(sb); |
2624 | ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); | 2625 | ntfs_inode *mft_ni = NTFS_I(vol->mft_ino); |
@@ -3093,10 +3094,11 @@ struct kmem_cache *ntfs_index_ctx_cache; | |||
3093 | /* Driver wide mutex. */ | 3094 | /* Driver wide mutex. */ |
3094 | DEFINE_MUTEX(ntfs_lock); | 3095 | DEFINE_MUTEX(ntfs_lock); |
3095 | 3096 | ||
3096 | static struct super_block *ntfs_get_sb(struct file_system_type *fs_type, | 3097 | static int ntfs_get_sb(struct file_system_type *fs_type, |
3097 | int flags, const char *dev_name, void *data) | 3098 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
3098 | { | 3099 | { |
3099 | return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super); | 3100 | return get_sb_bdev(fs_type, flags, dev_name, data, ntfs_fill_super, |
3101 | mnt); | ||
3100 | } | 3102 | } |
3101 | 3103 | ||
3102 | static struct file_system_type ntfs_fs_type = { | 3104 | static struct file_system_type ntfs_fs_type = { |
diff --git a/fs/ocfs2/dlm/dlmfs.c b/fs/ocfs2/dlm/dlmfs.c index 7e88e24b3471..7273d9fa6bab 100644 --- a/fs/ocfs2/dlm/dlmfs.c +++ b/fs/ocfs2/dlm/dlmfs.c | |||
@@ -574,10 +574,10 @@ static struct inode_operations dlmfs_file_inode_operations = { | |||
574 | .getattr = simple_getattr, | 574 | .getattr = simple_getattr, |
575 | }; | 575 | }; |
576 | 576 | ||
577 | static struct super_block *dlmfs_get_sb(struct file_system_type *fs_type, | 577 | static int dlmfs_get_sb(struct file_system_type *fs_type, |
578 | int flags, const char *dev_name, void *data) | 578 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
579 | { | 579 | { |
580 | return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super); | 580 | return get_sb_nodev(fs_type, flags, data, dlmfs_fill_super, mnt); |
581 | } | 581 | } |
582 | 582 | ||
583 | static struct file_system_type dlmfs_fs_type = { | 583 | static struct file_system_type dlmfs_fs_type = { |
diff --git a/fs/ocfs2/super.c b/fs/ocfs2/super.c index 949b3dac30f1..cdf73393f094 100644 --- a/fs/ocfs2/super.c +++ b/fs/ocfs2/super.c | |||
@@ -100,7 +100,7 @@ static int ocfs2_initialize_mem_caches(void); | |||
100 | static void ocfs2_free_mem_caches(void); | 100 | static void ocfs2_free_mem_caches(void); |
101 | static void ocfs2_delete_osb(struct ocfs2_super *osb); | 101 | static void ocfs2_delete_osb(struct ocfs2_super *osb); |
102 | 102 | ||
103 | static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf); | 103 | static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf); |
104 | 104 | ||
105 | static int ocfs2_sync_fs(struct super_block *sb, int wait); | 105 | static int ocfs2_sync_fs(struct super_block *sb, int wait); |
106 | 106 | ||
@@ -672,12 +672,14 @@ read_super_error: | |||
672 | return status; | 672 | return status; |
673 | } | 673 | } |
674 | 674 | ||
675 | static struct super_block *ocfs2_get_sb(struct file_system_type *fs_type, | 675 | static int ocfs2_get_sb(struct file_system_type *fs_type, |
676 | int flags, | 676 | int flags, |
677 | const char *dev_name, | 677 | const char *dev_name, |
678 | void *data) | 678 | void *data, |
679 | struct vfsmount *mnt) | ||
679 | { | 680 | { |
680 | return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super); | 681 | return get_sb_bdev(fs_type, flags, dev_name, data, ocfs2_fill_super, |
682 | mnt); | ||
681 | } | 683 | } |
682 | 684 | ||
683 | static struct file_system_type ocfs2_fs_type = { | 685 | static struct file_system_type ocfs2_fs_type = { |
@@ -855,7 +857,7 @@ static void ocfs2_put_super(struct super_block *sb) | |||
855 | mlog_exit_void(); | 857 | mlog_exit_void(); |
856 | } | 858 | } |
857 | 859 | ||
858 | static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) | 860 | static int ocfs2_statfs(struct dentry *dentry, struct kstatfs *buf) |
859 | { | 861 | { |
860 | struct ocfs2_super *osb; | 862 | struct ocfs2_super *osb; |
861 | u32 numbits, freebits; | 863 | u32 numbits, freebits; |
@@ -864,9 +866,9 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) | |||
864 | struct buffer_head *bh = NULL; | 866 | struct buffer_head *bh = NULL; |
865 | struct inode *inode = NULL; | 867 | struct inode *inode = NULL; |
866 | 868 | ||
867 | mlog_entry("(%p, %p)\n", sb, buf); | 869 | mlog_entry("(%p, %p)\n", dentry->d_sb, buf); |
868 | 870 | ||
869 | osb = OCFS2_SB(sb); | 871 | osb = OCFS2_SB(dentry->d_sb); |
870 | 872 | ||
871 | inode = ocfs2_get_system_file_inode(osb, | 873 | inode = ocfs2_get_system_file_inode(osb, |
872 | GLOBAL_BITMAP_SYSTEM_INODE, | 874 | GLOBAL_BITMAP_SYSTEM_INODE, |
@@ -889,7 +891,7 @@ static int ocfs2_statfs(struct super_block *sb, struct kstatfs *buf) | |||
889 | freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); | 891 | freebits = numbits - le32_to_cpu(bm_lock->id1.bitmap1.i_used); |
890 | 892 | ||
891 | buf->f_type = OCFS2_SUPER_MAGIC; | 893 | buf->f_type = OCFS2_SUPER_MAGIC; |
892 | buf->f_bsize = sb->s_blocksize; | 894 | buf->f_bsize = dentry->d_sb->s_blocksize; |
893 | buf->f_namelen = OCFS2_MAX_FILENAME_LEN; | 895 | buf->f_namelen = OCFS2_MAX_FILENAME_LEN; |
894 | buf->f_blocks = ((sector_t) numbits) * | 896 | buf->f_blocks = ((sector_t) numbits) * |
895 | (osb->s_clustersize >> osb->sb->s_blocksize_bits); | 897 | (osb->s_clustersize >> osb->sb->s_blocksize_bits); |
diff --git a/fs/ocfs2/symlink.c b/fs/ocfs2/symlink.c index f6986bd79e75..0c8a1294ec96 100644 --- a/fs/ocfs2/symlink.c +++ b/fs/ocfs2/symlink.c | |||
@@ -64,8 +64,7 @@ static char *ocfs2_page_getlink(struct dentry * dentry, | |||
64 | { | 64 | { |
65 | struct page * page; | 65 | struct page * page; |
66 | struct address_space *mapping = dentry->d_inode->i_mapping; | 66 | struct address_space *mapping = dentry->d_inode->i_mapping; |
67 | page = read_cache_page(mapping, 0, | 67 | page = read_mapping_page(mapping, 0, NULL); |
68 | (filler_t *)mapping->a_ops->readpage, NULL); | ||
69 | if (IS_ERR(page)) | 68 | if (IS_ERR(page)) |
70 | goto sync_fail; | 69 | goto sync_fail; |
71 | wait_on_page_locked(page); | 70 | wait_on_page_locked(page); |
@@ -31,18 +31,18 @@ | |||
31 | 31 | ||
32 | #include <asm/unistd.h> | 32 | #include <asm/unistd.h> |
33 | 33 | ||
34 | int vfs_statfs(struct super_block *sb, struct kstatfs *buf) | 34 | int vfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
35 | { | 35 | { |
36 | int retval = -ENODEV; | 36 | int retval = -ENODEV; |
37 | 37 | ||
38 | if (sb) { | 38 | if (dentry) { |
39 | retval = -ENOSYS; | 39 | retval = -ENOSYS; |
40 | if (sb->s_op->statfs) { | 40 | if (dentry->d_sb->s_op->statfs) { |
41 | memset(buf, 0, sizeof(*buf)); | 41 | memset(buf, 0, sizeof(*buf)); |
42 | retval = security_sb_statfs(sb); | 42 | retval = security_sb_statfs(dentry); |
43 | if (retval) | 43 | if (retval) |
44 | return retval; | 44 | return retval; |
45 | retval = sb->s_op->statfs(sb, buf); | 45 | retval = dentry->d_sb->s_op->statfs(dentry, buf); |
46 | if (retval == 0 && buf->f_frsize == 0) | 46 | if (retval == 0 && buf->f_frsize == 0) |
47 | buf->f_frsize = buf->f_bsize; | 47 | buf->f_frsize = buf->f_bsize; |
48 | } | 48 | } |
@@ -52,12 +52,12 @@ int vfs_statfs(struct super_block *sb, struct kstatfs *buf) | |||
52 | 52 | ||
53 | EXPORT_SYMBOL(vfs_statfs); | 53 | EXPORT_SYMBOL(vfs_statfs); |
54 | 54 | ||
55 | static int vfs_statfs_native(struct super_block *sb, struct statfs *buf) | 55 | static int vfs_statfs_native(struct dentry *dentry, struct statfs *buf) |
56 | { | 56 | { |
57 | struct kstatfs st; | 57 | struct kstatfs st; |
58 | int retval; | 58 | int retval; |
59 | 59 | ||
60 | retval = vfs_statfs(sb, &st); | 60 | retval = vfs_statfs(dentry, &st); |
61 | if (retval) | 61 | if (retval) |
62 | return retval; | 62 | return retval; |
63 | 63 | ||
@@ -95,12 +95,12 @@ static int vfs_statfs_native(struct super_block *sb, struct statfs *buf) | |||
95 | return 0; | 95 | return 0; |
96 | } | 96 | } |
97 | 97 | ||
98 | static int vfs_statfs64(struct super_block *sb, struct statfs64 *buf) | 98 | static int vfs_statfs64(struct dentry *dentry, struct statfs64 *buf) |
99 | { | 99 | { |
100 | struct kstatfs st; | 100 | struct kstatfs st; |
101 | int retval; | 101 | int retval; |
102 | 102 | ||
103 | retval = vfs_statfs(sb, &st); | 103 | retval = vfs_statfs(dentry, &st); |
104 | if (retval) | 104 | if (retval) |
105 | return retval; | 105 | return retval; |
106 | 106 | ||
@@ -130,7 +130,7 @@ asmlinkage long sys_statfs(const char __user * path, struct statfs __user * buf) | |||
130 | error = user_path_walk(path, &nd); | 130 | error = user_path_walk(path, &nd); |
131 | if (!error) { | 131 | if (!error) { |
132 | struct statfs tmp; | 132 | struct statfs tmp; |
133 | error = vfs_statfs_native(nd.dentry->d_inode->i_sb, &tmp); | 133 | error = vfs_statfs_native(nd.dentry, &tmp); |
134 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 134 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
135 | error = -EFAULT; | 135 | error = -EFAULT; |
136 | path_release(&nd); | 136 | path_release(&nd); |
@@ -149,7 +149,7 @@ asmlinkage long sys_statfs64(const char __user *path, size_t sz, struct statfs64 | |||
149 | error = user_path_walk(path, &nd); | 149 | error = user_path_walk(path, &nd); |
150 | if (!error) { | 150 | if (!error) { |
151 | struct statfs64 tmp; | 151 | struct statfs64 tmp; |
152 | error = vfs_statfs64(nd.dentry->d_inode->i_sb, &tmp); | 152 | error = vfs_statfs64(nd.dentry, &tmp); |
153 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 153 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
154 | error = -EFAULT; | 154 | error = -EFAULT; |
155 | path_release(&nd); | 155 | path_release(&nd); |
@@ -168,7 +168,7 @@ asmlinkage long sys_fstatfs(unsigned int fd, struct statfs __user * buf) | |||
168 | file = fget(fd); | 168 | file = fget(fd); |
169 | if (!file) | 169 | if (!file) |
170 | goto out; | 170 | goto out; |
171 | error = vfs_statfs_native(file->f_dentry->d_inode->i_sb, &tmp); | 171 | error = vfs_statfs_native(file->f_dentry, &tmp); |
172 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 172 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
173 | error = -EFAULT; | 173 | error = -EFAULT; |
174 | fput(file); | 174 | fput(file); |
@@ -189,7 +189,7 @@ asmlinkage long sys_fstatfs64(unsigned int fd, size_t sz, struct statfs64 __user | |||
189 | file = fget(fd); | 189 | file = fget(fd); |
190 | if (!file) | 190 | if (!file) |
191 | goto out; | 191 | goto out; |
192 | error = vfs_statfs64(file->f_dentry->d_inode->i_sb, &tmp); | 192 | error = vfs_statfs64(file->f_dentry, &tmp); |
193 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) | 193 | if (!error && copy_to_user(buf, &tmp, sizeof(tmp))) |
194 | error = -EFAULT; | 194 | error = -EFAULT; |
195 | fput(file); | 195 | fput(file); |
@@ -633,7 +633,7 @@ asmlinkage long sys_fchmod(unsigned int fd, mode_t mode) | |||
633 | dentry = file->f_dentry; | 633 | dentry = file->f_dentry; |
634 | inode = dentry->d_inode; | 634 | inode = dentry->d_inode; |
635 | 635 | ||
636 | audit_inode(NULL, inode, 0); | 636 | audit_inode(NULL, inode); |
637 | 637 | ||
638 | err = -EROFS; | 638 | err = -EROFS; |
639 | if (IS_RDONLY(inode)) | 639 | if (IS_RDONLY(inode)) |
@@ -786,7 +786,7 @@ asmlinkage long sys_fchown(unsigned int fd, uid_t user, gid_t group) | |||
786 | if (file) { | 786 | if (file) { |
787 | struct dentry * dentry; | 787 | struct dentry * dentry; |
788 | dentry = file->f_dentry; | 788 | dentry = file->f_dentry; |
789 | audit_inode(NULL, dentry->d_inode, 0); | 789 | audit_inode(NULL, dentry->d_inode); |
790 | error = chown_common(dentry, user, group); | 790 | error = chown_common(dentry, user, group); |
791 | fput(file); | 791 | fput(file); |
792 | } | 792 | } |
@@ -1152,7 +1152,7 @@ int filp_close(struct file *filp, fl_owner_t id) | |||
1152 | } | 1152 | } |
1153 | 1153 | ||
1154 | if (filp->f_op && filp->f_op->flush) | 1154 | if (filp->f_op && filp->f_op->flush) |
1155 | retval = filp->f_op->flush(filp); | 1155 | retval = filp->f_op->flush(filp, id); |
1156 | 1156 | ||
1157 | dnotify_flush(filp, id); | 1157 | dnotify_flush(filp, id); |
1158 | locks_remove_posix(filp, id); | 1158 | locks_remove_posix(filp, id); |
diff --git a/fs/openpromfs/inode.c b/fs/openpromfs/inode.c index 0f14276a2e51..464e2bce0203 100644 --- a/fs/openpromfs/inode.c +++ b/fs/openpromfs/inode.c | |||
@@ -1054,10 +1054,10 @@ out_no_root: | |||
1054 | return -ENOMEM; | 1054 | return -ENOMEM; |
1055 | } | 1055 | } |
1056 | 1056 | ||
1057 | static struct super_block *openprom_get_sb(struct file_system_type *fs_type, | 1057 | static int openprom_get_sb(struct file_system_type *fs_type, |
1058 | int flags, const char *dev_name, void *data) | 1058 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1059 | { | 1059 | { |
1060 | return get_sb_single(fs_type, flags, data, openprom_fill_super); | 1060 | return get_sb_single(fs_type, flags, data, openprom_fill_super, mnt); |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | static struct file_system_type openprom_fs_type = { | 1063 | static struct file_system_type openprom_fs_type = { |
diff --git a/fs/partitions/check.c b/fs/partitions/check.c index 7ef1f094de91..2ef313a96b66 100644 --- a/fs/partitions/check.c +++ b/fs/partitions/check.c | |||
@@ -329,6 +329,7 @@ void delete_partition(struct gendisk *disk, int part) | |||
329 | p->ios[0] = p->ios[1] = 0; | 329 | p->ios[0] = p->ios[1] = 0; |
330 | p->sectors[0] = p->sectors[1] = 0; | 330 | p->sectors[0] = p->sectors[1] = 0; |
331 | devfs_remove("%s/part%d", disk->devfs_name, part); | 331 | devfs_remove("%s/part%d", disk->devfs_name, part); |
332 | sysfs_remove_link(&p->kobj, "subsystem"); | ||
332 | if (p->holder_dir) | 333 | if (p->holder_dir) |
333 | kobject_unregister(p->holder_dir); | 334 | kobject_unregister(p->holder_dir); |
334 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | 335 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
@@ -363,6 +364,7 @@ void add_partition(struct gendisk *disk, int part, sector_t start, sector_t len) | |||
363 | kobject_add(&p->kobj); | 364 | kobject_add(&p->kobj); |
364 | if (!disk->part_uevent_suppress) | 365 | if (!disk->part_uevent_suppress) |
365 | kobject_uevent(&p->kobj, KOBJ_ADD); | 366 | kobject_uevent(&p->kobj, KOBJ_ADD); |
367 | sysfs_create_link(&p->kobj, &block_subsys.kset.kobj, "subsystem"); | ||
366 | partition_sysfs_add_subdir(p); | 368 | partition_sysfs_add_subdir(p); |
367 | disk->part[part-1] = p; | 369 | disk->part[part-1] = p; |
368 | } | 370 | } |
@@ -398,6 +400,7 @@ static void disk_sysfs_symlinks(struct gendisk *disk) | |||
398 | kfree(disk_name); | 400 | kfree(disk_name); |
399 | } | 401 | } |
400 | } | 402 | } |
403 | sysfs_create_link(&disk->kobj, &block_subsys.kset.kobj, "subsystem"); | ||
401 | } | 404 | } |
402 | 405 | ||
403 | /* Not exported, helper to add_disk(). */ | 406 | /* Not exported, helper to add_disk(). */ |
@@ -481,6 +484,10 @@ int rescan_partitions(struct gendisk *disk, struct block_device *bdev) | |||
481 | sector_t from = state->parts[p].from; | 484 | sector_t from = state->parts[p].from; |
482 | if (!size) | 485 | if (!size) |
483 | continue; | 486 | continue; |
487 | if (from + size > get_capacity(disk)) { | ||
488 | printk(" %s: p%d exceeds device capacity\n", | ||
489 | disk->disk_name, p); | ||
490 | } | ||
484 | add_partition(disk, p, from, size); | 491 | add_partition(disk, p, from, size); |
485 | #ifdef CONFIG_BLK_DEV_MD | 492 | #ifdef CONFIG_BLK_DEV_MD |
486 | if (state->parts[p].flags) | 493 | if (state->parts[p].flags) |
@@ -496,8 +503,8 @@ unsigned char *read_dev_sector(struct block_device *bdev, sector_t n, Sector *p) | |||
496 | struct address_space *mapping = bdev->bd_inode->i_mapping; | 503 | struct address_space *mapping = bdev->bd_inode->i_mapping; |
497 | struct page *page; | 504 | struct page *page; |
498 | 505 | ||
499 | page = read_cache_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), | 506 | page = read_mapping_page(mapping, (pgoff_t)(n >> (PAGE_CACHE_SHIFT-9)), |
500 | (filler_t *)mapping->a_ops->readpage, NULL); | 507 | NULL); |
501 | if (!IS_ERR(page)) { | 508 | if (!IS_ERR(page)) { |
502 | wait_on_page_locked(page); | 509 | wait_on_page_locked(page); |
503 | if (!PageUptodate(page)) | 510 | if (!PageUptodate(page)) |
@@ -548,5 +555,6 @@ void del_gendisk(struct gendisk *disk) | |||
548 | put_device(disk->driverfs_dev); | 555 | put_device(disk->driverfs_dev); |
549 | disk->driverfs_dev = NULL; | 556 | disk->driverfs_dev = NULL; |
550 | } | 557 | } |
558 | sysfs_remove_link(&disk->kobj, "subsystem"); | ||
551 | kobject_del(&disk->kobj); | 559 | kobject_del(&disk->kobj); |
552 | } | 560 | } |
@@ -979,12 +979,11 @@ no_files: | |||
979 | * any operations on the root directory. However, we need a non-trivial | 979 | * any operations on the root directory. However, we need a non-trivial |
980 | * d_name - pipe: will go nicely and kill the special-casing in procfs. | 980 | * d_name - pipe: will go nicely and kill the special-casing in procfs. |
981 | */ | 981 | */ |
982 | 982 | static int pipefs_get_sb(struct file_system_type *fs_type, | |
983 | static struct super_block * | 983 | int flags, const char *dev_name, void *data, |
984 | pipefs_get_sb(struct file_system_type *fs_type, int flags, | 984 | struct vfsmount *mnt) |
985 | const char *dev_name, void *data) | ||
986 | { | 985 | { |
987 | return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC); | 986 | return get_sb_pseudo(fs_type, "pipe:", NULL, PIPEFS_MAGIC, mnt); |
988 | } | 987 | } |
989 | 988 | ||
990 | static struct file_system_type pipe_fs_type = { | 989 | static struct file_system_type pipe_fs_type = { |
diff --git a/fs/proc/base.c b/fs/proc/base.c index 6cc77dc3f3ff..6afff725a8c9 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -1019,8 +1019,8 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, | |||
1019 | if (current != task) | 1019 | if (current != task) |
1020 | return -EPERM; | 1020 | return -EPERM; |
1021 | 1021 | ||
1022 | if (count > PAGE_SIZE) | 1022 | if (count >= PAGE_SIZE) |
1023 | count = PAGE_SIZE; | 1023 | count = PAGE_SIZE - 1; |
1024 | 1024 | ||
1025 | if (*ppos != 0) { | 1025 | if (*ppos != 0) { |
1026 | /* No partial writes. */ | 1026 | /* No partial writes. */ |
@@ -1033,6 +1033,7 @@ static ssize_t proc_loginuid_write(struct file * file, const char __user * buf, | |||
1033 | if (copy_from_user(page, buf, count)) | 1033 | if (copy_from_user(page, buf, count)) |
1034 | goto out_free_page; | 1034 | goto out_free_page; |
1035 | 1035 | ||
1036 | page[count] = '\0'; | ||
1036 | loginuid = simple_strtoul(page, &tmp, 10); | 1037 | loginuid = simple_strtoul(page, &tmp, 10); |
1037 | if (tmp == page) { | 1038 | if (tmp == page) { |
1038 | length = -EINVAL; | 1039 | length = -EINVAL; |
diff --git a/fs/proc/root.c b/fs/proc/root.c index c3fd3611112f..9995356ce73e 100644 --- a/fs/proc/root.c +++ b/fs/proc/root.c | |||
@@ -26,10 +26,10 @@ struct proc_dir_entry *proc_net, *proc_net_stat, *proc_bus, *proc_root_fs, *proc | |||
26 | struct proc_dir_entry *proc_sys_root; | 26 | struct proc_dir_entry *proc_sys_root; |
27 | #endif | 27 | #endif |
28 | 28 | ||
29 | static struct super_block *proc_get_sb(struct file_system_type *fs_type, | 29 | static int proc_get_sb(struct file_system_type *fs_type, |
30 | int flags, const char *dev_name, void *data) | 30 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
31 | { | 31 | { |
32 | return get_sb_single(fs_type, flags, data, proc_fill_super); | 32 | return get_sb_single(fs_type, flags, data, proc_fill_super, mnt); |
33 | } | 33 | } |
34 | 34 | ||
35 | static struct file_system_type proc_fs_type = { | 35 | static struct file_system_type proc_fs_type = { |
diff --git a/fs/qnx4/inode.c b/fs/qnx4/inode.c index 2ecd46f85e9f..2f24c46f72a1 100644 --- a/fs/qnx4/inode.c +++ b/fs/qnx4/inode.c | |||
@@ -128,7 +128,7 @@ static struct inode *qnx4_alloc_inode(struct super_block *sb); | |||
128 | static void qnx4_destroy_inode(struct inode *inode); | 128 | static void qnx4_destroy_inode(struct inode *inode); |
129 | static void qnx4_read_inode(struct inode *); | 129 | static void qnx4_read_inode(struct inode *); |
130 | static int qnx4_remount(struct super_block *sb, int *flags, char *data); | 130 | static int qnx4_remount(struct super_block *sb, int *flags, char *data); |
131 | static int qnx4_statfs(struct super_block *, struct kstatfs *); | 131 | static int qnx4_statfs(struct dentry *, struct kstatfs *); |
132 | 132 | ||
133 | static struct super_operations qnx4_sops = | 133 | static struct super_operations qnx4_sops = |
134 | { | 134 | { |
@@ -282,8 +282,10 @@ unsigned long qnx4_block_map( struct inode *inode, long iblock ) | |||
282 | return block; | 282 | return block; |
283 | } | 283 | } |
284 | 284 | ||
285 | static int qnx4_statfs(struct super_block *sb, struct kstatfs *buf) | 285 | static int qnx4_statfs(struct dentry *dentry, struct kstatfs *buf) |
286 | { | 286 | { |
287 | struct super_block *sb = dentry->d_sb; | ||
288 | |||
287 | lock_kernel(); | 289 | lock_kernel(); |
288 | 290 | ||
289 | buf->f_type = sb->s_magic; | 291 | buf->f_type = sb->s_magic; |
@@ -561,10 +563,11 @@ static void destroy_inodecache(void) | |||
561 | "qnx4_inode_cache: not all structures were freed\n"); | 563 | "qnx4_inode_cache: not all structures were freed\n"); |
562 | } | 564 | } |
563 | 565 | ||
564 | static struct super_block *qnx4_get_sb(struct file_system_type *fs_type, | 566 | static int qnx4_get_sb(struct file_system_type *fs_type, |
565 | int flags, const char *dev_name, void *data) | 567 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
566 | { | 568 | { |
567 | return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super); | 569 | return get_sb_bdev(fs_type, flags, dev_name, data, qnx4_fill_super, |
570 | mnt); | ||
568 | } | 571 | } |
569 | 572 | ||
570 | static struct file_system_type qnx4_fs_type = { | 573 | static struct file_system_type qnx4_fs_type = { |
diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index 14bd2246fb6d..b9677335cc8d 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c | |||
@@ -185,16 +185,17 @@ static int ramfs_fill_super(struct super_block * sb, void * data, int silent) | |||
185 | return 0; | 185 | return 0; |
186 | } | 186 | } |
187 | 187 | ||
188 | struct super_block *ramfs_get_sb(struct file_system_type *fs_type, | 188 | int ramfs_get_sb(struct file_system_type *fs_type, |
189 | int flags, const char *dev_name, void *data) | 189 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
190 | { | 190 | { |
191 | return get_sb_nodev(fs_type, flags, data, ramfs_fill_super); | 191 | return get_sb_nodev(fs_type, flags, data, ramfs_fill_super, mnt); |
192 | } | 192 | } |
193 | 193 | ||
194 | static struct super_block *rootfs_get_sb(struct file_system_type *fs_type, | 194 | static int rootfs_get_sb(struct file_system_type *fs_type, |
195 | int flags, const char *dev_name, void *data) | 195 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
196 | { | 196 | { |
197 | return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super); | 197 | return get_sb_nodev(fs_type, flags|MS_NOUSER, data, ramfs_fill_super, |
198 | mnt); | ||
198 | } | 199 | } |
199 | 200 | ||
200 | static struct file_system_type ramfs_fs_type = { | 201 | static struct file_system_type ramfs_fs_type = { |
diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index cae2abbc0c71..00f1321e9209 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c | |||
@@ -60,7 +60,7 @@ static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | static int reiserfs_remount(struct super_block *s, int *flags, char *data); | 62 | static int reiserfs_remount(struct super_block *s, int *flags, char *data); |
63 | static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf); | 63 | static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf); |
64 | 64 | ||
65 | static int reiserfs_sync_fs(struct super_block *s, int wait) | 65 | static int reiserfs_sync_fs(struct super_block *s, int wait) |
66 | { | 66 | { |
@@ -1938,15 +1938,15 @@ static int reiserfs_fill_super(struct super_block *s, void *data, int silent) | |||
1938 | return errval; | 1938 | return errval; |
1939 | } | 1939 | } |
1940 | 1940 | ||
1941 | static int reiserfs_statfs(struct super_block *s, struct kstatfs *buf) | 1941 | static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
1942 | { | 1942 | { |
1943 | struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); | 1943 | struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb); |
1944 | 1944 | ||
1945 | buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize)); | 1945 | buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize)); |
1946 | buf->f_bfree = sb_free_blocks(rs); | 1946 | buf->f_bfree = sb_free_blocks(rs); |
1947 | buf->f_bavail = buf->f_bfree; | 1947 | buf->f_bavail = buf->f_bfree; |
1948 | buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1; | 1948 | buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1; |
1949 | buf->f_bsize = s->s_blocksize; | 1949 | buf->f_bsize = dentry->d_sb->s_blocksize; |
1950 | /* changed to accommodate gcc folks. */ | 1950 | /* changed to accommodate gcc folks. */ |
1951 | buf->f_type = REISERFS_SUPER_MAGIC; | 1951 | buf->f_type = REISERFS_SUPER_MAGIC; |
1952 | return 0; | 1952 | return 0; |
@@ -2249,11 +2249,12 @@ static ssize_t reiserfs_quota_write(struct super_block *sb, int type, | |||
2249 | 2249 | ||
2250 | #endif | 2250 | #endif |
2251 | 2251 | ||
2252 | static struct super_block *get_super_block(struct file_system_type *fs_type, | 2252 | static int get_super_block(struct file_system_type *fs_type, |
2253 | int flags, const char *dev_name, | 2253 | int flags, const char *dev_name, |
2254 | void *data) | 2254 | void *data, struct vfsmount *mnt) |
2255 | { | 2255 | { |
2256 | return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super); | 2256 | return get_sb_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super, |
2257 | mnt); | ||
2257 | } | 2258 | } |
2258 | 2259 | ||
2259 | static int __init init_reiserfs_fs(void) | 2260 | static int __init init_reiserfs_fs(void) |
diff --git a/fs/reiserfs/xattr.c b/fs/reiserfs/xattr.c index ffb79c48c5bf..39fedaa88a0c 100644 --- a/fs/reiserfs/xattr.c +++ b/fs/reiserfs/xattr.c | |||
@@ -452,8 +452,7 @@ static struct page *reiserfs_get_page(struct inode *dir, unsigned long n) | |||
452 | /* We can deadlock if we try to free dentries, | 452 | /* We can deadlock if we try to free dentries, |
453 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ | 453 | and an unlink/rmdir has just occured - GFP_NOFS avoids this */ |
454 | mapping_set_gfp_mask(mapping, GFP_NOFS); | 454 | mapping_set_gfp_mask(mapping, GFP_NOFS); |
455 | page = read_cache_page(mapping, n, | 455 | page = read_mapping_page(mapping, n, NULL); |
456 | (filler_t *) mapping->a_ops->readpage, NULL); | ||
457 | if (!IS_ERR(page)) { | 456 | if (!IS_ERR(page)) { |
458 | wait_on_page_locked(page); | 457 | wait_on_page_locked(page); |
459 | kmap(page); | 458 | kmap(page); |
diff --git a/fs/romfs/inode.c b/fs/romfs/inode.c index 9b9eda7b335c..283fbc6b8eea 100644 --- a/fs/romfs/inode.c +++ b/fs/romfs/inode.c | |||
@@ -179,12 +179,12 @@ outnobh: | |||
179 | /* That's simple too. */ | 179 | /* That's simple too. */ |
180 | 180 | ||
181 | static int | 181 | static int |
182 | romfs_statfs(struct super_block *sb, struct kstatfs *buf) | 182 | romfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
183 | { | 183 | { |
184 | buf->f_type = ROMFS_MAGIC; | 184 | buf->f_type = ROMFS_MAGIC; |
185 | buf->f_bsize = ROMBSIZE; | 185 | buf->f_bsize = ROMBSIZE; |
186 | buf->f_bfree = buf->f_bavail = buf->f_ffree; | 186 | buf->f_bfree = buf->f_bavail = buf->f_ffree; |
187 | buf->f_blocks = (romfs_maxsize(sb)+ROMBSIZE-1)>>ROMBSBITS; | 187 | buf->f_blocks = (romfs_maxsize(dentry->d_sb)+ROMBSIZE-1)>>ROMBSBITS; |
188 | buf->f_namelen = ROMFS_MAXFN; | 188 | buf->f_namelen = ROMFS_MAXFN; |
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
@@ -607,10 +607,11 @@ static struct super_operations romfs_ops = { | |||
607 | .remount_fs = romfs_remount, | 607 | .remount_fs = romfs_remount, |
608 | }; | 608 | }; |
609 | 609 | ||
610 | static struct super_block *romfs_get_sb(struct file_system_type *fs_type, | 610 | static int romfs_get_sb(struct file_system_type *fs_type, |
611 | int flags, const char *dev_name, void *data) | 611 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
612 | { | 612 | { |
613 | return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super); | 613 | return get_sb_bdev(fs_type, flags, dev_name, data, romfs_fill_super, |
614 | mnt); | ||
614 | } | 615 | } |
615 | 616 | ||
616 | static struct file_system_type romfs_fs_type = { | 617 | static struct file_system_type romfs_fs_type = { |
diff --git a/fs/select.c b/fs/select.c index a8109baa5e46..9c4f0f2604f1 100644 --- a/fs/select.c +++ b/fs/select.c | |||
@@ -546,37 +546,38 @@ struct poll_list { | |||
546 | 546 | ||
547 | #define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) | 547 | #define POLLFD_PER_PAGE ((PAGE_SIZE-sizeof(struct poll_list)) / sizeof(struct pollfd)) |
548 | 548 | ||
549 | static void do_pollfd(unsigned int num, struct pollfd * fdpage, | 549 | /* |
550 | poll_table ** pwait, int *count) | 550 | * Fish for pollable events on the pollfd->fd file descriptor. We're only |
551 | * interested in events matching the pollfd->events mask, and the result | ||
552 | * matching that mask is both recorded in pollfd->revents and returned. The | ||
553 | * pwait poll_table will be used by the fd-provided poll handler for waiting, | ||
554 | * if non-NULL. | ||
555 | */ | ||
556 | static inline unsigned int do_pollfd(struct pollfd *pollfd, poll_table *pwait) | ||
551 | { | 557 | { |
552 | int i; | 558 | unsigned int mask; |
553 | 559 | int fd; | |
554 | for (i = 0; i < num; i++) { | 560 | |
555 | int fd; | 561 | mask = 0; |
556 | unsigned int mask; | 562 | fd = pollfd->fd; |
557 | struct pollfd *fdp; | 563 | if (fd >= 0) { |
558 | 564 | int fput_needed; | |
559 | mask = 0; | 565 | struct file * file; |
560 | fdp = fdpage+i; | 566 | |
561 | fd = fdp->fd; | 567 | file = fget_light(fd, &fput_needed); |
562 | if (fd >= 0) { | 568 | mask = POLLNVAL; |
563 | int fput_needed; | 569 | if (file != NULL) { |
564 | struct file * file = fget_light(fd, &fput_needed); | 570 | mask = DEFAULT_POLLMASK; |
565 | mask = POLLNVAL; | 571 | if (file->f_op && file->f_op->poll) |
566 | if (file != NULL) { | 572 | mask = file->f_op->poll(file, pwait); |
567 | mask = DEFAULT_POLLMASK; | 573 | /* Mask out unneeded events. */ |
568 | if (file->f_op && file->f_op->poll) | 574 | mask &= pollfd->events | POLLERR | POLLHUP; |
569 | mask = file->f_op->poll(file, *pwait); | 575 | fput_light(file, fput_needed); |
570 | mask &= fdp->events | POLLERR | POLLHUP; | ||
571 | fput_light(file, fput_needed); | ||
572 | } | ||
573 | if (mask) { | ||
574 | *pwait = NULL; | ||
575 | (*count)++; | ||
576 | } | ||
577 | } | 576 | } |
578 | fdp->revents = mask; | ||
579 | } | 577 | } |
578 | pollfd->revents = mask; | ||
579 | |||
580 | return mask; | ||
580 | } | 581 | } |
581 | 582 | ||
582 | static int do_poll(unsigned int nfds, struct poll_list *list, | 583 | static int do_poll(unsigned int nfds, struct poll_list *list, |
@@ -594,11 +595,29 @@ static int do_poll(unsigned int nfds, struct poll_list *list, | |||
594 | long __timeout; | 595 | long __timeout; |
595 | 596 | ||
596 | set_current_state(TASK_INTERRUPTIBLE); | 597 | set_current_state(TASK_INTERRUPTIBLE); |
597 | walk = list; | 598 | for (walk = list; walk != NULL; walk = walk->next) { |
598 | while(walk != NULL) { | 599 | struct pollfd * pfd, * pfd_end; |
599 | do_pollfd( walk->len, walk->entries, &pt, &count); | 600 | |
600 | walk = walk->next; | 601 | pfd = walk->entries; |
602 | pfd_end = pfd + walk->len; | ||
603 | for (; pfd != pfd_end; pfd++) { | ||
604 | /* | ||
605 | * Fish for events. If we found one, record it | ||
606 | * and kill the poll_table, so we don't | ||
607 | * needlessly register any other waiters after | ||
608 | * this. They'll get immediately deregistered | ||
609 | * when we break out and return. | ||
610 | */ | ||
611 | if (do_pollfd(pfd, pt)) { | ||
612 | count++; | ||
613 | pt = NULL; | ||
614 | } | ||
615 | } | ||
601 | } | 616 | } |
617 | /* | ||
618 | * All waiters have already been registered, so don't provide | ||
619 | * a poll_table to them on the next loop iteration. | ||
620 | */ | ||
602 | pt = NULL; | 621 | pt = NULL; |
603 | if (count || !*timeout || signal_pending(current)) | 622 | if (count || !*timeout || signal_pending(current)) |
604 | break; | 623 | break; |
diff --git a/fs/smbfs/inode.c b/fs/smbfs/inode.c index fdeabc0a34f7..506ff87c1d4b 100644 --- a/fs/smbfs/inode.c +++ b/fs/smbfs/inode.c | |||
@@ -48,7 +48,7 @@ | |||
48 | 48 | ||
49 | static void smb_delete_inode(struct inode *); | 49 | static void smb_delete_inode(struct inode *); |
50 | static void smb_put_super(struct super_block *); | 50 | static void smb_put_super(struct super_block *); |
51 | static int smb_statfs(struct super_block *, struct kstatfs *); | 51 | static int smb_statfs(struct dentry *, struct kstatfs *); |
52 | static int smb_show_options(struct seq_file *, struct vfsmount *); | 52 | static int smb_show_options(struct seq_file *, struct vfsmount *); |
53 | 53 | ||
54 | static kmem_cache_t *smb_inode_cachep; | 54 | static kmem_cache_t *smb_inode_cachep; |
@@ -641,13 +641,13 @@ out_no_server: | |||
641 | } | 641 | } |
642 | 642 | ||
643 | static int | 643 | static int |
644 | smb_statfs(struct super_block *sb, struct kstatfs *buf) | 644 | smb_statfs(struct dentry *dentry, struct kstatfs *buf) |
645 | { | 645 | { |
646 | int result; | 646 | int result; |
647 | 647 | ||
648 | lock_kernel(); | 648 | lock_kernel(); |
649 | 649 | ||
650 | result = smb_proc_dskattr(sb, buf); | 650 | result = smb_proc_dskattr(dentry, buf); |
651 | 651 | ||
652 | unlock_kernel(); | 652 | unlock_kernel(); |
653 | 653 | ||
@@ -782,10 +782,10 @@ out: | |||
782 | return error; | 782 | return error; |
783 | } | 783 | } |
784 | 784 | ||
785 | static struct super_block *smb_get_sb(struct file_system_type *fs_type, | 785 | static int smb_get_sb(struct file_system_type *fs_type, |
786 | int flags, const char *dev_name, void *data) | 786 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
787 | { | 787 | { |
788 | return get_sb_nodev(fs_type, flags, data, smb_fill_super); | 788 | return get_sb_nodev(fs_type, flags, data, smb_fill_super, mnt); |
789 | } | 789 | } |
790 | 790 | ||
791 | static struct file_system_type smb_fs_type = { | 791 | static struct file_system_type smb_fs_type = { |
diff --git a/fs/smbfs/proc.c b/fs/smbfs/proc.c index b1b878b81730..c3495059889d 100644 --- a/fs/smbfs/proc.c +++ b/fs/smbfs/proc.c | |||
@@ -3226,9 +3226,9 @@ smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr) | |||
3226 | } | 3226 | } |
3227 | 3227 | ||
3228 | int | 3228 | int |
3229 | smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr) | 3229 | smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr) |
3230 | { | 3230 | { |
3231 | struct smb_sb_info *server = SMB_SB(sb); | 3231 | struct smb_sb_info *server = SMB_SB(dentry->d_sb); |
3232 | int result; | 3232 | int result; |
3233 | char *p; | 3233 | char *p; |
3234 | long unit; | 3234 | long unit; |
diff --git a/fs/smbfs/proto.h b/fs/smbfs/proto.h index 47664597e6b1..972ed7dad388 100644 --- a/fs/smbfs/proto.h +++ b/fs/smbfs/proto.h | |||
@@ -29,7 +29,7 @@ extern int smb_proc_getattr(struct dentry *dir, struct smb_fattr *fattr); | |||
29 | extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr); | 29 | extern int smb_proc_setattr(struct dentry *dir, struct smb_fattr *fattr); |
30 | extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor); | 30 | extern int smb_proc_setattr_unix(struct dentry *d, struct iattr *attr, unsigned int major, unsigned int minor); |
31 | extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr); | 31 | extern int smb_proc_settime(struct dentry *dentry, struct smb_fattr *fattr); |
32 | extern int smb_proc_dskattr(struct super_block *sb, struct kstatfs *attr); | 32 | extern int smb_proc_dskattr(struct dentry *dentry, struct kstatfs *attr); |
33 | extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len); | 33 | extern int smb_proc_read_link(struct smb_sb_info *server, struct dentry *d, char *buffer, int len); |
34 | extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); | 34 | extern int smb_proc_symlink(struct smb_sb_info *server, struct dentry *d, const char *oldpath); |
35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); | 35 | extern int smb_proc_link(struct smb_sb_info *server, struct dentry *dentry, struct dentry *new_dentry); |
diff --git a/fs/splice.c b/fs/splice.c index a285fd746dc0..05fd2787be98 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
@@ -55,31 +55,43 @@ static int page_cache_pipe_buf_steal(struct pipe_inode_info *pipe, | |||
55 | struct pipe_buffer *buf) | 55 | struct pipe_buffer *buf) |
56 | { | 56 | { |
57 | struct page *page = buf->page; | 57 | struct page *page = buf->page; |
58 | struct address_space *mapping = page_mapping(page); | 58 | struct address_space *mapping; |
59 | 59 | ||
60 | lock_page(page); | 60 | lock_page(page); |
61 | 61 | ||
62 | WARN_ON(!PageUptodate(page)); | 62 | mapping = page_mapping(page); |
63 | if (mapping) { | ||
64 | WARN_ON(!PageUptodate(page)); | ||
63 | 65 | ||
64 | /* | 66 | /* |
65 | * At least for ext2 with nobh option, we need to wait on writeback | 67 | * At least for ext2 with nobh option, we need to wait on |
66 | * completing on this page, since we'll remove it from the pagecache. | 68 | * writeback completing on this page, since we'll remove it |
67 | * Otherwise truncate wont wait on the page, allowing the disk | 69 | * from the pagecache. Otherwise truncate wont wait on the |
68 | * blocks to be reused by someone else before we actually wrote our | 70 | * page, allowing the disk blocks to be reused by someone else |
69 | * data to them. fs corruption ensues. | 71 | * before we actually wrote our data to them. fs corruption |
70 | */ | 72 | * ensues. |
71 | wait_on_page_writeback(page); | 73 | */ |
74 | wait_on_page_writeback(page); | ||
72 | 75 | ||
73 | if (PagePrivate(page)) | 76 | if (PagePrivate(page)) |
74 | try_to_release_page(page, mapping_gfp_mask(mapping)); | 77 | try_to_release_page(page, mapping_gfp_mask(mapping)); |
75 | 78 | ||
76 | if (!remove_mapping(mapping, page)) { | 79 | /* |
77 | unlock_page(page); | 80 | * If we succeeded in removing the mapping, set LRU flag |
78 | return 1; | 81 | * and return good. |
82 | */ | ||
83 | if (remove_mapping(mapping, page)) { | ||
84 | buf->flags |= PIPE_BUF_FLAG_LRU; | ||
85 | return 0; | ||
86 | } | ||
79 | } | 87 | } |
80 | 88 | ||
81 | buf->flags |= PIPE_BUF_FLAG_LRU; | 89 | /* |
82 | return 0; | 90 | * Raced with truncate or failed to remove page from current |
91 | * address space, unlock and return failure. | ||
92 | */ | ||
93 | unlock_page(page); | ||
94 | return 1; | ||
83 | } | 95 | } |
84 | 96 | ||
85 | static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, | 97 | static void page_cache_pipe_buf_release(struct pipe_inode_info *pipe, |
diff --git a/fs/super.c b/fs/super.c index a66f66bb8049..057b5325b7ef 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -231,7 +231,7 @@ void generic_shutdown_super(struct super_block *sb) | |||
231 | if (root) { | 231 | if (root) { |
232 | sb->s_root = NULL; | 232 | sb->s_root = NULL; |
233 | shrink_dcache_parent(root); | 233 | shrink_dcache_parent(root); |
234 | shrink_dcache_anon(&sb->s_anon); | 234 | shrink_dcache_sb(sb); |
235 | dput(root); | 235 | dput(root); |
236 | fsync_super(sb); | 236 | fsync_super(sb); |
237 | lock_super(sb); | 237 | lock_super(sb); |
@@ -486,7 +486,7 @@ asmlinkage long sys_ustat(unsigned dev, struct ustat __user * ubuf) | |||
486 | s = user_get_super(new_decode_dev(dev)); | 486 | s = user_get_super(new_decode_dev(dev)); |
487 | if (s == NULL) | 487 | if (s == NULL) |
488 | goto out; | 488 | goto out; |
489 | err = vfs_statfs(s, &sbuf); | 489 | err = vfs_statfs(s->s_root, &sbuf); |
490 | drop_super(s); | 490 | drop_super(s); |
491 | if (err) | 491 | if (err) |
492 | goto out; | 492 | goto out; |
@@ -676,9 +676,10 @@ static void bdev_uevent(struct block_device *bdev, enum kobject_action action) | |||
676 | } | 676 | } |
677 | } | 677 | } |
678 | 678 | ||
679 | struct super_block *get_sb_bdev(struct file_system_type *fs_type, | 679 | int get_sb_bdev(struct file_system_type *fs_type, |
680 | int flags, const char *dev_name, void *data, | 680 | int flags, const char *dev_name, void *data, |
681 | int (*fill_super)(struct super_block *, void *, int)) | 681 | int (*fill_super)(struct super_block *, void *, int), |
682 | struct vfsmount *mnt) | ||
682 | { | 683 | { |
683 | struct block_device *bdev; | 684 | struct block_device *bdev; |
684 | struct super_block *s; | 685 | struct super_block *s; |
@@ -686,7 +687,7 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
686 | 687 | ||
687 | bdev = open_bdev_excl(dev_name, flags, fs_type); | 688 | bdev = open_bdev_excl(dev_name, flags, fs_type); |
688 | if (IS_ERR(bdev)) | 689 | if (IS_ERR(bdev)) |
689 | return (struct super_block *)bdev; | 690 | return PTR_ERR(bdev); |
690 | 691 | ||
691 | /* | 692 | /* |
692 | * once the super is inserted into the list by sget, s_umount | 693 | * once the super is inserted into the list by sget, s_umount |
@@ -697,15 +698,17 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
697 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); | 698 | s = sget(fs_type, test_bdev_super, set_bdev_super, bdev); |
698 | mutex_unlock(&bdev->bd_mount_mutex); | 699 | mutex_unlock(&bdev->bd_mount_mutex); |
699 | if (IS_ERR(s)) | 700 | if (IS_ERR(s)) |
700 | goto out; | 701 | goto error_s; |
701 | 702 | ||
702 | if (s->s_root) { | 703 | if (s->s_root) { |
703 | if ((flags ^ s->s_flags) & MS_RDONLY) { | 704 | if ((flags ^ s->s_flags) & MS_RDONLY) { |
704 | up_write(&s->s_umount); | 705 | up_write(&s->s_umount); |
705 | deactivate_super(s); | 706 | deactivate_super(s); |
706 | s = ERR_PTR(-EBUSY); | 707 | error = -EBUSY; |
708 | goto error_bdev; | ||
707 | } | 709 | } |
708 | goto out; | 710 | |
711 | close_bdev_excl(bdev); | ||
709 | } else { | 712 | } else { |
710 | char b[BDEVNAME_SIZE]; | 713 | char b[BDEVNAME_SIZE]; |
711 | 714 | ||
@@ -716,18 +719,21 @@ struct super_block *get_sb_bdev(struct file_system_type *fs_type, | |||
716 | if (error) { | 719 | if (error) { |
717 | up_write(&s->s_umount); | 720 | up_write(&s->s_umount); |
718 | deactivate_super(s); | 721 | deactivate_super(s); |
719 | s = ERR_PTR(error); | 722 | goto error; |
720 | } else { | ||
721 | s->s_flags |= MS_ACTIVE; | ||
722 | bdev_uevent(bdev, KOBJ_MOUNT); | ||
723 | } | 723 | } |
724 | |||
725 | s->s_flags |= MS_ACTIVE; | ||
726 | bdev_uevent(bdev, KOBJ_MOUNT); | ||
724 | } | 727 | } |
725 | 728 | ||
726 | return s; | 729 | return simple_set_mnt(mnt, s); |
727 | 730 | ||
728 | out: | 731 | error_s: |
732 | error = PTR_ERR(s); | ||
733 | error_bdev: | ||
729 | close_bdev_excl(bdev); | 734 | close_bdev_excl(bdev); |
730 | return s; | 735 | error: |
736 | return error; | ||
731 | } | 737 | } |
732 | 738 | ||
733 | EXPORT_SYMBOL(get_sb_bdev); | 739 | EXPORT_SYMBOL(get_sb_bdev); |
@@ -744,15 +750,16 @@ void kill_block_super(struct super_block *sb) | |||
744 | 750 | ||
745 | EXPORT_SYMBOL(kill_block_super); | 751 | EXPORT_SYMBOL(kill_block_super); |
746 | 752 | ||
747 | struct super_block *get_sb_nodev(struct file_system_type *fs_type, | 753 | int get_sb_nodev(struct file_system_type *fs_type, |
748 | int flags, void *data, | 754 | int flags, void *data, |
749 | int (*fill_super)(struct super_block *, void *, int)) | 755 | int (*fill_super)(struct super_block *, void *, int), |
756 | struct vfsmount *mnt) | ||
750 | { | 757 | { |
751 | int error; | 758 | int error; |
752 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); | 759 | struct super_block *s = sget(fs_type, NULL, set_anon_super, NULL); |
753 | 760 | ||
754 | if (IS_ERR(s)) | 761 | if (IS_ERR(s)) |
755 | return s; | 762 | return PTR_ERR(s); |
756 | 763 | ||
757 | s->s_flags = flags; | 764 | s->s_flags = flags; |
758 | 765 | ||
@@ -760,10 +767,10 @@ struct super_block *get_sb_nodev(struct file_system_type *fs_type, | |||
760 | if (error) { | 767 | if (error) { |
761 | up_write(&s->s_umount); | 768 | up_write(&s->s_umount); |
762 | deactivate_super(s); | 769 | deactivate_super(s); |
763 | return ERR_PTR(error); | 770 | return error; |
764 | } | 771 | } |
765 | s->s_flags |= MS_ACTIVE; | 772 | s->s_flags |= MS_ACTIVE; |
766 | return s; | 773 | return simple_set_mnt(mnt, s); |
767 | } | 774 | } |
768 | 775 | ||
769 | EXPORT_SYMBOL(get_sb_nodev); | 776 | EXPORT_SYMBOL(get_sb_nodev); |
@@ -773,94 +780,102 @@ static int compare_single(struct super_block *s, void *p) | |||
773 | return 1; | 780 | return 1; |
774 | } | 781 | } |
775 | 782 | ||
776 | struct super_block *get_sb_single(struct file_system_type *fs_type, | 783 | int get_sb_single(struct file_system_type *fs_type, |
777 | int flags, void *data, | 784 | int flags, void *data, |
778 | int (*fill_super)(struct super_block *, void *, int)) | 785 | int (*fill_super)(struct super_block *, void *, int), |
786 | struct vfsmount *mnt) | ||
779 | { | 787 | { |
780 | struct super_block *s; | 788 | struct super_block *s; |
781 | int error; | 789 | int error; |
782 | 790 | ||
783 | s = sget(fs_type, compare_single, set_anon_super, NULL); | 791 | s = sget(fs_type, compare_single, set_anon_super, NULL); |
784 | if (IS_ERR(s)) | 792 | if (IS_ERR(s)) |
785 | return s; | 793 | return PTR_ERR(s); |
786 | if (!s->s_root) { | 794 | if (!s->s_root) { |
787 | s->s_flags = flags; | 795 | s->s_flags = flags; |
788 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); | 796 | error = fill_super(s, data, flags & MS_SILENT ? 1 : 0); |
789 | if (error) { | 797 | if (error) { |
790 | up_write(&s->s_umount); | 798 | up_write(&s->s_umount); |
791 | deactivate_super(s); | 799 | deactivate_super(s); |
792 | return ERR_PTR(error); | 800 | return error; |
793 | } | 801 | } |
794 | s->s_flags |= MS_ACTIVE; | 802 | s->s_flags |= MS_ACTIVE; |
795 | } | 803 | } |
796 | do_remount_sb(s, flags, data, 0); | 804 | do_remount_sb(s, flags, data, 0); |
797 | return s; | 805 | return simple_set_mnt(mnt, s); |
798 | } | 806 | } |
799 | 807 | ||
800 | EXPORT_SYMBOL(get_sb_single); | 808 | EXPORT_SYMBOL(get_sb_single); |
801 | 809 | ||
802 | struct vfsmount * | 810 | struct vfsmount * |
803 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | 811 | vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void *data) |
804 | { | 812 | { |
805 | struct file_system_type *type = get_fs_type(fstype); | ||
806 | struct super_block *sb = ERR_PTR(-ENOMEM); | ||
807 | struct vfsmount *mnt; | 813 | struct vfsmount *mnt; |
808 | int error; | ||
809 | char *secdata = NULL; | 814 | char *secdata = NULL; |
815 | int error; | ||
810 | 816 | ||
811 | if (!type) | 817 | if (!type) |
812 | return ERR_PTR(-ENODEV); | 818 | return ERR_PTR(-ENODEV); |
813 | 819 | ||
820 | error = -ENOMEM; | ||
814 | mnt = alloc_vfsmnt(name); | 821 | mnt = alloc_vfsmnt(name); |
815 | if (!mnt) | 822 | if (!mnt) |
816 | goto out; | 823 | goto out; |
817 | 824 | ||
818 | if (data) { | 825 | if (data) { |
819 | secdata = alloc_secdata(); | 826 | secdata = alloc_secdata(); |
820 | if (!secdata) { | 827 | if (!secdata) |
821 | sb = ERR_PTR(-ENOMEM); | ||
822 | goto out_mnt; | 828 | goto out_mnt; |
823 | } | ||
824 | 829 | ||
825 | error = security_sb_copy_data(type, data, secdata); | 830 | error = security_sb_copy_data(type, data, secdata); |
826 | if (error) { | 831 | if (error) |
827 | sb = ERR_PTR(error); | ||
828 | goto out_free_secdata; | 832 | goto out_free_secdata; |
829 | } | ||
830 | } | 833 | } |
831 | 834 | ||
832 | sb = type->get_sb(type, flags, name, data); | 835 | error = type->get_sb(type, flags, name, data, mnt); |
833 | if (IS_ERR(sb)) | 836 | if (error < 0) |
834 | goto out_free_secdata; | 837 | goto out_free_secdata; |
835 | error = security_sb_kern_mount(sb, secdata); | 838 | |
839 | error = security_sb_kern_mount(mnt->mnt_sb, secdata); | ||
836 | if (error) | 840 | if (error) |
837 | goto out_sb; | 841 | goto out_sb; |
838 | mnt->mnt_sb = sb; | 842 | |
839 | mnt->mnt_root = dget(sb->s_root); | 843 | mnt->mnt_mountpoint = mnt->mnt_root; |
840 | mnt->mnt_mountpoint = sb->s_root; | ||
841 | mnt->mnt_parent = mnt; | 844 | mnt->mnt_parent = mnt; |
842 | up_write(&sb->s_umount); | 845 | up_write(&mnt->mnt_sb->s_umount); |
843 | free_secdata(secdata); | 846 | free_secdata(secdata); |
844 | put_filesystem(type); | ||
845 | return mnt; | 847 | return mnt; |
846 | out_sb: | 848 | out_sb: |
847 | up_write(&sb->s_umount); | 849 | dput(mnt->mnt_root); |
848 | deactivate_super(sb); | 850 | up_write(&mnt->mnt_sb->s_umount); |
849 | sb = ERR_PTR(error); | 851 | deactivate_super(mnt->mnt_sb); |
850 | out_free_secdata: | 852 | out_free_secdata: |
851 | free_secdata(secdata); | 853 | free_secdata(secdata); |
852 | out_mnt: | 854 | out_mnt: |
853 | free_vfsmnt(mnt); | 855 | free_vfsmnt(mnt); |
854 | out: | 856 | out: |
857 | return ERR_PTR(error); | ||
858 | } | ||
859 | |||
860 | EXPORT_SYMBOL_GPL(vfs_kern_mount); | ||
861 | |||
862 | struct vfsmount * | ||
863 | do_kern_mount(const char *fstype, int flags, const char *name, void *data) | ||
864 | { | ||
865 | struct file_system_type *type = get_fs_type(fstype); | ||
866 | struct vfsmount *mnt; | ||
867 | if (!type) | ||
868 | return ERR_PTR(-ENODEV); | ||
869 | mnt = vfs_kern_mount(type, flags, name, data); | ||
855 | put_filesystem(type); | 870 | put_filesystem(type); |
856 | return (struct vfsmount *)sb; | 871 | return mnt; |
857 | } | 872 | } |
858 | 873 | ||
859 | EXPORT_SYMBOL_GPL(do_kern_mount); | 874 | EXPORT_SYMBOL_GPL(do_kern_mount); |
860 | 875 | ||
861 | struct vfsmount *kern_mount(struct file_system_type *type) | 876 | struct vfsmount *kern_mount(struct file_system_type *type) |
862 | { | 877 | { |
863 | return do_kern_mount(type->name, 0, type->name, NULL); | 878 | return vfs_kern_mount(type, 0, type->name, NULL); |
864 | } | 879 | } |
865 | 880 | ||
866 | EXPORT_SYMBOL(kern_mount); | 881 | EXPORT_SYMBOL(kern_mount); |
@@ -100,7 +100,7 @@ asmlinkage long sys_sync_file_range(int fd, loff_t offset, loff_t nbytes, | |||
100 | } | 100 | } |
101 | 101 | ||
102 | if (nbytes == 0) | 102 | if (nbytes == 0) |
103 | endbyte = -1; | 103 | endbyte = LLONG_MAX; |
104 | else | 104 | else |
105 | endbyte--; /* inclusive */ | 105 | endbyte--; /* inclusive */ |
106 | 106 | ||
diff --git a/fs/sysfs/mount.c b/fs/sysfs/mount.c index f1117e885bd6..40190c489271 100644 --- a/fs/sysfs/mount.c +++ b/fs/sysfs/mount.c | |||
@@ -66,10 +66,10 @@ static int sysfs_fill_super(struct super_block *sb, void *data, int silent) | |||
66 | return 0; | 66 | return 0; |
67 | } | 67 | } |
68 | 68 | ||
69 | static struct super_block *sysfs_get_sb(struct file_system_type *fs_type, | 69 | static int sysfs_get_sb(struct file_system_type *fs_type, |
70 | int flags, const char *dev_name, void *data) | 70 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
71 | { | 71 | { |
72 | return get_sb_single(fs_type, flags, data, sysfs_fill_super); | 72 | return get_sb_single(fs_type, flags, data, sysfs_fill_super, mnt); |
73 | } | 73 | } |
74 | 74 | ||
75 | static struct file_system_type sysfs_fs_type = { | 75 | static struct file_system_type sysfs_fs_type = { |
diff --git a/fs/sysv/dir.c b/fs/sysv/dir.c index d7074341ee87..f2bef962d309 100644 --- a/fs/sysv/dir.c +++ b/fs/sysv/dir.c | |||
@@ -53,8 +53,7 @@ static int dir_commit_chunk(struct page *page, unsigned from, unsigned to) | |||
53 | static struct page * dir_get_page(struct inode *dir, unsigned long n) | 53 | static struct page * dir_get_page(struct inode *dir, unsigned long n) |
54 | { | 54 | { |
55 | struct address_space *mapping = dir->i_mapping; | 55 | struct address_space *mapping = dir->i_mapping; |
56 | struct page *page = read_cache_page(mapping, n, | 56 | struct page *page = read_mapping_page(mapping, n, NULL); |
57 | (filler_t*)mapping->a_ops->readpage, NULL); | ||
58 | if (!IS_ERR(page)) { | 57 | if (!IS_ERR(page)) { |
59 | wait_on_page_locked(page); | 58 | wait_on_page_locked(page); |
60 | kmap(page); | 59 | kmap(page); |
diff --git a/fs/sysv/inode.c b/fs/sysv/inode.c index 3ff89cc5833a..58b2d22142ba 100644 --- a/fs/sysv/inode.c +++ b/fs/sysv/inode.c | |||
@@ -85,8 +85,9 @@ static void sysv_put_super(struct super_block *sb) | |||
85 | kfree(sbi); | 85 | kfree(sbi); |
86 | } | 86 | } |
87 | 87 | ||
88 | static int sysv_statfs(struct super_block *sb, struct kstatfs *buf) | 88 | static int sysv_statfs(struct dentry *dentry, struct kstatfs *buf) |
89 | { | 89 | { |
90 | struct super_block *sb = dentry->d_sb; | ||
90 | struct sysv_sb_info *sbi = SYSV_SB(sb); | 91 | struct sysv_sb_info *sbi = SYSV_SB(sb); |
91 | 92 | ||
92 | buf->f_type = sb->s_magic; | 93 | buf->f_type = sb->s_magic; |
diff --git a/fs/sysv/super.c b/fs/sysv/super.c index e92b991e6dda..876639b93321 100644 --- a/fs/sysv/super.c +++ b/fs/sysv/super.c | |||
@@ -506,16 +506,17 @@ failed: | |||
506 | 506 | ||
507 | /* Every kernel module contains stuff like this. */ | 507 | /* Every kernel module contains stuff like this. */ |
508 | 508 | ||
509 | static struct super_block *sysv_get_sb(struct file_system_type *fs_type, | 509 | static int sysv_get_sb(struct file_system_type *fs_type, |
510 | int flags, const char *dev_name, void *data) | 510 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
511 | { | 511 | { |
512 | return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super); | 512 | return get_sb_bdev(fs_type, flags, dev_name, data, sysv_fill_super, |
513 | mnt); | ||
513 | } | 514 | } |
514 | 515 | ||
515 | static struct super_block *v7_get_sb(struct file_system_type *fs_type, | 516 | static int v7_get_sb(struct file_system_type *fs_type, |
516 | int flags, const char *dev_name, void *data) | 517 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
517 | { | 518 | { |
518 | return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super); | 519 | return get_sb_bdev(fs_type, flags, dev_name, data, v7_fill_super, mnt); |
519 | } | 520 | } |
520 | 521 | ||
521 | static struct file_system_type sysv_fs_type = { | 522 | static struct file_system_type sysv_fs_type = { |
diff --git a/fs/udf/super.c b/fs/udf/super.c index e45789fe38e8..44fe2cb0bbb2 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -91,13 +91,13 @@ static void udf_load_partdesc(struct super_block *, struct buffer_head *); | |||
91 | static void udf_open_lvid(struct super_block *); | 91 | static void udf_open_lvid(struct super_block *); |
92 | static void udf_close_lvid(struct super_block *); | 92 | static void udf_close_lvid(struct super_block *); |
93 | static unsigned int udf_count_free(struct super_block *); | 93 | static unsigned int udf_count_free(struct super_block *); |
94 | static int udf_statfs(struct super_block *, struct kstatfs *); | 94 | static int udf_statfs(struct dentry *, struct kstatfs *); |
95 | 95 | ||
96 | /* UDF filesystem type */ | 96 | /* UDF filesystem type */ |
97 | static struct super_block *udf_get_sb(struct file_system_type *fs_type, | 97 | static int udf_get_sb(struct file_system_type *fs_type, |
98 | int flags, const char *dev_name, void *data) | 98 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
99 | { | 99 | { |
100 | return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super); | 100 | return get_sb_bdev(fs_type, flags, dev_name, data, udf_fill_super, mnt); |
101 | } | 101 | } |
102 | 102 | ||
103 | static struct file_system_type udf_fstype = { | 103 | static struct file_system_type udf_fstype = { |
@@ -1779,8 +1779,10 @@ udf_put_super(struct super_block *sb) | |||
1779 | * Written, tested, and released. | 1779 | * Written, tested, and released. |
1780 | */ | 1780 | */ |
1781 | static int | 1781 | static int |
1782 | udf_statfs(struct super_block *sb, struct kstatfs *buf) | 1782 | udf_statfs(struct dentry *dentry, struct kstatfs *buf) |
1783 | { | 1783 | { |
1784 | struct super_block *sb = dentry->d_sb; | ||
1785 | |||
1784 | buf->f_type = UDF_SUPER_MAGIC; | 1786 | buf->f_type = UDF_SUPER_MAGIC; |
1785 | buf->f_bsize = sb->s_blocksize; | 1787 | buf->f_bsize = sb->s_blocksize; |
1786 | buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); | 1788 | buf->f_blocks = UDF_SB_PARTLEN(sb, UDF_SB_PARTITION(sb)); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index db98a4c71e63..fe5ab2aa2899 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
@@ -1113,8 +1113,9 @@ static int ufs_remount (struct super_block *sb, int *mount_flags, char *data) | |||
1113 | return 0; | 1113 | return 0; |
1114 | } | 1114 | } |
1115 | 1115 | ||
1116 | static int ufs_statfs (struct super_block *sb, struct kstatfs *buf) | 1116 | static int ufs_statfs (struct dentry *dentry, struct kstatfs *buf) |
1117 | { | 1117 | { |
1118 | struct super_block *sb = dentry->d_sb; | ||
1118 | struct ufs_sb_private_info * uspi; | 1119 | struct ufs_sb_private_info * uspi; |
1119 | struct ufs_super_block_first * usb1; | 1120 | struct ufs_super_block_first * usb1; |
1120 | struct ufs_super_block * usb; | 1121 | struct ufs_super_block * usb; |
@@ -1311,10 +1312,10 @@ out: | |||
1311 | 1312 | ||
1312 | #endif | 1313 | #endif |
1313 | 1314 | ||
1314 | static struct super_block *ufs_get_sb(struct file_system_type *fs_type, | 1315 | static int ufs_get_sb(struct file_system_type *fs_type, |
1315 | int flags, const char *dev_name, void *data) | 1316 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
1316 | { | 1317 | { |
1317 | return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super); | 1318 | return get_sb_bdev(fs_type, flags, dev_name, data, ufs_fill_super, mnt); |
1318 | } | 1319 | } |
1319 | 1320 | ||
1320 | static struct file_system_type ufs_fs_type = { | 1321 | static struct file_system_type ufs_fs_type = { |
diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index a56cec3be5f0..9a8f48bae956 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c | |||
@@ -1023,11 +1023,12 @@ static int vfat_fill_super(struct super_block *sb, void *data, int silent) | |||
1023 | return 0; | 1023 | return 0; |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static struct super_block *vfat_get_sb(struct file_system_type *fs_type, | 1026 | static int vfat_get_sb(struct file_system_type *fs_type, |
1027 | int flags, const char *dev_name, | 1027 | int flags, const char *dev_name, |
1028 | void *data) | 1028 | void *data, struct vfsmount *mnt) |
1029 | { | 1029 | { |
1030 | return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super); | 1030 | return get_sb_bdev(fs_type, flags, dev_name, data, vfat_fill_super, |
1031 | mnt); | ||
1031 | } | 1032 | } |
1032 | 1033 | ||
1033 | static struct file_system_type vfat_fs_type = { | 1034 | static struct file_system_type vfat_fs_type = { |
diff --git a/fs/xattr.c b/fs/xattr.c index e416190f5e9c..c32f15b5f60f 100644 --- a/fs/xattr.c +++ b/fs/xattr.c | |||
@@ -242,7 +242,7 @@ sys_fsetxattr(int fd, char __user *name, void __user *value, | |||
242 | if (!f) | 242 | if (!f) |
243 | return error; | 243 | return error; |
244 | dentry = f->f_dentry; | 244 | dentry = f->f_dentry; |
245 | audit_inode(NULL, dentry->d_inode, 0); | 245 | audit_inode(NULL, dentry->d_inode); |
246 | error = setxattr(dentry, name, value, size, flags); | 246 | error = setxattr(dentry, name, value, size, flags); |
247 | fput(f); | 247 | fput(f); |
248 | return error; | 248 | return error; |
@@ -469,7 +469,7 @@ sys_fremovexattr(int fd, char __user *name) | |||
469 | if (!f) | 469 | if (!f) |
470 | return error; | 470 | return error; |
471 | dentry = f->f_dentry; | 471 | dentry = f->f_dentry; |
472 | audit_inode(NULL, dentry->d_inode, 0); | 472 | audit_inode(NULL, dentry->d_inode); |
473 | error = removexattr(dentry, name); | 473 | error = removexattr(dentry, name); |
474 | fput(f); | 474 | fput(f); |
475 | return error; | 475 | return error; |
diff --git a/fs/xfs/Kconfig b/fs/xfs/Kconfig index bac27d66151d..26b364c9d62c 100644 --- a/fs/xfs/Kconfig +++ b/fs/xfs/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | config XFS_FS | 1 | config XFS_FS |
2 | tristate "XFS filesystem support" | 2 | tristate "XFS filesystem support" |
3 | select EXPORTFS if NFSD!=n | ||
4 | help | 3 | help |
5 | XFS is a high performance journaling filesystem which originated | 4 | XFS is a high performance journaling filesystem which originated |
6 | on the SGI IRIX platform. It is completely multi-threaded, can | 5 | on the SGI IRIX platform. It is completely multi-threaded, can |
@@ -18,11 +17,6 @@ config XFS_FS | |||
18 | system of your root partition is compiled as a module, you'll need | 17 | system of your root partition is compiled as a module, you'll need |
19 | to use an initial ramdisk (initrd) to boot. | 18 | to use an initial ramdisk (initrd) to boot. |
20 | 19 | ||
21 | config XFS_EXPORT | ||
22 | bool | ||
23 | depends on XFS_FS && EXPORTFS | ||
24 | default y | ||
25 | |||
26 | config XFS_QUOTA | 20 | config XFS_QUOTA |
27 | bool "XFS Quota support" | 21 | bool "XFS Quota support" |
28 | depends on XFS_FS | 22 | depends on XFS_FS |
@@ -65,18 +59,19 @@ config XFS_POSIX_ACL | |||
65 | If you don't know what Access Control Lists are, say N. | 59 | If you don't know what Access Control Lists are, say N. |
66 | 60 | ||
67 | config XFS_RT | 61 | config XFS_RT |
68 | bool "XFS Realtime support (EXPERIMENTAL)" | 62 | bool "XFS Realtime subvolume support" |
69 | depends on XFS_FS && EXPERIMENTAL | 63 | depends on XFS_FS |
70 | help | 64 | help |
71 | If you say Y here you will be able to mount and use XFS filesystems | 65 | If you say Y here you will be able to mount and use XFS filesystems |
72 | which contain a realtime subvolume. The realtime subvolume is a | 66 | which contain a realtime subvolume. The realtime subvolume is a |
73 | separate area of disk space where only file data is stored. The | 67 | separate area of disk space where only file data is stored. It was |
74 | realtime subvolume is designed to provide very deterministic | 68 | originally designed to provide deterministic data rates suitable |
75 | data rates suitable for media streaming applications. | 69 | for media streaming applications, but is also useful as a generic |
76 | 70 | mechanism for ensuring data and metadata/log I/Os are completely | |
77 | See the xfs man page in section 5 for a bit more information. | 71 | separated. Regular file I/Os are isolated to a separate device |
72 | from all other requests, and this can be done quite transparently | ||
73 | to applications via the inherit-realtime directory inode flag. | ||
78 | 74 | ||
79 | This feature is unsupported at this time, is not yet fully | 75 | See the xfs man page in section 5 for additional information. |
80 | functional, and may cause serious problems. | ||
81 | 76 | ||
82 | If unsure, say N. | 77 | If unsure, say N. |
diff --git a/fs/xfs/Makefile-linux-2.6 b/fs/xfs/Makefile-linux-2.6 index 5d73eaa1971f..9e7f85986d0d 100644 --- a/fs/xfs/Makefile-linux-2.6 +++ b/fs/xfs/Makefile-linux-2.6 | |||
@@ -59,7 +59,6 @@ xfs-$(CONFIG_XFS_POSIX_ACL) += xfs_acl.o | |||
59 | xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o | 59 | xfs-$(CONFIG_PROC_FS) += $(XFS_LINUX)/xfs_stats.o |
60 | xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o | 60 | xfs-$(CONFIG_SYSCTL) += $(XFS_LINUX)/xfs_sysctl.o |
61 | xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o | 61 | xfs-$(CONFIG_COMPAT) += $(XFS_LINUX)/xfs_ioctl32.o |
62 | xfs-$(CONFIG_XFS_EXPORT) += $(XFS_LINUX)/xfs_export.o | ||
63 | 62 | ||
64 | 63 | ||
65 | xfs-y += xfs_alloc.o \ | 64 | xfs-y += xfs_alloc.o \ |
@@ -73,14 +72,12 @@ xfs-y += xfs_alloc.o \ | |||
73 | xfs_btree.o \ | 72 | xfs_btree.o \ |
74 | xfs_buf_item.o \ | 73 | xfs_buf_item.o \ |
75 | xfs_da_btree.o \ | 74 | xfs_da_btree.o \ |
76 | xfs_dir.o \ | ||
77 | xfs_dir2.o \ | 75 | xfs_dir2.o \ |
78 | xfs_dir2_block.o \ | 76 | xfs_dir2_block.o \ |
79 | xfs_dir2_data.o \ | 77 | xfs_dir2_data.o \ |
80 | xfs_dir2_leaf.o \ | 78 | xfs_dir2_leaf.o \ |
81 | xfs_dir2_node.o \ | 79 | xfs_dir2_node.o \ |
82 | xfs_dir2_sf.o \ | 80 | xfs_dir2_sf.o \ |
83 | xfs_dir_leaf.o \ | ||
84 | xfs_error.o \ | 81 | xfs_error.o \ |
85 | xfs_extfree_item.o \ | 82 | xfs_extfree_item.o \ |
86 | xfs_fsops.o \ | 83 | xfs_fsops.o \ |
@@ -117,6 +114,7 @@ xfs-y += $(addprefix $(XFS_LINUX)/, \ | |||
117 | kmem.o \ | 114 | kmem.o \ |
118 | xfs_aops.o \ | 115 | xfs_aops.o \ |
119 | xfs_buf.o \ | 116 | xfs_buf.o \ |
117 | xfs_export.o \ | ||
120 | xfs_file.o \ | 118 | xfs_file.o \ |
121 | xfs_fs_subr.o \ | 119 | xfs_fs_subr.o \ |
122 | xfs_globals.o \ | 120 | xfs_globals.o \ |
diff --git a/fs/xfs/linux-2.6/kmem.h b/fs/xfs/linux-2.6/kmem.h index 2cfd33d4d8aa..939bd84bc7ee 100644 --- a/fs/xfs/linux-2.6/kmem.h +++ b/fs/xfs/linux-2.6/kmem.h | |||
@@ -23,42 +23,6 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | 24 | ||
25 | /* | 25 | /* |
26 | * Process flags handling | ||
27 | */ | ||
28 | |||
29 | #define PFLAGS_TEST_NOIO() (current->flags & PF_NOIO) | ||
30 | #define PFLAGS_TEST_FSTRANS() (current->flags & PF_FSTRANS) | ||
31 | |||
32 | #define PFLAGS_SET_NOIO() do { \ | ||
33 | current->flags |= PF_NOIO; \ | ||
34 | } while (0) | ||
35 | |||
36 | #define PFLAGS_CLEAR_NOIO() do { \ | ||
37 | current->flags &= ~PF_NOIO; \ | ||
38 | } while (0) | ||
39 | |||
40 | /* these could be nested, so we save state */ | ||
41 | #define PFLAGS_SET_FSTRANS(STATEP) do { \ | ||
42 | *(STATEP) = current->flags; \ | ||
43 | current->flags |= PF_FSTRANS; \ | ||
44 | } while (0) | ||
45 | |||
46 | #define PFLAGS_CLEAR_FSTRANS(STATEP) do { \ | ||
47 | *(STATEP) = current->flags; \ | ||
48 | current->flags &= ~PF_FSTRANS; \ | ||
49 | } while (0) | ||
50 | |||
51 | /* Restore the PF_FSTRANS state to what was saved in STATEP */ | ||
52 | #define PFLAGS_RESTORE_FSTRANS(STATEP) do { \ | ||
53 | current->flags = ((current->flags & ~PF_FSTRANS) | \ | ||
54 | (*(STATEP) & PF_FSTRANS)); \ | ||
55 | } while (0) | ||
56 | |||
57 | #define PFLAGS_DUP(OSTATEP, NSTATEP) do { \ | ||
58 | *(NSTATEP) = *(OSTATEP); \ | ||
59 | } while (0) | ||
60 | |||
61 | /* | ||
62 | * General memory allocation interfaces | 26 | * General memory allocation interfaces |
63 | */ | 27 | */ |
64 | 28 | ||
@@ -83,7 +47,7 @@ kmem_flags_convert(unsigned int __nocast flags) | |||
83 | lflags = GFP_ATOMIC | __GFP_NOWARN; | 47 | lflags = GFP_ATOMIC | __GFP_NOWARN; |
84 | } else { | 48 | } else { |
85 | lflags = GFP_KERNEL | __GFP_NOWARN; | 49 | lflags = GFP_KERNEL | __GFP_NOWARN; |
86 | if (PFLAGS_TEST_FSTRANS() || (flags & KM_NOFS)) | 50 | if ((current->flags & PF_FSTRANS) || (flags & KM_NOFS)) |
87 | lflags &= ~__GFP_FS; | 51 | lflags &= ~__GFP_FS; |
88 | } | 52 | } |
89 | return lflags; | 53 | return lflags; |
diff --git a/fs/xfs/linux-2.6/mrlock.h b/fs/xfs/linux-2.6/mrlock.h index 1b262b790d9c..32e1ce0f04c9 100644 --- a/fs/xfs/linux-2.6/mrlock.h +++ b/fs/xfs/linux-2.6/mrlock.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -28,7 +28,7 @@ typedef struct { | |||
28 | } mrlock_t; | 28 | } mrlock_t; |
29 | 29 | ||
30 | #define mrinit(mrp, name) \ | 30 | #define mrinit(mrp, name) \ |
31 | ( (mrp)->mr_writer = 0, init_rwsem(&(mrp)->mr_lock) ) | 31 | do { (mrp)->mr_writer = 0; init_rwsem(&(mrp)->mr_lock); } while (0) |
32 | #define mrlock_init(mrp, t,n,s) mrinit(mrp, n) | 32 | #define mrlock_init(mrp, t,n,s) mrinit(mrp, n) |
33 | #define mrfree(mrp) do { } while (0) | 33 | #define mrfree(mrp) do { } while (0) |
34 | #define mraccess(mrp) mraccessf(mrp, 0) | 34 | #define mraccess(mrp) mraccessf(mrp, 0) |
diff --git a/fs/xfs/linux-2.6/sema.h b/fs/xfs/linux-2.6/sema.h index 194a84490bd1..b25090094cca 100644 --- a/fs/xfs/linux-2.6/sema.h +++ b/fs/xfs/linux-2.6/sema.h | |||
@@ -34,20 +34,21 @@ typedef struct semaphore sema_t; | |||
34 | #define initnsema(sp, val, name) sema_init(sp, val) | 34 | #define initnsema(sp, val, name) sema_init(sp, val) |
35 | #define psema(sp, b) down(sp) | 35 | #define psema(sp, b) down(sp) |
36 | #define vsema(sp) up(sp) | 36 | #define vsema(sp) up(sp) |
37 | #define valusema(sp) (atomic_read(&(sp)->count)) | 37 | #define freesema(sema) do { } while (0) |
38 | #define freesema(sema) | 38 | |
39 | static inline int issemalocked(sema_t *sp) | ||
40 | { | ||
41 | return down_trylock(sp) || (up(sp), 0); | ||
42 | } | ||
39 | 43 | ||
40 | /* | 44 | /* |
41 | * Map cpsema (try to get the sema) to down_trylock. We need to switch | 45 | * Map cpsema (try to get the sema) to down_trylock. We need to switch |
42 | * the return values since cpsema returns 1 (acquired) 0 (failed) and | 46 | * the return values since cpsema returns 1 (acquired) 0 (failed) and |
43 | * down_trylock returns the reverse 0 (acquired) 1 (failed). | 47 | * down_trylock returns the reverse 0 (acquired) 1 (failed). |
44 | */ | 48 | */ |
45 | 49 | static inline int cpsema(sema_t *sp) | |
46 | #define cpsema(sp) (down_trylock(sp) ? 0 : 1) | 50 | { |
47 | 51 | return down_trylock(sp) ? 0 : 1; | |
48 | /* | 52 | } |
49 | * Didn't do cvsema(sp). Not sure how to map this to up/down/... | ||
50 | * It does a vsema if the values is < 0 other wise nothing. | ||
51 | */ | ||
52 | 53 | ||
53 | #endif /* __XFS_SUPPORT_SEMA_H__ */ | 54 | #endif /* __XFS_SUPPORT_SEMA_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index 4d191ef39b67..3e807b828e22 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "xfs_inum.h" | 21 | #include "xfs_inum.h" |
22 | #include "xfs_sb.h" | 22 | #include "xfs_sb.h" |
23 | #include "xfs_ag.h" | 23 | #include "xfs_ag.h" |
24 | #include "xfs_dir.h" | ||
25 | #include "xfs_dir2.h" | 24 | #include "xfs_dir2.h" |
26 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
@@ -29,7 +28,6 @@ | |||
29 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
30 | #include "xfs_alloc_btree.h" | 29 | #include "xfs_alloc_btree.h" |
31 | #include "xfs_ialloc_btree.h" | 30 | #include "xfs_ialloc_btree.h" |
32 | #include "xfs_dir_sf.h" | ||
33 | #include "xfs_dir2_sf.h" | 31 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 32 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
@@ -76,7 +74,7 @@ xfs_page_trace( | |||
76 | int mask) | 74 | int mask) |
77 | { | 75 | { |
78 | xfs_inode_t *ip; | 76 | xfs_inode_t *ip; |
79 | vnode_t *vp = vn_from_inode(inode); | 77 | bhv_vnode_t *vp = vn_from_inode(inode); |
80 | loff_t isize = i_size_read(inode); | 78 | loff_t isize = i_size_read(inode); |
81 | loff_t offset = page_offset(page); | 79 | loff_t offset = page_offset(page); |
82 | int delalloc = -1, unmapped = -1, unwritten = -1; | 80 | int delalloc = -1, unmapped = -1, unwritten = -1; |
@@ -136,9 +134,10 @@ xfs_destroy_ioend( | |||
136 | 134 | ||
137 | for (bh = ioend->io_buffer_head; bh; bh = next) { | 135 | for (bh = ioend->io_buffer_head; bh; bh = next) { |
138 | next = bh->b_private; | 136 | next = bh->b_private; |
139 | bh->b_end_io(bh, ioend->io_uptodate); | 137 | bh->b_end_io(bh, !ioend->io_error); |
140 | } | 138 | } |
141 | 139 | if (unlikely(ioend->io_error)) | |
140 | vn_ioerror(ioend->io_vnode, ioend->io_error, __FILE__,__LINE__); | ||
142 | vn_iowake(ioend->io_vnode); | 141 | vn_iowake(ioend->io_vnode); |
143 | mempool_free(ioend, xfs_ioend_pool); | 142 | mempool_free(ioend, xfs_ioend_pool); |
144 | } | 143 | } |
@@ -180,13 +179,12 @@ xfs_end_bio_unwritten( | |||
180 | void *data) | 179 | void *data) |
181 | { | 180 | { |
182 | xfs_ioend_t *ioend = data; | 181 | xfs_ioend_t *ioend = data; |
183 | vnode_t *vp = ioend->io_vnode; | 182 | bhv_vnode_t *vp = ioend->io_vnode; |
184 | xfs_off_t offset = ioend->io_offset; | 183 | xfs_off_t offset = ioend->io_offset; |
185 | size_t size = ioend->io_size; | 184 | size_t size = ioend->io_size; |
186 | int error; | ||
187 | 185 | ||
188 | if (ioend->io_uptodate) | 186 | if (likely(!ioend->io_error)) |
189 | VOP_BMAP(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL, error); | 187 | bhv_vop_bmap(vp, offset, size, BMAPI_UNWRITTEN, NULL, NULL); |
190 | xfs_destroy_ioend(ioend); | 188 | xfs_destroy_ioend(ioend); |
191 | } | 189 | } |
192 | 190 | ||
@@ -211,7 +209,7 @@ xfs_alloc_ioend( | |||
211 | * all the I/O from calling the completion routine too early. | 209 | * all the I/O from calling the completion routine too early. |
212 | */ | 210 | */ |
213 | atomic_set(&ioend->io_remaining, 1); | 211 | atomic_set(&ioend->io_remaining, 1); |
214 | ioend->io_uptodate = 1; /* cleared if any I/O fails */ | 212 | ioend->io_error = 0; |
215 | ioend->io_list = NULL; | 213 | ioend->io_list = NULL; |
216 | ioend->io_type = type; | 214 | ioend->io_type = type; |
217 | ioend->io_vnode = vn_from_inode(inode); | 215 | ioend->io_vnode = vn_from_inode(inode); |
@@ -239,10 +237,10 @@ xfs_map_blocks( | |||
239 | xfs_iomap_t *mapp, | 237 | xfs_iomap_t *mapp, |
240 | int flags) | 238 | int flags) |
241 | { | 239 | { |
242 | vnode_t *vp = vn_from_inode(inode); | 240 | bhv_vnode_t *vp = vn_from_inode(inode); |
243 | int error, nmaps = 1; | 241 | int error, nmaps = 1; |
244 | 242 | ||
245 | VOP_BMAP(vp, offset, count, flags, mapp, &nmaps, error); | 243 | error = bhv_vop_bmap(vp, offset, count, flags, mapp, &nmaps); |
246 | if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE))) | 244 | if (!error && (flags & (BMAPI_WRITE|BMAPI_ALLOCATE))) |
247 | VMODIFY(vp); | 245 | VMODIFY(vp); |
248 | return -error; | 246 | return -error; |
@@ -271,16 +269,14 @@ xfs_end_bio( | |||
271 | if (bio->bi_size) | 269 | if (bio->bi_size) |
272 | return 1; | 270 | return 1; |
273 | 271 | ||
274 | ASSERT(ioend); | ||
275 | ASSERT(atomic_read(&bio->bi_cnt) >= 1); | 272 | ASSERT(atomic_read(&bio->bi_cnt) >= 1); |
273 | ioend->io_error = test_bit(BIO_UPTODATE, &bio->bi_flags) ? 0 : error; | ||
276 | 274 | ||
277 | /* Toss bio and pass work off to an xfsdatad thread */ | 275 | /* Toss bio and pass work off to an xfsdatad thread */ |
278 | if (!test_bit(BIO_UPTODATE, &bio->bi_flags)) | ||
279 | ioend->io_uptodate = 0; | ||
280 | bio->bi_private = NULL; | 276 | bio->bi_private = NULL; |
281 | bio->bi_end_io = NULL; | 277 | bio->bi_end_io = NULL; |
282 | |||
283 | bio_put(bio); | 278 | bio_put(bio); |
279 | |||
284 | xfs_finish_ioend(ioend); | 280 | xfs_finish_ioend(ioend); |
285 | return 0; | 281 | return 0; |
286 | } | 282 | } |
@@ -1127,7 +1123,7 @@ xfs_vm_writepage( | |||
1127 | * then mark the page dirty again and leave the page | 1123 | * then mark the page dirty again and leave the page |
1128 | * as is. | 1124 | * as is. |
1129 | */ | 1125 | */ |
1130 | if (PFLAGS_TEST_FSTRANS() && need_trans) | 1126 | if (current_test_flags(PF_FSTRANS) && need_trans) |
1131 | goto out_fail; | 1127 | goto out_fail; |
1132 | 1128 | ||
1133 | /* | 1129 | /* |
@@ -1158,6 +1154,18 @@ out_unlock: | |||
1158 | return error; | 1154 | return error; |
1159 | } | 1155 | } |
1160 | 1156 | ||
1157 | STATIC int | ||
1158 | xfs_vm_writepages( | ||
1159 | struct address_space *mapping, | ||
1160 | struct writeback_control *wbc) | ||
1161 | { | ||
1162 | struct bhv_vnode *vp = vn_from_inode(mapping->host); | ||
1163 | |||
1164 | if (VN_TRUNC(vp)) | ||
1165 | VUNTRUNCATE(vp); | ||
1166 | return generic_writepages(mapping, wbc); | ||
1167 | } | ||
1168 | |||
1161 | /* | 1169 | /* |
1162 | * Called to move a page into cleanable state - and from there | 1170 | * Called to move a page into cleanable state - and from there |
1163 | * to be released. Possibly the page is already clean. We always | 1171 | * to be released. Possibly the page is already clean. We always |
@@ -1204,7 +1212,7 @@ xfs_vm_releasepage( | |||
1204 | /* If we are already inside a transaction or the thread cannot | 1212 | /* If we are already inside a transaction or the thread cannot |
1205 | * do I/O, we cannot release this page. | 1213 | * do I/O, we cannot release this page. |
1206 | */ | 1214 | */ |
1207 | if (PFLAGS_TEST_FSTRANS()) | 1215 | if (current_test_flags(PF_FSTRANS)) |
1208 | return 0; | 1216 | return 0; |
1209 | 1217 | ||
1210 | /* | 1218 | /* |
@@ -1231,7 +1239,7 @@ __xfs_get_blocks( | |||
1231 | int direct, | 1239 | int direct, |
1232 | bmapi_flags_t flags) | 1240 | bmapi_flags_t flags) |
1233 | { | 1241 | { |
1234 | vnode_t *vp = vn_from_inode(inode); | 1242 | bhv_vnode_t *vp = vn_from_inode(inode); |
1235 | xfs_iomap_t iomap; | 1243 | xfs_iomap_t iomap; |
1236 | xfs_off_t offset; | 1244 | xfs_off_t offset; |
1237 | ssize_t size; | 1245 | ssize_t size; |
@@ -1241,8 +1249,8 @@ __xfs_get_blocks( | |||
1241 | offset = (xfs_off_t)iblock << inode->i_blkbits; | 1249 | offset = (xfs_off_t)iblock << inode->i_blkbits; |
1242 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); | 1250 | ASSERT(bh_result->b_size >= (1 << inode->i_blkbits)); |
1243 | size = bh_result->b_size; | 1251 | size = bh_result->b_size; |
1244 | VOP_BMAP(vp, offset, size, | 1252 | error = bhv_vop_bmap(vp, offset, size, |
1245 | create ? flags : BMAPI_READ, &iomap, &niomap, error); | 1253 | create ? flags : BMAPI_READ, &iomap, &niomap); |
1246 | if (error) | 1254 | if (error) |
1247 | return -error; | 1255 | return -error; |
1248 | if (niomap == 0) | 1256 | if (niomap == 0) |
@@ -1370,13 +1378,13 @@ xfs_vm_direct_IO( | |||
1370 | { | 1378 | { |
1371 | struct file *file = iocb->ki_filp; | 1379 | struct file *file = iocb->ki_filp; |
1372 | struct inode *inode = file->f_mapping->host; | 1380 | struct inode *inode = file->f_mapping->host; |
1373 | vnode_t *vp = vn_from_inode(inode); | 1381 | bhv_vnode_t *vp = vn_from_inode(inode); |
1374 | xfs_iomap_t iomap; | 1382 | xfs_iomap_t iomap; |
1375 | int maps = 1; | 1383 | int maps = 1; |
1376 | int error; | 1384 | int error; |
1377 | ssize_t ret; | 1385 | ssize_t ret; |
1378 | 1386 | ||
1379 | VOP_BMAP(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps, error); | 1387 | error = bhv_vop_bmap(vp, offset, 0, BMAPI_DEVICE, &iomap, &maps); |
1380 | if (error) | 1388 | if (error) |
1381 | return -error; | 1389 | return -error; |
1382 | 1390 | ||
@@ -1409,14 +1417,12 @@ xfs_vm_bmap( | |||
1409 | sector_t block) | 1417 | sector_t block) |
1410 | { | 1418 | { |
1411 | struct inode *inode = (struct inode *)mapping->host; | 1419 | struct inode *inode = (struct inode *)mapping->host; |
1412 | vnode_t *vp = vn_from_inode(inode); | 1420 | bhv_vnode_t *vp = vn_from_inode(inode); |
1413 | int error; | ||
1414 | 1421 | ||
1415 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 1422 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
1416 | 1423 | bhv_vop_rwlock(vp, VRWLOCK_READ); | |
1417 | VOP_RWLOCK(vp, VRWLOCK_READ); | 1424 | bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF); |
1418 | VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); | 1425 | bhv_vop_rwunlock(vp, VRWLOCK_READ); |
1419 | VOP_RWUNLOCK(vp, VRWLOCK_READ); | ||
1420 | return generic_block_bmap(mapping, block, xfs_get_blocks); | 1426 | return generic_block_bmap(mapping, block, xfs_get_blocks); |
1421 | } | 1427 | } |
1422 | 1428 | ||
@@ -1452,6 +1458,7 @@ struct address_space_operations xfs_address_space_operations = { | |||
1452 | .readpage = xfs_vm_readpage, | 1458 | .readpage = xfs_vm_readpage, |
1453 | .readpages = xfs_vm_readpages, | 1459 | .readpages = xfs_vm_readpages, |
1454 | .writepage = xfs_vm_writepage, | 1460 | .writepage = xfs_vm_writepage, |
1461 | .writepages = xfs_vm_writepages, | ||
1455 | .sync_page = block_sync_page, | 1462 | .sync_page = block_sync_page, |
1456 | .releasepage = xfs_vm_releasepage, | 1463 | .releasepage = xfs_vm_releasepage, |
1457 | .invalidatepage = xfs_vm_invalidatepage, | 1464 | .invalidatepage = xfs_vm_invalidatepage, |
diff --git a/fs/xfs/linux-2.6/xfs_aops.h b/fs/xfs/linux-2.6/xfs_aops.h index 60716543c68b..706d8c781b8a 100644 --- a/fs/xfs/linux-2.6/xfs_aops.h +++ b/fs/xfs/linux-2.6/xfs_aops.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2005-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -30,9 +30,9 @@ typedef void (*xfs_ioend_func_t)(void *); | |||
30 | typedef struct xfs_ioend { | 30 | typedef struct xfs_ioend { |
31 | struct xfs_ioend *io_list; /* next ioend in chain */ | 31 | struct xfs_ioend *io_list; /* next ioend in chain */ |
32 | unsigned int io_type; /* delalloc / unwritten */ | 32 | unsigned int io_type; /* delalloc / unwritten */ |
33 | unsigned int io_uptodate; /* I/O status register */ | 33 | int io_error; /* I/O error code */ |
34 | atomic_t io_remaining; /* hold count */ | 34 | atomic_t io_remaining; /* hold count */ |
35 | struct vnode *io_vnode; /* file being written to */ | 35 | struct bhv_vnode *io_vnode; /* file being written to */ |
36 | struct buffer_head *io_buffer_head;/* buffer linked list head */ | 36 | struct buffer_head *io_buffer_head;/* buffer linked list head */ |
37 | struct buffer_head *io_buffer_tail;/* buffer linked list tail */ | 37 | struct buffer_head *io_buffer_tail;/* buffer linked list tail */ |
38 | size_t io_size; /* size of the extent */ | 38 | size_t io_size; /* size of the extent */ |
@@ -43,4 +43,4 @@ typedef struct xfs_ioend { | |||
43 | extern struct address_space_operations xfs_address_space_operations; | 43 | extern struct address_space_operations xfs_address_space_operations; |
44 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); | 44 | extern int xfs_get_blocks(struct inode *, sector_t, struct buffer_head *, int); |
45 | 45 | ||
46 | #endif /* __XFS_IOPS_H__ */ | 46 | #endif /* __XFS_AOPS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_export.c b/fs/xfs/linux-2.6/xfs_export.c index b768ea910bbe..5fb75d9151f2 100644 --- a/fs/xfs/linux-2.6/xfs_export.c +++ b/fs/xfs/linux-2.6/xfs_export.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "xfs_log.h" | 21 | #include "xfs_log.h" |
22 | #include "xfs_trans.h" | 22 | #include "xfs_trans.h" |
23 | #include "xfs_sb.h" | 23 | #include "xfs_sb.h" |
24 | #include "xfs_dir.h" | ||
25 | #include "xfs_mount.h" | 24 | #include "xfs_mount.h" |
26 | #include "xfs_export.h" | 25 | #include "xfs_export.h" |
27 | 26 | ||
@@ -97,7 +96,7 @@ xfs_fs_encode_fh( | |||
97 | int len; | 96 | int len; |
98 | int is64 = 0; | 97 | int is64 = 0; |
99 | #if XFS_BIG_INUMS | 98 | #if XFS_BIG_INUMS |
100 | vfs_t *vfs = vfs_from_sb(inode->i_sb); | 99 | bhv_vfs_t *vfs = vfs_from_sb(inode->i_sb); |
101 | 100 | ||
102 | if (!(vfs->vfs_flag & VFS_32BITINODES)) { | 101 | if (!(vfs->vfs_flag & VFS_32BITINODES)) { |
103 | /* filesystem may contain 64bit inode numbers */ | 102 | /* filesystem may contain 64bit inode numbers */ |
@@ -136,13 +135,13 @@ xfs_fs_get_dentry( | |||
136 | struct super_block *sb, | 135 | struct super_block *sb, |
137 | void *data) | 136 | void *data) |
138 | { | 137 | { |
139 | vnode_t *vp; | 138 | bhv_vnode_t *vp; |
140 | struct inode *inode; | 139 | struct inode *inode; |
141 | struct dentry *result; | 140 | struct dentry *result; |
142 | vfs_t *vfsp = vfs_from_sb(sb); | 141 | bhv_vfs_t *vfsp = vfs_from_sb(sb); |
143 | int error; | 142 | int error; |
144 | 143 | ||
145 | VFS_VGET(vfsp, &vp, (fid_t *)data, error); | 144 | error = bhv_vfs_vget(vfsp, &vp, (fid_t *)data); |
146 | if (error || vp == NULL) | 145 | if (error || vp == NULL) |
147 | return ERR_PTR(-ESTALE) ; | 146 | return ERR_PTR(-ESTALE) ; |
148 | 147 | ||
@@ -160,12 +159,12 @@ xfs_fs_get_parent( | |||
160 | struct dentry *child) | 159 | struct dentry *child) |
161 | { | 160 | { |
162 | int error; | 161 | int error; |
163 | vnode_t *vp, *cvp; | 162 | bhv_vnode_t *vp, *cvp; |
164 | struct dentry *parent; | 163 | struct dentry *parent; |
165 | 164 | ||
166 | cvp = NULL; | 165 | cvp = NULL; |
167 | vp = vn_from_inode(child->d_inode); | 166 | vp = vn_from_inode(child->d_inode); |
168 | VOP_LOOKUP(vp, &dotdot, &cvp, 0, NULL, NULL, error); | 167 | error = bhv_vop_lookup(vp, &dotdot, &cvp, 0, NULL, NULL); |
169 | if (unlikely(error)) | 168 | if (unlikely(error)) |
170 | return ERR_PTR(-error); | 169 | return ERR_PTR(-error); |
171 | 170 | ||
diff --git a/fs/xfs/linux-2.6/xfs_file.c b/fs/xfs/linux-2.6/xfs_file.c index c847416f6d10..70662371bb11 100644 --- a/fs/xfs/linux-2.6/xfs_file.c +++ b/fs/xfs/linux-2.6/xfs_file.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include "xfs_inum.h" | 21 | #include "xfs_inum.h" |
22 | #include "xfs_sb.h" | 22 | #include "xfs_sb.h" |
23 | #include "xfs_ag.h" | 23 | #include "xfs_ag.h" |
24 | #include "xfs_dir.h" | ||
25 | #include "xfs_dir2.h" | 24 | #include "xfs_dir2.h" |
26 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_alloc.h" | 31 | #include "xfs_alloc.h" |
33 | #include "xfs_btree.h" | 32 | #include "xfs_btree.h" |
34 | #include "xfs_attr_sf.h" | 33 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
@@ -58,15 +56,12 @@ __xfs_file_read( | |||
58 | { | 56 | { |
59 | struct iovec iov = {buf, count}; | 57 | struct iovec iov = {buf, count}; |
60 | struct file *file = iocb->ki_filp; | 58 | struct file *file = iocb->ki_filp; |
61 | vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); | 59 | bhv_vnode_t *vp = vn_from_inode(file->f_dentry->d_inode); |
62 | ssize_t rval; | ||
63 | 60 | ||
64 | BUG_ON(iocb->ki_pos != pos); | 61 | BUG_ON(iocb->ki_pos != pos); |
65 | |||
66 | if (unlikely(file->f_flags & O_DIRECT)) | 62 | if (unlikely(file->f_flags & O_DIRECT)) |
67 | ioflags |= IO_ISDIRECT; | 63 | ioflags |= IO_ISDIRECT; |
68 | VOP_READ(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval); | 64 | return bhv_vop_read(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); |
69 | return rval; | ||
70 | } | 65 | } |
71 | 66 | ||
72 | STATIC ssize_t | 67 | STATIC ssize_t |
@@ -100,15 +95,12 @@ __xfs_file_write( | |||
100 | struct iovec iov = {(void __user *)buf, count}; | 95 | struct iovec iov = {(void __user *)buf, count}; |
101 | struct file *file = iocb->ki_filp; | 96 | struct file *file = iocb->ki_filp; |
102 | struct inode *inode = file->f_mapping->host; | 97 | struct inode *inode = file->f_mapping->host; |
103 | vnode_t *vp = vn_from_inode(inode); | 98 | bhv_vnode_t *vp = vn_from_inode(inode); |
104 | ssize_t rval; | ||
105 | 99 | ||
106 | BUG_ON(iocb->ki_pos != pos); | 100 | BUG_ON(iocb->ki_pos != pos); |
107 | if (unlikely(file->f_flags & O_DIRECT)) | 101 | if (unlikely(file->f_flags & O_DIRECT)) |
108 | ioflags |= IO_ISDIRECT; | 102 | ioflags |= IO_ISDIRECT; |
109 | 103 | return bhv_vop_write(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL); | |
110 | VOP_WRITE(vp, iocb, &iov, 1, &iocb->ki_pos, ioflags, NULL, rval); | ||
111 | return rval; | ||
112 | } | 104 | } |
113 | 105 | ||
114 | STATIC ssize_t | 106 | STATIC ssize_t |
@@ -140,7 +132,7 @@ __xfs_file_readv( | |||
140 | loff_t *ppos) | 132 | loff_t *ppos) |
141 | { | 133 | { |
142 | struct inode *inode = file->f_mapping->host; | 134 | struct inode *inode = file->f_mapping->host; |
143 | vnode_t *vp = vn_from_inode(inode); | 135 | bhv_vnode_t *vp = vn_from_inode(inode); |
144 | struct kiocb kiocb; | 136 | struct kiocb kiocb; |
145 | ssize_t rval; | 137 | ssize_t rval; |
146 | 138 | ||
@@ -149,7 +141,8 @@ __xfs_file_readv( | |||
149 | 141 | ||
150 | if (unlikely(file->f_flags & O_DIRECT)) | 142 | if (unlikely(file->f_flags & O_DIRECT)) |
151 | ioflags |= IO_ISDIRECT; | 143 | ioflags |= IO_ISDIRECT; |
152 | VOP_READ(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); | 144 | rval = bhv_vop_read(vp, &kiocb, iov, nr_segs, |
145 | &kiocb.ki_pos, ioflags, NULL); | ||
153 | 146 | ||
154 | *ppos = kiocb.ki_pos; | 147 | *ppos = kiocb.ki_pos; |
155 | return rval; | 148 | return rval; |
@@ -184,7 +177,7 @@ __xfs_file_writev( | |||
184 | loff_t *ppos) | 177 | loff_t *ppos) |
185 | { | 178 | { |
186 | struct inode *inode = file->f_mapping->host; | 179 | struct inode *inode = file->f_mapping->host; |
187 | vnode_t *vp = vn_from_inode(inode); | 180 | bhv_vnode_t *vp = vn_from_inode(inode); |
188 | struct kiocb kiocb; | 181 | struct kiocb kiocb; |
189 | ssize_t rval; | 182 | ssize_t rval; |
190 | 183 | ||
@@ -193,7 +186,8 @@ __xfs_file_writev( | |||
193 | if (unlikely(file->f_flags & O_DIRECT)) | 186 | if (unlikely(file->f_flags & O_DIRECT)) |
194 | ioflags |= IO_ISDIRECT; | 187 | ioflags |= IO_ISDIRECT; |
195 | 188 | ||
196 | VOP_WRITE(vp, &kiocb, iov, nr_segs, &kiocb.ki_pos, ioflags, NULL, rval); | 189 | rval = bhv_vop_write(vp, &kiocb, iov, nr_segs, |
190 | &kiocb.ki_pos, ioflags, NULL); | ||
197 | 191 | ||
198 | *ppos = kiocb.ki_pos; | 192 | *ppos = kiocb.ki_pos; |
199 | return rval; | 193 | return rval; |
@@ -227,11 +221,8 @@ xfs_file_sendfile( | |||
227 | read_actor_t actor, | 221 | read_actor_t actor, |
228 | void *target) | 222 | void *target) |
229 | { | 223 | { |
230 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | 224 | return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), |
231 | ssize_t rval; | 225 | filp, pos, 0, count, actor, target, NULL); |
232 | |||
233 | VOP_SENDFILE(vp, filp, pos, 0, count, actor, target, NULL, rval); | ||
234 | return rval; | ||
235 | } | 226 | } |
236 | 227 | ||
237 | STATIC ssize_t | 228 | STATIC ssize_t |
@@ -242,11 +233,8 @@ xfs_file_sendfile_invis( | |||
242 | read_actor_t actor, | 233 | read_actor_t actor, |
243 | void *target) | 234 | void *target) |
244 | { | 235 | { |
245 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | 236 | return bhv_vop_sendfile(vn_from_inode(filp->f_dentry->d_inode), |
246 | ssize_t rval; | 237 | filp, pos, IO_INVIS, count, actor, target, NULL); |
247 | |||
248 | VOP_SENDFILE(vp, filp, pos, IO_INVIS, count, actor, target, NULL, rval); | ||
249 | return rval; | ||
250 | } | 238 | } |
251 | 239 | ||
252 | STATIC ssize_t | 240 | STATIC ssize_t |
@@ -257,11 +245,8 @@ xfs_file_splice_read( | |||
257 | size_t len, | 245 | size_t len, |
258 | unsigned int flags) | 246 | unsigned int flags) |
259 | { | 247 | { |
260 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | 248 | return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), |
261 | ssize_t rval; | 249 | infilp, ppos, pipe, len, flags, 0, NULL); |
262 | |||
263 | VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, 0, NULL, rval); | ||
264 | return rval; | ||
265 | } | 250 | } |
266 | 251 | ||
267 | STATIC ssize_t | 252 | STATIC ssize_t |
@@ -272,11 +257,9 @@ xfs_file_splice_read_invis( | |||
272 | size_t len, | 257 | size_t len, |
273 | unsigned int flags) | 258 | unsigned int flags) |
274 | { | 259 | { |
275 | vnode_t *vp = vn_from_inode(infilp->f_dentry->d_inode); | 260 | return bhv_vop_splice_read(vn_from_inode(infilp->f_dentry->d_inode), |
276 | ssize_t rval; | 261 | infilp, ppos, pipe, len, flags, IO_INVIS, |
277 | 262 | NULL); | |
278 | VOP_SPLICE_READ(vp, infilp, ppos, pipe, len, flags, IO_INVIS, NULL, rval); | ||
279 | return rval; | ||
280 | } | 263 | } |
281 | 264 | ||
282 | STATIC ssize_t | 265 | STATIC ssize_t |
@@ -287,11 +270,8 @@ xfs_file_splice_write( | |||
287 | size_t len, | 270 | size_t len, |
288 | unsigned int flags) | 271 | unsigned int flags) |
289 | { | 272 | { |
290 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | 273 | return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), |
291 | ssize_t rval; | 274 | pipe, outfilp, ppos, len, flags, 0, NULL); |
292 | |||
293 | VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, 0, NULL, rval); | ||
294 | return rval; | ||
295 | } | 275 | } |
296 | 276 | ||
297 | STATIC ssize_t | 277 | STATIC ssize_t |
@@ -302,11 +282,9 @@ xfs_file_splice_write_invis( | |||
302 | size_t len, | 282 | size_t len, |
303 | unsigned int flags) | 283 | unsigned int flags) |
304 | { | 284 | { |
305 | vnode_t *vp = vn_from_inode(outfilp->f_dentry->d_inode); | 285 | return bhv_vop_splice_write(vn_from_inode(outfilp->f_dentry->d_inode), |
306 | ssize_t rval; | 286 | pipe, outfilp, ppos, len, flags, IO_INVIS, |
307 | 287 | NULL); | |
308 | VOP_SPLICE_WRITE(vp, pipe, outfilp, ppos, len, flags, IO_INVIS, NULL, rval); | ||
309 | return rval; | ||
310 | } | 288 | } |
311 | 289 | ||
312 | STATIC int | 290 | STATIC int |
@@ -314,13 +292,17 @@ xfs_file_open( | |||
314 | struct inode *inode, | 292 | struct inode *inode, |
315 | struct file *filp) | 293 | struct file *filp) |
316 | { | 294 | { |
317 | vnode_t *vp = vn_from_inode(inode); | ||
318 | int error; | ||
319 | |||
320 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) | 295 | if (!(filp->f_flags & O_LARGEFILE) && i_size_read(inode) > MAX_NON_LFS) |
321 | return -EFBIG; | 296 | return -EFBIG; |
322 | VOP_OPEN(vp, NULL, error); | 297 | return -bhv_vop_open(vn_from_inode(inode), NULL); |
323 | return -error; | 298 | } |
299 | |||
300 | STATIC int | ||
301 | xfs_file_close( | ||
302 | struct file *filp) | ||
303 | { | ||
304 | return -bhv_vop_close(vn_from_inode(filp->f_dentry->d_inode), 0, | ||
305 | file_count(filp) > 1 ? L_FALSE : L_TRUE, NULL); | ||
324 | } | 306 | } |
325 | 307 | ||
326 | STATIC int | 308 | STATIC int |
@@ -328,12 +310,11 @@ xfs_file_release( | |||
328 | struct inode *inode, | 310 | struct inode *inode, |
329 | struct file *filp) | 311 | struct file *filp) |
330 | { | 312 | { |
331 | vnode_t *vp = vn_from_inode(inode); | 313 | bhv_vnode_t *vp = vn_from_inode(inode); |
332 | int error = 0; | ||
333 | 314 | ||
334 | if (vp) | 315 | if (vp) |
335 | VOP_RELEASE(vp, error); | 316 | return -bhv_vop_release(vp); |
336 | return -error; | 317 | return 0; |
337 | } | 318 | } |
338 | 319 | ||
339 | STATIC int | 320 | STATIC int |
@@ -342,15 +323,14 @@ xfs_file_fsync( | |||
342 | struct dentry *dentry, | 323 | struct dentry *dentry, |
343 | int datasync) | 324 | int datasync) |
344 | { | 325 | { |
345 | struct inode *inode = dentry->d_inode; | 326 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
346 | vnode_t *vp = vn_from_inode(inode); | ||
347 | int error; | ||
348 | int flags = FSYNC_WAIT; | 327 | int flags = FSYNC_WAIT; |
349 | 328 | ||
350 | if (datasync) | 329 | if (datasync) |
351 | flags |= FSYNC_DATA; | 330 | flags |= FSYNC_DATA; |
352 | VOP_FSYNC(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1, error); | 331 | if (VN_TRUNC(vp)) |
353 | return -error; | 332 | VUNTRUNCATE(vp); |
333 | return -bhv_vop_fsync(vp, flags, NULL, (xfs_off_t)0, (xfs_off_t)-1); | ||
354 | } | 334 | } |
355 | 335 | ||
356 | #ifdef CONFIG_XFS_DMAPI | 336 | #ifdef CONFIG_XFS_DMAPI |
@@ -361,16 +341,11 @@ xfs_vm_nopage( | |||
361 | int *type) | 341 | int *type) |
362 | { | 342 | { |
363 | struct inode *inode = area->vm_file->f_dentry->d_inode; | 343 | struct inode *inode = area->vm_file->f_dentry->d_inode; |
364 | vnode_t *vp = vn_from_inode(inode); | 344 | bhv_vnode_t *vp = vn_from_inode(inode); |
365 | xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); | ||
366 | int error; | ||
367 | 345 | ||
368 | ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); | 346 | ASSERT_ALWAYS(vp->v_vfsp->vfs_flag & VFS_DMI); |
369 | 347 | if (XFS_SEND_MMAP(XFS_VFSTOM(vp->v_vfsp), area, 0)) | |
370 | error = XFS_SEND_MMAP(mp, area, 0); | ||
371 | if (error) | ||
372 | return NULL; | 348 | return NULL; |
373 | |||
374 | return filemap_nopage(area, address, type); | 349 | return filemap_nopage(area, address, type); |
375 | } | 350 | } |
376 | #endif /* CONFIG_XFS_DMAPI */ | 351 | #endif /* CONFIG_XFS_DMAPI */ |
@@ -382,7 +357,7 @@ xfs_file_readdir( | |||
382 | filldir_t filldir) | 357 | filldir_t filldir) |
383 | { | 358 | { |
384 | int error = 0; | 359 | int error = 0; |
385 | vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); | 360 | bhv_vnode_t *vp = vn_from_inode(filp->f_dentry->d_inode); |
386 | uio_t uio; | 361 | uio_t uio; |
387 | iovec_t iov; | 362 | iovec_t iov; |
388 | int eof = 0; | 363 | int eof = 0; |
@@ -417,7 +392,7 @@ xfs_file_readdir( | |||
417 | 392 | ||
418 | start_offset = uio.uio_offset; | 393 | start_offset = uio.uio_offset; |
419 | 394 | ||
420 | VOP_READDIR(vp, &uio, NULL, &eof, error); | 395 | error = bhv_vop_readdir(vp, &uio, NULL, &eof); |
421 | if ((uio.uio_offset == start_offset) || error) { | 396 | if ((uio.uio_offset == start_offset) || error) { |
422 | size = 0; | 397 | size = 0; |
423 | break; | 398 | break; |
@@ -456,38 +431,28 @@ xfs_file_mmap( | |||
456 | struct file *filp, | 431 | struct file *filp, |
457 | struct vm_area_struct *vma) | 432 | struct vm_area_struct *vma) |
458 | { | 433 | { |
459 | struct inode *ip = filp->f_dentry->d_inode; | ||
460 | vnode_t *vp = vn_from_inode(ip); | ||
461 | vattr_t vattr; | ||
462 | int error; | ||
463 | |||
464 | vma->vm_ops = &xfs_file_vm_ops; | 434 | vma->vm_ops = &xfs_file_vm_ops; |
465 | 435 | ||
466 | #ifdef CONFIG_XFS_DMAPI | 436 | #ifdef CONFIG_XFS_DMAPI |
467 | if (vp->v_vfsp->vfs_flag & VFS_DMI) { | 437 | if (vn_from_inode(filp->f_dentry->d_inode)->v_vfsp->vfs_flag & VFS_DMI) |
468 | vma->vm_ops = &xfs_dmapi_file_vm_ops; | 438 | vma->vm_ops = &xfs_dmapi_file_vm_ops; |
469 | } | ||
470 | #endif /* CONFIG_XFS_DMAPI */ | 439 | #endif /* CONFIG_XFS_DMAPI */ |
471 | 440 | ||
472 | vattr.va_mask = XFS_AT_UPDATIME; | 441 | file_accessed(filp); |
473 | VOP_SETATTR(vp, &vattr, XFS_AT_UPDATIME, NULL, error); | ||
474 | if (likely(!error)) | ||
475 | __vn_revalidate(vp, &vattr); /* update flags */ | ||
476 | return 0; | 442 | return 0; |
477 | } | 443 | } |
478 | 444 | ||
479 | |||
480 | STATIC long | 445 | STATIC long |
481 | xfs_file_ioctl( | 446 | xfs_file_ioctl( |
482 | struct file *filp, | 447 | struct file *filp, |
483 | unsigned int cmd, | 448 | unsigned int cmd, |
484 | unsigned long arg) | 449 | unsigned long p) |
485 | { | 450 | { |
486 | int error; | 451 | int error; |
487 | struct inode *inode = filp->f_dentry->d_inode; | 452 | struct inode *inode = filp->f_dentry->d_inode; |
488 | vnode_t *vp = vn_from_inode(inode); | 453 | bhv_vnode_t *vp = vn_from_inode(inode); |
489 | 454 | ||
490 | VOP_IOCTL(vp, inode, filp, 0, cmd, (void __user *)arg, error); | 455 | error = bhv_vop_ioctl(vp, inode, filp, 0, cmd, (void __user *)p); |
491 | VMODIFY(vp); | 456 | VMODIFY(vp); |
492 | 457 | ||
493 | /* NOTE: some of the ioctl's return positive #'s as a | 458 | /* NOTE: some of the ioctl's return positive #'s as a |
@@ -503,13 +468,13 @@ STATIC long | |||
503 | xfs_file_ioctl_invis( | 468 | xfs_file_ioctl_invis( |
504 | struct file *filp, | 469 | struct file *filp, |
505 | unsigned int cmd, | 470 | unsigned int cmd, |
506 | unsigned long arg) | 471 | unsigned long p) |
507 | { | 472 | { |
508 | struct inode *inode = filp->f_dentry->d_inode; | ||
509 | vnode_t *vp = vn_from_inode(inode); | ||
510 | int error; | 473 | int error; |
474 | struct inode *inode = filp->f_dentry->d_inode; | ||
475 | bhv_vnode_t *vp = vn_from_inode(inode); | ||
511 | 476 | ||
512 | VOP_IOCTL(vp, inode, filp, IO_INVIS, cmd, (void __user *)arg, error); | 477 | error = bhv_vop_ioctl(vp, inode, filp, IO_INVIS, cmd, (void __user *)p); |
513 | VMODIFY(vp); | 478 | VMODIFY(vp); |
514 | 479 | ||
515 | /* NOTE: some of the ioctl's return positive #'s as a | 480 | /* NOTE: some of the ioctl's return positive #'s as a |
@@ -528,7 +493,7 @@ xfs_vm_mprotect( | |||
528 | struct vm_area_struct *vma, | 493 | struct vm_area_struct *vma, |
529 | unsigned int newflags) | 494 | unsigned int newflags) |
530 | { | 495 | { |
531 | vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); | 496 | bhv_vnode_t *vp = vn_from_inode(vma->vm_file->f_dentry->d_inode); |
532 | int error = 0; | 497 | int error = 0; |
533 | 498 | ||
534 | if (vp->v_vfsp->vfs_flag & VFS_DMI) { | 499 | if (vp->v_vfsp->vfs_flag & VFS_DMI) { |
@@ -554,24 +519,19 @@ STATIC int | |||
554 | xfs_file_open_exec( | 519 | xfs_file_open_exec( |
555 | struct inode *inode) | 520 | struct inode *inode) |
556 | { | 521 | { |
557 | vnode_t *vp = vn_from_inode(inode); | 522 | bhv_vnode_t *vp = vn_from_inode(inode); |
558 | xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); | ||
559 | int error = 0; | ||
560 | xfs_inode_t *ip; | ||
561 | 523 | ||
562 | if (vp->v_vfsp->vfs_flag & VFS_DMI) { | 524 | if (unlikely(vp->v_vfsp->vfs_flag & VFS_DMI)) { |
563 | ip = xfs_vtoi(vp); | 525 | xfs_mount_t *mp = XFS_VFSTOM(vp->v_vfsp); |
564 | if (!ip) { | 526 | xfs_inode_t *ip = xfs_vtoi(vp); |
565 | error = -EINVAL; | 527 | |
566 | goto open_exec_out; | 528 | if (!ip) |
567 | } | 529 | return -EINVAL; |
568 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) { | 530 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ)) |
569 | error = -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, | 531 | return -XFS_SEND_DATA(mp, DM_EVENT_READ, vp, |
570 | 0, 0, 0, NULL); | 532 | 0, 0, 0, NULL); |
571 | } | ||
572 | } | 533 | } |
573 | open_exec_out: | 534 | return 0; |
574 | return error; | ||
575 | } | 535 | } |
576 | #endif /* HAVE_FOP_OPEN_EXEC */ | 536 | #endif /* HAVE_FOP_OPEN_EXEC */ |
577 | 537 | ||
@@ -592,6 +552,7 @@ const struct file_operations xfs_file_operations = { | |||
592 | #endif | 552 | #endif |
593 | .mmap = xfs_file_mmap, | 553 | .mmap = xfs_file_mmap, |
594 | .open = xfs_file_open, | 554 | .open = xfs_file_open, |
555 | .flush = xfs_file_close, | ||
595 | .release = xfs_file_release, | 556 | .release = xfs_file_release, |
596 | .fsync = xfs_file_fsync, | 557 | .fsync = xfs_file_fsync, |
597 | #ifdef HAVE_FOP_OPEN_EXEC | 558 | #ifdef HAVE_FOP_OPEN_EXEC |
@@ -616,6 +577,7 @@ const struct file_operations xfs_invis_file_operations = { | |||
616 | #endif | 577 | #endif |
617 | .mmap = xfs_file_mmap, | 578 | .mmap = xfs_file_mmap, |
618 | .open = xfs_file_open, | 579 | .open = xfs_file_open, |
580 | .flush = xfs_file_close, | ||
619 | .release = xfs_file_release, | 581 | .release = xfs_file_release, |
620 | .fsync = xfs_file_fsync, | 582 | .fsync = xfs_file_fsync, |
621 | }; | 583 | }; |
diff --git a/fs/xfs/linux-2.6/xfs_fs_subr.c b/fs/xfs/linux-2.6/xfs_fs_subr.c index 575f2a790f31..dc0562828e76 100644 --- a/fs/xfs/linux-2.6/xfs_fs_subr.c +++ b/fs/xfs/linux-2.6/xfs_fs_subr.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2002,2005-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -15,40 +15,12 @@ | |||
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | |||
19 | #include "xfs.h" | 18 | #include "xfs.h" |
20 | 19 | ||
21 | /* | 20 | int fs_noerr(void) { return 0; } |
22 | * Stub for no-op vnode operations that return error status. | 21 | int fs_nosys(void) { return ENOSYS; } |
23 | */ | 22 | void fs_noval(void) { return; } |
24 | int | ||
25 | fs_noerr(void) | ||
26 | { | ||
27 | return 0; | ||
28 | } | ||
29 | 23 | ||
30 | /* | ||
31 | * Operation unsupported under this file system. | ||
32 | */ | ||
33 | int | ||
34 | fs_nosys(void) | ||
35 | { | ||
36 | return ENOSYS; | ||
37 | } | ||
38 | |||
39 | /* | ||
40 | * Stub for inactive, strategy, and read/write lock/unlock. Does nothing. | ||
41 | */ | ||
42 | /* ARGSUSED */ | ||
43 | void | ||
44 | fs_noval(void) | ||
45 | { | ||
46 | } | ||
47 | |||
48 | /* | ||
49 | * vnode pcache layer for vnode_tosspages. | ||
50 | * 'last' parameter unused but left in for IRIX compatibility | ||
51 | */ | ||
52 | void | 24 | void |
53 | fs_tosspages( | 25 | fs_tosspages( |
54 | bhv_desc_t *bdp, | 26 | bhv_desc_t *bdp, |
@@ -56,18 +28,13 @@ fs_tosspages( | |||
56 | xfs_off_t last, | 28 | xfs_off_t last, |
57 | int fiopt) | 29 | int fiopt) |
58 | { | 30 | { |
59 | vnode_t *vp = BHV_TO_VNODE(bdp); | 31 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); |
60 | struct inode *ip = vn_to_inode(vp); | 32 | struct inode *ip = vn_to_inode(vp); |
61 | 33 | ||
62 | if (VN_CACHED(vp)) | 34 | if (VN_CACHED(vp)) |
63 | truncate_inode_pages(ip->i_mapping, first); | 35 | truncate_inode_pages(ip->i_mapping, first); |
64 | } | 36 | } |
65 | 37 | ||
66 | |||
67 | /* | ||
68 | * vnode pcache layer for vnode_flushinval_pages. | ||
69 | * 'last' parameter unused but left in for IRIX compatibility | ||
70 | */ | ||
71 | void | 38 | void |
72 | fs_flushinval_pages( | 39 | fs_flushinval_pages( |
73 | bhv_desc_t *bdp, | 40 | bhv_desc_t *bdp, |
@@ -75,20 +42,17 @@ fs_flushinval_pages( | |||
75 | xfs_off_t last, | 42 | xfs_off_t last, |
76 | int fiopt) | 43 | int fiopt) |
77 | { | 44 | { |
78 | vnode_t *vp = BHV_TO_VNODE(bdp); | 45 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); |
79 | struct inode *ip = vn_to_inode(vp); | 46 | struct inode *ip = vn_to_inode(vp); |
80 | 47 | ||
81 | if (VN_CACHED(vp)) { | 48 | if (VN_CACHED(vp)) { |
49 | if (VN_TRUNC(vp)) | ||
50 | VUNTRUNCATE(vp); | ||
82 | filemap_write_and_wait(ip->i_mapping); | 51 | filemap_write_and_wait(ip->i_mapping); |
83 | |||
84 | truncate_inode_pages(ip->i_mapping, first); | 52 | truncate_inode_pages(ip->i_mapping, first); |
85 | } | 53 | } |
86 | } | 54 | } |
87 | 55 | ||
88 | /* | ||
89 | * vnode pcache layer for vnode_flush_pages. | ||
90 | * 'last' parameter unused but left in for IRIX compatibility | ||
91 | */ | ||
92 | int | 56 | int |
93 | fs_flush_pages( | 57 | fs_flush_pages( |
94 | bhv_desc_t *bdp, | 58 | bhv_desc_t *bdp, |
@@ -97,15 +61,16 @@ fs_flush_pages( | |||
97 | uint64_t flags, | 61 | uint64_t flags, |
98 | int fiopt) | 62 | int fiopt) |
99 | { | 63 | { |
100 | vnode_t *vp = BHV_TO_VNODE(bdp); | 64 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); |
101 | struct inode *ip = vn_to_inode(vp); | 65 | struct inode *ip = vn_to_inode(vp); |
102 | 66 | ||
103 | if (VN_CACHED(vp)) { | 67 | if (VN_DIRTY(vp)) { |
68 | if (VN_TRUNC(vp)) | ||
69 | VUNTRUNCATE(vp); | ||
104 | filemap_fdatawrite(ip->i_mapping); | 70 | filemap_fdatawrite(ip->i_mapping); |
105 | if (flags & XFS_B_ASYNC) | 71 | if (flags & XFS_B_ASYNC) |
106 | return 0; | 72 | return 0; |
107 | filemap_fdatawait(ip->i_mapping); | 73 | filemap_fdatawait(ip->i_mapping); |
108 | } | 74 | } |
109 | |||
110 | return 0; | 75 | return 0; |
111 | } | 76 | } |
diff --git a/fs/xfs/linux-2.6/xfs_globals.c b/fs/xfs/linux-2.6/xfs_globals.c index 6e8085f34635..6c162c3dde7e 100644 --- a/fs/xfs/linux-2.6/xfs_globals.c +++ b/fs/xfs/linux-2.6/xfs_globals.c | |||
@@ -45,6 +45,7 @@ xfs_param_t xfs_params = { | |||
45 | .xfs_buf_age = { 1*100, 15*100, 7200*100}, | 45 | .xfs_buf_age = { 1*100, 15*100, 7200*100}, |
46 | .inherit_nosym = { 0, 0, 1 }, | 46 | .inherit_nosym = { 0, 0, 1 }, |
47 | .rotorstep = { 1, 1, 255 }, | 47 | .rotorstep = { 1, 1, 255 }, |
48 | .inherit_nodfrg = { 0, 1, 1 }, | ||
48 | }; | 49 | }; |
49 | 50 | ||
50 | /* | 51 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 84478491609b..6e52a5dd38d8 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -31,7 +30,6 @@ | |||
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_attr_sf.h" | 33 | #include "xfs_attr_sf.h" |
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -78,7 +76,7 @@ xfs_find_handle( | |||
78 | xfs_handle_t handle; | 76 | xfs_handle_t handle; |
79 | xfs_fsop_handlereq_t hreq; | 77 | xfs_fsop_handlereq_t hreq; |
80 | struct inode *inode; | 78 | struct inode *inode; |
81 | struct vnode *vp; | 79 | bhv_vnode_t *vp; |
82 | 80 | ||
83 | if (copy_from_user(&hreq, arg, sizeof(hreq))) | 81 | if (copy_from_user(&hreq, arg, sizeof(hreq))) |
84 | return -XFS_ERROR(EFAULT); | 82 | return -XFS_ERROR(EFAULT); |
@@ -192,7 +190,7 @@ xfs_vget_fsop_handlereq( | |||
192 | xfs_mount_t *mp, | 190 | xfs_mount_t *mp, |
193 | struct inode *parinode, /* parent inode pointer */ | 191 | struct inode *parinode, /* parent inode pointer */ |
194 | xfs_fsop_handlereq_t *hreq, | 192 | xfs_fsop_handlereq_t *hreq, |
195 | vnode_t **vp, | 193 | bhv_vnode_t **vp, |
196 | struct inode **inode) | 194 | struct inode **inode) |
197 | { | 195 | { |
198 | void __user *hanp; | 196 | void __user *hanp; |
@@ -202,7 +200,7 @@ xfs_vget_fsop_handlereq( | |||
202 | xfs_handle_t handle; | 200 | xfs_handle_t handle; |
203 | xfs_inode_t *ip; | 201 | xfs_inode_t *ip; |
204 | struct inode *inodep; | 202 | struct inode *inodep; |
205 | vnode_t *vpp; | 203 | bhv_vnode_t *vpp; |
206 | xfs_ino_t ino; | 204 | xfs_ino_t ino; |
207 | __u32 igen; | 205 | __u32 igen; |
208 | int error; | 206 | int error; |
@@ -277,7 +275,7 @@ xfs_open_by_handle( | |||
277 | struct file *filp; | 275 | struct file *filp; |
278 | struct inode *inode; | 276 | struct inode *inode; |
279 | struct dentry *dentry; | 277 | struct dentry *dentry; |
280 | vnode_t *vp; | 278 | bhv_vnode_t *vp; |
281 | xfs_fsop_handlereq_t hreq; | 279 | xfs_fsop_handlereq_t hreq; |
282 | 280 | ||
283 | if (!capable(CAP_SYS_ADMIN)) | 281 | if (!capable(CAP_SYS_ADMIN)) |
@@ -362,7 +360,7 @@ xfs_readlink_by_handle( | |||
362 | struct uio auio; | 360 | struct uio auio; |
363 | struct inode *inode; | 361 | struct inode *inode; |
364 | xfs_fsop_handlereq_t hreq; | 362 | xfs_fsop_handlereq_t hreq; |
365 | vnode_t *vp; | 363 | bhv_vnode_t *vp; |
366 | __u32 olen; | 364 | __u32 olen; |
367 | 365 | ||
368 | if (!capable(CAP_SYS_ADMIN)) | 366 | if (!capable(CAP_SYS_ADMIN)) |
@@ -393,9 +391,11 @@ xfs_readlink_by_handle( | |||
393 | auio.uio_segflg = UIO_USERSPACE; | 391 | auio.uio_segflg = UIO_USERSPACE; |
394 | auio.uio_resid = olen; | 392 | auio.uio_resid = olen; |
395 | 393 | ||
396 | VOP_READLINK(vp, &auio, IO_INVIS, NULL, error); | 394 | error = bhv_vop_readlink(vp, &auio, IO_INVIS, NULL); |
397 | |||
398 | VN_RELE(vp); | 395 | VN_RELE(vp); |
396 | if (error) | ||
397 | return -error; | ||
398 | |||
399 | return (olen - auio.uio_resid); | 399 | return (olen - auio.uio_resid); |
400 | } | 400 | } |
401 | 401 | ||
@@ -411,7 +411,7 @@ xfs_fssetdm_by_handle( | |||
411 | xfs_fsop_setdm_handlereq_t dmhreq; | 411 | xfs_fsop_setdm_handlereq_t dmhreq; |
412 | struct inode *inode; | 412 | struct inode *inode; |
413 | bhv_desc_t *bdp; | 413 | bhv_desc_t *bdp; |
414 | vnode_t *vp; | 414 | bhv_vnode_t *vp; |
415 | 415 | ||
416 | if (!capable(CAP_MKNOD)) | 416 | if (!capable(CAP_MKNOD)) |
417 | return -XFS_ERROR(EPERM); | 417 | return -XFS_ERROR(EPERM); |
@@ -452,7 +452,7 @@ xfs_attrlist_by_handle( | |||
452 | attrlist_cursor_kern_t *cursor; | 452 | attrlist_cursor_kern_t *cursor; |
453 | xfs_fsop_attrlist_handlereq_t al_hreq; | 453 | xfs_fsop_attrlist_handlereq_t al_hreq; |
454 | struct inode *inode; | 454 | struct inode *inode; |
455 | vnode_t *vp; | 455 | bhv_vnode_t *vp; |
456 | char *kbuf; | 456 | char *kbuf; |
457 | 457 | ||
458 | if (!capable(CAP_SYS_ADMIN)) | 458 | if (!capable(CAP_SYS_ADMIN)) |
@@ -472,8 +472,8 @@ xfs_attrlist_by_handle( | |||
472 | goto out_vn_rele; | 472 | goto out_vn_rele; |
473 | 473 | ||
474 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; | 474 | cursor = (attrlist_cursor_kern_t *)&al_hreq.pos; |
475 | VOP_ATTR_LIST(vp, kbuf, al_hreq.buflen, al_hreq.flags, | 475 | error = bhv_vop_attr_list(vp, kbuf, al_hreq.buflen, al_hreq.flags, |
476 | cursor, NULL, error); | 476 | cursor, NULL); |
477 | if (error) | 477 | if (error) |
478 | goto out_kfree; | 478 | goto out_kfree; |
479 | 479 | ||
@@ -490,7 +490,7 @@ xfs_attrlist_by_handle( | |||
490 | 490 | ||
491 | STATIC int | 491 | STATIC int |
492 | xfs_attrmulti_attr_get( | 492 | xfs_attrmulti_attr_get( |
493 | struct vnode *vp, | 493 | bhv_vnode_t *vp, |
494 | char *name, | 494 | char *name, |
495 | char __user *ubuf, | 495 | char __user *ubuf, |
496 | __uint32_t *len, | 496 | __uint32_t *len, |
@@ -505,7 +505,7 @@ xfs_attrmulti_attr_get( | |||
505 | if (!kbuf) | 505 | if (!kbuf) |
506 | return ENOMEM; | 506 | return ENOMEM; |
507 | 507 | ||
508 | VOP_ATTR_GET(vp, name, kbuf, len, flags, NULL, error); | 508 | error = bhv_vop_attr_get(vp, name, kbuf, len, flags, NULL); |
509 | if (error) | 509 | if (error) |
510 | goto out_kfree; | 510 | goto out_kfree; |
511 | 511 | ||
@@ -519,7 +519,7 @@ xfs_attrmulti_attr_get( | |||
519 | 519 | ||
520 | STATIC int | 520 | STATIC int |
521 | xfs_attrmulti_attr_set( | 521 | xfs_attrmulti_attr_set( |
522 | struct vnode *vp, | 522 | bhv_vnode_t *vp, |
523 | char *name, | 523 | char *name, |
524 | const char __user *ubuf, | 524 | const char __user *ubuf, |
525 | __uint32_t len, | 525 | __uint32_t len, |
@@ -542,7 +542,7 @@ xfs_attrmulti_attr_set( | |||
542 | if (copy_from_user(kbuf, ubuf, len)) | 542 | if (copy_from_user(kbuf, ubuf, len)) |
543 | goto out_kfree; | 543 | goto out_kfree; |
544 | 544 | ||
545 | VOP_ATTR_SET(vp, name, kbuf, len, flags, NULL, error); | 545 | error = bhv_vop_attr_set(vp, name, kbuf, len, flags, NULL); |
546 | 546 | ||
547 | out_kfree: | 547 | out_kfree: |
548 | kfree(kbuf); | 548 | kfree(kbuf); |
@@ -551,20 +551,15 @@ xfs_attrmulti_attr_set( | |||
551 | 551 | ||
552 | STATIC int | 552 | STATIC int |
553 | xfs_attrmulti_attr_remove( | 553 | xfs_attrmulti_attr_remove( |
554 | struct vnode *vp, | 554 | bhv_vnode_t *vp, |
555 | char *name, | 555 | char *name, |
556 | __uint32_t flags) | 556 | __uint32_t flags) |
557 | { | 557 | { |
558 | int error; | ||
559 | |||
560 | |||
561 | if (IS_RDONLY(&vp->v_inode)) | 558 | if (IS_RDONLY(&vp->v_inode)) |
562 | return -EROFS; | 559 | return -EROFS; |
563 | if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) | 560 | if (IS_IMMUTABLE(&vp->v_inode) || IS_APPEND(&vp->v_inode)) |
564 | return EPERM; | 561 | return EPERM; |
565 | 562 | return bhv_vop_attr_remove(vp, name, flags, NULL); | |
566 | VOP_ATTR_REMOVE(vp, name, flags, NULL, error); | ||
567 | return error; | ||
568 | } | 563 | } |
569 | 564 | ||
570 | STATIC int | 565 | STATIC int |
@@ -578,7 +573,7 @@ xfs_attrmulti_by_handle( | |||
578 | xfs_attr_multiop_t *ops; | 573 | xfs_attr_multiop_t *ops; |
579 | xfs_fsop_attrmulti_handlereq_t am_hreq; | 574 | xfs_fsop_attrmulti_handlereq_t am_hreq; |
580 | struct inode *inode; | 575 | struct inode *inode; |
581 | vnode_t *vp; | 576 | bhv_vnode_t *vp; |
582 | unsigned int i, size; | 577 | unsigned int i, size; |
583 | char *attr_name; | 578 | char *attr_name; |
584 | 579 | ||
@@ -658,7 +653,7 @@ xfs_attrmulti_by_handle( | |||
658 | STATIC int | 653 | STATIC int |
659 | xfs_ioc_space( | 654 | xfs_ioc_space( |
660 | bhv_desc_t *bdp, | 655 | bhv_desc_t *bdp, |
661 | vnode_t *vp, | 656 | bhv_vnode_t *vp, |
662 | struct file *filp, | 657 | struct file *filp, |
663 | int flags, | 658 | int flags, |
664 | unsigned int cmd, | 659 | unsigned int cmd, |
@@ -682,7 +677,7 @@ xfs_ioc_fsgeometry( | |||
682 | 677 | ||
683 | STATIC int | 678 | STATIC int |
684 | xfs_ioc_xattr( | 679 | xfs_ioc_xattr( |
685 | vnode_t *vp, | 680 | bhv_vnode_t *vp, |
686 | xfs_inode_t *ip, | 681 | xfs_inode_t *ip, |
687 | struct file *filp, | 682 | struct file *filp, |
688 | unsigned int cmd, | 683 | unsigned int cmd, |
@@ -711,7 +706,7 @@ xfs_ioctl( | |||
711 | void __user *arg) | 706 | void __user *arg) |
712 | { | 707 | { |
713 | int error; | 708 | int error; |
714 | vnode_t *vp; | 709 | bhv_vnode_t *vp; |
715 | xfs_inode_t *ip; | 710 | xfs_inode_t *ip; |
716 | xfs_mount_t *mp; | 711 | xfs_mount_t *mp; |
717 | 712 | ||
@@ -962,7 +957,7 @@ xfs_ioctl( | |||
962 | STATIC int | 957 | STATIC int |
963 | xfs_ioc_space( | 958 | xfs_ioc_space( |
964 | bhv_desc_t *bdp, | 959 | bhv_desc_t *bdp, |
965 | vnode_t *vp, | 960 | bhv_vnode_t *vp, |
966 | struct file *filp, | 961 | struct file *filp, |
967 | int ioflags, | 962 | int ioflags, |
968 | unsigned int cmd, | 963 | unsigned int cmd, |
@@ -1153,14 +1148,14 @@ xfs_di2lxflags( | |||
1153 | 1148 | ||
1154 | STATIC int | 1149 | STATIC int |
1155 | xfs_ioc_xattr( | 1150 | xfs_ioc_xattr( |
1156 | vnode_t *vp, | 1151 | bhv_vnode_t *vp, |
1157 | xfs_inode_t *ip, | 1152 | xfs_inode_t *ip, |
1158 | struct file *filp, | 1153 | struct file *filp, |
1159 | unsigned int cmd, | 1154 | unsigned int cmd, |
1160 | void __user *arg) | 1155 | void __user *arg) |
1161 | { | 1156 | { |
1162 | struct fsxattr fa; | 1157 | struct fsxattr fa; |
1163 | struct vattr *vattr; | 1158 | struct bhv_vattr *vattr; |
1164 | int error = 0; | 1159 | int error = 0; |
1165 | int attr_flags; | 1160 | int attr_flags; |
1166 | unsigned int flags; | 1161 | unsigned int flags; |
@@ -1173,7 +1168,7 @@ xfs_ioc_xattr( | |||
1173 | case XFS_IOC_FSGETXATTR: { | 1168 | case XFS_IOC_FSGETXATTR: { |
1174 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ | 1169 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ |
1175 | XFS_AT_NEXTENTS | XFS_AT_PROJID; | 1170 | XFS_AT_NEXTENTS | XFS_AT_PROJID; |
1176 | VOP_GETATTR(vp, vattr, 0, NULL, error); | 1171 | error = bhv_vop_getattr(vp, vattr, 0, NULL); |
1177 | if (unlikely(error)) { | 1172 | if (unlikely(error)) { |
1178 | error = -error; | 1173 | error = -error; |
1179 | break; | 1174 | break; |
@@ -1206,7 +1201,7 @@ xfs_ioc_xattr( | |||
1206 | vattr->va_extsize = fa.fsx_extsize; | 1201 | vattr->va_extsize = fa.fsx_extsize; |
1207 | vattr->va_projid = fa.fsx_projid; | 1202 | vattr->va_projid = fa.fsx_projid; |
1208 | 1203 | ||
1209 | VOP_SETATTR(vp, vattr, attr_flags, NULL, error); | 1204 | error = bhv_vop_setattr(vp, vattr, attr_flags, NULL); |
1210 | if (likely(!error)) | 1205 | if (likely(!error)) |
1211 | __vn_revalidate(vp, vattr); /* update flags */ | 1206 | __vn_revalidate(vp, vattr); /* update flags */ |
1212 | error = -error; | 1207 | error = -error; |
@@ -1216,7 +1211,7 @@ xfs_ioc_xattr( | |||
1216 | case XFS_IOC_FSGETXATTRA: { | 1211 | case XFS_IOC_FSGETXATTRA: { |
1217 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ | 1212 | vattr->va_mask = XFS_AT_XFLAGS | XFS_AT_EXTSIZE | \ |
1218 | XFS_AT_ANEXTENTS | XFS_AT_PROJID; | 1213 | XFS_AT_ANEXTENTS | XFS_AT_PROJID; |
1219 | VOP_GETATTR(vp, vattr, 0, NULL, error); | 1214 | error = bhv_vop_getattr(vp, vattr, 0, NULL); |
1220 | if (unlikely(error)) { | 1215 | if (unlikely(error)) { |
1221 | error = -error; | 1216 | error = -error; |
1222 | break; | 1217 | break; |
@@ -1262,7 +1257,7 @@ xfs_ioc_xattr( | |||
1262 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, | 1257 | vattr->va_xflags = xfs_merge_ioc_xflags(flags, |
1263 | xfs_ip2xflags(ip)); | 1258 | xfs_ip2xflags(ip)); |
1264 | 1259 | ||
1265 | VOP_SETATTR(vp, vattr, attr_flags, NULL, error); | 1260 | error = bhv_vop_setattr(vp, vattr, attr_flags, NULL); |
1266 | if (likely(!error)) | 1261 | if (likely(!error)) |
1267 | __vn_revalidate(vp, vattr); /* update flags */ | 1262 | __vn_revalidate(vp, vattr); /* update flags */ |
1268 | error = -error; | 1263 | error = -error; |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl32.c b/fs/xfs/linux-2.6/xfs_ioctl32.c index 251bfe451a3f..601f01c92f7f 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl32.c +++ b/fs/xfs/linux-2.6/xfs_ioctl32.c | |||
@@ -114,7 +114,7 @@ xfs_compat_ioctl( | |||
114 | unsigned long arg) | 114 | unsigned long arg) |
115 | { | 115 | { |
116 | struct inode *inode = file->f_dentry->d_inode; | 116 | struct inode *inode = file->f_dentry->d_inode; |
117 | vnode_t *vp = vn_from_inode(inode); | 117 | bhv_vnode_t *vp = vn_from_inode(inode); |
118 | int error; | 118 | int error; |
119 | 119 | ||
120 | switch (cmd) { | 120 | switch (cmd) { |
@@ -193,7 +193,7 @@ xfs_compat_ioctl( | |||
193 | return -ENOIOCTLCMD; | 193 | return -ENOIOCTLCMD; |
194 | } | 194 | } |
195 | 195 | ||
196 | VOP_IOCTL(vp, inode, file, mode, cmd, (void __user *)arg, error); | 196 | error = bhv_vop_ioctl(vp, inode, file, mode, cmd, (void __user *)arg); |
197 | VMODIFY(vp); | 197 | VMODIFY(vp); |
198 | 198 | ||
199 | return error; | 199 | return error; |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 2e2e275c786f..12810baeb5d4 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -61,7 +59,7 @@ | |||
61 | */ | 59 | */ |
62 | xfs_inode_t * | 60 | xfs_inode_t * |
63 | xfs_vtoi( | 61 | xfs_vtoi( |
64 | struct vnode *vp) | 62 | bhv_vnode_t *vp) |
65 | { | 63 | { |
66 | bhv_desc_t *bdp; | 64 | bhv_desc_t *bdp; |
67 | 65 | ||
@@ -80,7 +78,7 @@ void | |||
80 | xfs_synchronize_atime( | 78 | xfs_synchronize_atime( |
81 | xfs_inode_t *ip) | 79 | xfs_inode_t *ip) |
82 | { | 80 | { |
83 | vnode_t *vp; | 81 | bhv_vnode_t *vp; |
84 | 82 | ||
85 | vp = XFS_ITOV_NULL(ip); | 83 | vp = XFS_ITOV_NULL(ip); |
86 | if (vp) { | 84 | if (vp) { |
@@ -200,14 +198,10 @@ xfs_ichgtime_fast( | |||
200 | STATIC void | 198 | STATIC void |
201 | xfs_validate_fields( | 199 | xfs_validate_fields( |
202 | struct inode *ip, | 200 | struct inode *ip, |
203 | struct vattr *vattr) | 201 | bhv_vattr_t *vattr) |
204 | { | 202 | { |
205 | vnode_t *vp = vn_from_inode(ip); | ||
206 | int error; | ||
207 | |||
208 | vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; | 203 | vattr->va_mask = XFS_AT_NLINK|XFS_AT_SIZE|XFS_AT_NBLOCKS; |
209 | VOP_GETATTR(vp, vattr, ATTR_LAZY, NULL, error); | 204 | if (!bhv_vop_getattr(vn_from_inode(ip), vattr, ATTR_LAZY, NULL)) { |
210 | if (likely(!error)) { | ||
211 | ip->i_nlink = vattr->va_nlink; | 205 | ip->i_nlink = vattr->va_nlink; |
212 | ip->i_blocks = vattr->va_nblocks; | 206 | ip->i_blocks = vattr->va_nblocks; |
213 | 207 | ||
@@ -225,7 +219,7 @@ xfs_validate_fields( | |||
225 | */ | 219 | */ |
226 | STATIC int | 220 | STATIC int |
227 | xfs_init_security( | 221 | xfs_init_security( |
228 | struct vnode *vp, | 222 | bhv_vnode_t *vp, |
229 | struct inode *dir) | 223 | struct inode *dir) |
230 | { | 224 | { |
231 | struct inode *ip = vn_to_inode(vp); | 225 | struct inode *ip = vn_to_inode(vp); |
@@ -241,7 +235,7 @@ xfs_init_security( | |||
241 | return -error; | 235 | return -error; |
242 | } | 236 | } |
243 | 237 | ||
244 | VOP_ATTR_SET(vp, name, value, length, ATTR_SECURE, NULL, error); | 238 | error = bhv_vop_attr_set(vp, name, value, length, ATTR_SECURE, NULL); |
245 | if (!error) | 239 | if (!error) |
246 | VMODIFY(vp); | 240 | VMODIFY(vp); |
247 | 241 | ||
@@ -264,13 +258,12 @@ xfs_has_fs_struct(struct task_struct *task) | |||
264 | 258 | ||
265 | STATIC inline void | 259 | STATIC inline void |
266 | xfs_cleanup_inode( | 260 | xfs_cleanup_inode( |
267 | vnode_t *dvp, | 261 | bhv_vnode_t *dvp, |
268 | vnode_t *vp, | 262 | bhv_vnode_t *vp, |
269 | struct dentry *dentry, | 263 | struct dentry *dentry, |
270 | int mode) | 264 | int mode) |
271 | { | 265 | { |
272 | struct dentry teardown = {}; | 266 | struct dentry teardown = {}; |
273 | int error; | ||
274 | 267 | ||
275 | /* Oh, the horror. | 268 | /* Oh, the horror. |
276 | * If we can't add the ACL or we fail in | 269 | * If we can't add the ACL or we fail in |
@@ -281,9 +274,9 @@ xfs_cleanup_inode( | |||
281 | teardown.d_name = dentry->d_name; | 274 | teardown.d_name = dentry->d_name; |
282 | 275 | ||
283 | if (S_ISDIR(mode)) | 276 | if (S_ISDIR(mode)) |
284 | VOP_RMDIR(dvp, &teardown, NULL, error); | 277 | bhv_vop_rmdir(dvp, &teardown, NULL); |
285 | else | 278 | else |
286 | VOP_REMOVE(dvp, &teardown, NULL, error); | 279 | bhv_vop_remove(dvp, &teardown, NULL); |
287 | VN_RELE(vp); | 280 | VN_RELE(vp); |
288 | } | 281 | } |
289 | 282 | ||
@@ -295,8 +288,8 @@ xfs_vn_mknod( | |||
295 | dev_t rdev) | 288 | dev_t rdev) |
296 | { | 289 | { |
297 | struct inode *ip; | 290 | struct inode *ip; |
298 | vattr_t vattr = { 0 }; | 291 | bhv_vattr_t vattr = { 0 }; |
299 | vnode_t *vp = NULL, *dvp = vn_from_inode(dir); | 292 | bhv_vnode_t *vp = NULL, *dvp = vn_from_inode(dir); |
300 | xfs_acl_t *default_acl = NULL; | 293 | xfs_acl_t *default_acl = NULL; |
301 | attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; | 294 | attrexists_t test_default_acl = _ACL_DEFAULT_EXISTS; |
302 | int error; | 295 | int error; |
@@ -330,10 +323,10 @@ xfs_vn_mknod( | |||
330 | vattr.va_mask |= XFS_AT_RDEV; | 323 | vattr.va_mask |= XFS_AT_RDEV; |
331 | /*FALLTHROUGH*/ | 324 | /*FALLTHROUGH*/ |
332 | case S_IFREG: | 325 | case S_IFREG: |
333 | VOP_CREATE(dvp, dentry, &vattr, &vp, NULL, error); | 326 | error = bhv_vop_create(dvp, dentry, &vattr, &vp, NULL); |
334 | break; | 327 | break; |
335 | case S_IFDIR: | 328 | case S_IFDIR: |
336 | VOP_MKDIR(dvp, dentry, &vattr, &vp, NULL, error); | 329 | error = bhv_vop_mkdir(dvp, dentry, &vattr, &vp, NULL); |
337 | break; | 330 | break; |
338 | default: | 331 | default: |
339 | error = EINVAL; | 332 | error = EINVAL; |
@@ -396,14 +389,14 @@ xfs_vn_lookup( | |||
396 | struct dentry *dentry, | 389 | struct dentry *dentry, |
397 | struct nameidata *nd) | 390 | struct nameidata *nd) |
398 | { | 391 | { |
399 | struct vnode *vp = vn_from_inode(dir), *cvp; | 392 | bhv_vnode_t *vp = vn_from_inode(dir), *cvp; |
400 | int error; | 393 | int error; |
401 | 394 | ||
402 | if (dentry->d_name.len >= MAXNAMELEN) | 395 | if (dentry->d_name.len >= MAXNAMELEN) |
403 | return ERR_PTR(-ENAMETOOLONG); | 396 | return ERR_PTR(-ENAMETOOLONG); |
404 | 397 | ||
405 | VOP_LOOKUP(vp, dentry, &cvp, 0, NULL, NULL, error); | 398 | error = bhv_vop_lookup(vp, dentry, &cvp, 0, NULL, NULL); |
406 | if (error) { | 399 | if (unlikely(error)) { |
407 | if (unlikely(error != ENOENT)) | 400 | if (unlikely(error != ENOENT)) |
408 | return ERR_PTR(-error); | 401 | return ERR_PTR(-error); |
409 | d_add(dentry, NULL); | 402 | d_add(dentry, NULL); |
@@ -420,9 +413,9 @@ xfs_vn_link( | |||
420 | struct dentry *dentry) | 413 | struct dentry *dentry) |
421 | { | 414 | { |
422 | struct inode *ip; /* inode of guy being linked to */ | 415 | struct inode *ip; /* inode of guy being linked to */ |
423 | vnode_t *tdvp; /* target directory for new name/link */ | 416 | bhv_vnode_t *tdvp; /* target directory for new name/link */ |
424 | vnode_t *vp; /* vp of name being linked */ | 417 | bhv_vnode_t *vp; /* vp of name being linked */ |
425 | vattr_t vattr; | 418 | bhv_vattr_t vattr; |
426 | int error; | 419 | int error; |
427 | 420 | ||
428 | ip = old_dentry->d_inode; /* inode being linked to */ | 421 | ip = old_dentry->d_inode; /* inode being linked to */ |
@@ -432,7 +425,7 @@ xfs_vn_link( | |||
432 | tdvp = vn_from_inode(dir); | 425 | tdvp = vn_from_inode(dir); |
433 | vp = vn_from_inode(ip); | 426 | vp = vn_from_inode(ip); |
434 | 427 | ||
435 | VOP_LINK(tdvp, vp, dentry, NULL, error); | 428 | error = bhv_vop_link(tdvp, vp, dentry, NULL); |
436 | if (likely(!error)) { | 429 | if (likely(!error)) { |
437 | VMODIFY(tdvp); | 430 | VMODIFY(tdvp); |
438 | VN_HOLD(vp); | 431 | VN_HOLD(vp); |
@@ -448,14 +441,14 @@ xfs_vn_unlink( | |||
448 | struct dentry *dentry) | 441 | struct dentry *dentry) |
449 | { | 442 | { |
450 | struct inode *inode; | 443 | struct inode *inode; |
451 | vnode_t *dvp; /* directory containing name to remove */ | 444 | bhv_vnode_t *dvp; /* directory containing name to remove */ |
452 | vattr_t vattr; | 445 | bhv_vattr_t vattr; |
453 | int error; | 446 | int error; |
454 | 447 | ||
455 | inode = dentry->d_inode; | 448 | inode = dentry->d_inode; |
456 | dvp = vn_from_inode(dir); | 449 | dvp = vn_from_inode(dir); |
457 | 450 | ||
458 | VOP_REMOVE(dvp, dentry, NULL, error); | 451 | error = bhv_vop_remove(dvp, dentry, NULL); |
459 | if (likely(!error)) { | 452 | if (likely(!error)) { |
460 | xfs_validate_fields(dir, &vattr); /* size needs update */ | 453 | xfs_validate_fields(dir, &vattr); /* size needs update */ |
461 | xfs_validate_fields(inode, &vattr); | 454 | xfs_validate_fields(inode, &vattr); |
@@ -470,27 +463,26 @@ xfs_vn_symlink( | |||
470 | const char *symname) | 463 | const char *symname) |
471 | { | 464 | { |
472 | struct inode *ip; | 465 | struct inode *ip; |
473 | vattr_t vattr = { 0 }; | 466 | bhv_vattr_t va = { 0 }; |
474 | vnode_t *dvp; /* directory containing name of symlink */ | 467 | bhv_vnode_t *dvp; /* directory containing name of symlink */ |
475 | vnode_t *cvp; /* used to lookup symlink to put in dentry */ | 468 | bhv_vnode_t *cvp; /* used to lookup symlink to put in dentry */ |
476 | int error; | 469 | int error; |
477 | 470 | ||
478 | dvp = vn_from_inode(dir); | 471 | dvp = vn_from_inode(dir); |
479 | cvp = NULL; | 472 | cvp = NULL; |
480 | 473 | ||
481 | vattr.va_mode = S_IFLNK | | 474 | va.va_mode = S_IFLNK | |
482 | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); | 475 | (irix_symlink_mode ? 0777 & ~current->fs->umask : S_IRWXUGO); |
483 | vattr.va_mask = XFS_AT_TYPE|XFS_AT_MODE; | 476 | va.va_mask = XFS_AT_TYPE|XFS_AT_MODE; |
484 | 477 | ||
485 | error = 0; | 478 | error = bhv_vop_symlink(dvp, dentry, &va, (char *)symname, &cvp, NULL); |
486 | VOP_SYMLINK(dvp, dentry, &vattr, (char *)symname, &cvp, NULL, error); | ||
487 | if (likely(!error && cvp)) { | 479 | if (likely(!error && cvp)) { |
488 | error = xfs_init_security(cvp, dir); | 480 | error = xfs_init_security(cvp, dir); |
489 | if (likely(!error)) { | 481 | if (likely(!error)) { |
490 | ip = vn_to_inode(cvp); | 482 | ip = vn_to_inode(cvp); |
491 | d_instantiate(dentry, ip); | 483 | d_instantiate(dentry, ip); |
492 | xfs_validate_fields(dir, &vattr); | 484 | xfs_validate_fields(dir, &va); |
493 | xfs_validate_fields(ip, &vattr); | 485 | xfs_validate_fields(ip, &va); |
494 | } else { | 486 | } else { |
495 | xfs_cleanup_inode(dvp, cvp, dentry, 0); | 487 | xfs_cleanup_inode(dvp, cvp, dentry, 0); |
496 | } | 488 | } |
@@ -504,11 +496,11 @@ xfs_vn_rmdir( | |||
504 | struct dentry *dentry) | 496 | struct dentry *dentry) |
505 | { | 497 | { |
506 | struct inode *inode = dentry->d_inode; | 498 | struct inode *inode = dentry->d_inode; |
507 | vnode_t *dvp = vn_from_inode(dir); | 499 | bhv_vnode_t *dvp = vn_from_inode(dir); |
508 | vattr_t vattr; | 500 | bhv_vattr_t vattr; |
509 | int error; | 501 | int error; |
510 | 502 | ||
511 | VOP_RMDIR(dvp, dentry, NULL, error); | 503 | error = bhv_vop_rmdir(dvp, dentry, NULL); |
512 | if (likely(!error)) { | 504 | if (likely(!error)) { |
513 | xfs_validate_fields(inode, &vattr); | 505 | xfs_validate_fields(inode, &vattr); |
514 | xfs_validate_fields(dir, &vattr); | 506 | xfs_validate_fields(dir, &vattr); |
@@ -524,15 +516,15 @@ xfs_vn_rename( | |||
524 | struct dentry *ndentry) | 516 | struct dentry *ndentry) |
525 | { | 517 | { |
526 | struct inode *new_inode = ndentry->d_inode; | 518 | struct inode *new_inode = ndentry->d_inode; |
527 | vnode_t *fvp; /* from directory */ | 519 | bhv_vnode_t *fvp; /* from directory */ |
528 | vnode_t *tvp; /* target directory */ | 520 | bhv_vnode_t *tvp; /* target directory */ |
529 | vattr_t vattr; | 521 | bhv_vattr_t vattr; |
530 | int error; | 522 | int error; |
531 | 523 | ||
532 | fvp = vn_from_inode(odir); | 524 | fvp = vn_from_inode(odir); |
533 | tvp = vn_from_inode(ndir); | 525 | tvp = vn_from_inode(ndir); |
534 | 526 | ||
535 | VOP_RENAME(fvp, odentry, tvp, ndentry, NULL, error); | 527 | error = bhv_vop_rename(fvp, odentry, tvp, ndentry, NULL); |
536 | if (likely(!error)) { | 528 | if (likely(!error)) { |
537 | if (new_inode) | 529 | if (new_inode) |
538 | xfs_validate_fields(new_inode, &vattr); | 530 | xfs_validate_fields(new_inode, &vattr); |
@@ -553,7 +545,7 @@ xfs_vn_follow_link( | |||
553 | struct dentry *dentry, | 545 | struct dentry *dentry, |
554 | struct nameidata *nd) | 546 | struct nameidata *nd) |
555 | { | 547 | { |
556 | vnode_t *vp; | 548 | bhv_vnode_t *vp; |
557 | uio_t *uio; | 549 | uio_t *uio; |
558 | iovec_t iov; | 550 | iovec_t iov; |
559 | int error; | 551 | int error; |
@@ -586,8 +578,8 @@ xfs_vn_follow_link( | |||
586 | uio->uio_resid = MAXPATHLEN; | 578 | uio->uio_resid = MAXPATHLEN; |
587 | uio->uio_iovcnt = 1; | 579 | uio->uio_iovcnt = 1; |
588 | 580 | ||
589 | VOP_READLINK(vp, uio, 0, NULL, error); | 581 | error = bhv_vop_readlink(vp, uio, 0, NULL); |
590 | if (error) { | 582 | if (unlikely(error)) { |
591 | kfree(link); | 583 | kfree(link); |
592 | link = ERR_PTR(-error); | 584 | link = ERR_PTR(-error); |
593 | } else { | 585 | } else { |
@@ -618,12 +610,7 @@ xfs_vn_permission( | |||
618 | int mode, | 610 | int mode, |
619 | struct nameidata *nd) | 611 | struct nameidata *nd) |
620 | { | 612 | { |
621 | vnode_t *vp = vn_from_inode(inode); | 613 | return -bhv_vop_access(vn_from_inode(inode), mode << 6, NULL); |
622 | int error; | ||
623 | |||
624 | mode <<= 6; /* convert from linux to vnode access bits */ | ||
625 | VOP_ACCESS(vp, mode, NULL, error); | ||
626 | return -error; | ||
627 | } | 614 | } |
628 | #else | 615 | #else |
629 | #define xfs_vn_permission NULL | 616 | #define xfs_vn_permission NULL |
@@ -636,14 +623,14 @@ xfs_vn_getattr( | |||
636 | struct kstat *stat) | 623 | struct kstat *stat) |
637 | { | 624 | { |
638 | struct inode *inode = dentry->d_inode; | 625 | struct inode *inode = dentry->d_inode; |
639 | vnode_t *vp = vn_from_inode(inode); | 626 | bhv_vnode_t *vp = vn_from_inode(inode); |
640 | int error = 0; | 627 | int error = 0; |
641 | 628 | ||
642 | if (unlikely(vp->v_flag & VMODIFIED)) | 629 | if (unlikely(vp->v_flag & VMODIFIED)) |
643 | error = vn_revalidate(vp); | 630 | error = vn_revalidate(vp); |
644 | if (!error) | 631 | if (!error) |
645 | generic_fillattr(inode, stat); | 632 | generic_fillattr(inode, stat); |
646 | return 0; | 633 | return -error; |
647 | } | 634 | } |
648 | 635 | ||
649 | STATIC int | 636 | STATIC int |
@@ -653,8 +640,8 @@ xfs_vn_setattr( | |||
653 | { | 640 | { |
654 | struct inode *inode = dentry->d_inode; | 641 | struct inode *inode = dentry->d_inode; |
655 | unsigned int ia_valid = attr->ia_valid; | 642 | unsigned int ia_valid = attr->ia_valid; |
656 | vnode_t *vp = vn_from_inode(inode); | 643 | bhv_vnode_t *vp = vn_from_inode(inode); |
657 | vattr_t vattr = { 0 }; | 644 | bhv_vattr_t vattr = { 0 }; |
658 | int flags = 0; | 645 | int flags = 0; |
659 | int error; | 646 | int error; |
660 | 647 | ||
@@ -697,7 +684,7 @@ xfs_vn_setattr( | |||
697 | flags |= ATTR_NONBLOCK; | 684 | flags |= ATTR_NONBLOCK; |
698 | #endif | 685 | #endif |
699 | 686 | ||
700 | VOP_SETATTR(vp, &vattr, flags, NULL, error); | 687 | error = bhv_vop_setattr(vp, &vattr, flags, NULL); |
701 | if (likely(!error)) | 688 | if (likely(!error)) |
702 | __vn_revalidate(vp, &vattr); | 689 | __vn_revalidate(vp, &vattr); |
703 | return -error; | 690 | return -error; |
@@ -718,7 +705,7 @@ xfs_vn_setxattr( | |||
718 | size_t size, | 705 | size_t size, |
719 | int flags) | 706 | int flags) |
720 | { | 707 | { |
721 | vnode_t *vp = vn_from_inode(dentry->d_inode); | 708 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
722 | char *attr = (char *)name; | 709 | char *attr = (char *)name; |
723 | attrnames_t *namesp; | 710 | attrnames_t *namesp; |
724 | int xflags = 0; | 711 | int xflags = 0; |
@@ -748,7 +735,7 @@ xfs_vn_getxattr( | |||
748 | void *data, | 735 | void *data, |
749 | size_t size) | 736 | size_t size) |
750 | { | 737 | { |
751 | vnode_t *vp = vn_from_inode(dentry->d_inode); | 738 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
752 | char *attr = (char *)name; | 739 | char *attr = (char *)name; |
753 | attrnames_t *namesp; | 740 | attrnames_t *namesp; |
754 | int xflags = 0; | 741 | int xflags = 0; |
@@ -777,7 +764,7 @@ xfs_vn_listxattr( | |||
777 | char *data, | 764 | char *data, |
778 | size_t size) | 765 | size_t size) |
779 | { | 766 | { |
780 | vnode_t *vp = vn_from_inode(dentry->d_inode); | 767 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
781 | int error, xflags = ATTR_KERNAMELS; | 768 | int error, xflags = ATTR_KERNAMELS; |
782 | ssize_t result; | 769 | ssize_t result; |
783 | 770 | ||
@@ -796,7 +783,7 @@ xfs_vn_removexattr( | |||
796 | struct dentry *dentry, | 783 | struct dentry *dentry, |
797 | const char *name) | 784 | const char *name) |
798 | { | 785 | { |
799 | vnode_t *vp = vn_from_inode(dentry->d_inode); | 786 | bhv_vnode_t *vp = vn_from_inode(dentry->d_inode); |
800 | char *attr = (char *)name; | 787 | char *attr = (char *)name; |
801 | attrnames_t *namesp; | 788 | attrnames_t *namesp; |
802 | int xflags = 0; | 789 | int xflags = 0; |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index e9fe43d74768..aa26ab906c88 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -134,14 +134,21 @@ BUFFER_FNS(PrivateStart, unwritten); | |||
134 | #define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val | 134 | #define xfs_buf_age_centisecs xfs_params.xfs_buf_age.val |
135 | #define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val | 135 | #define xfs_inherit_nosymlinks xfs_params.inherit_nosym.val |
136 | #define xfs_rotorstep xfs_params.rotorstep.val | 136 | #define xfs_rotorstep xfs_params.rotorstep.val |
137 | #define xfs_inherit_nodefrag xfs_params.inherit_nodfrg.val | ||
137 | 138 | ||
138 | #ifndef raw_smp_processor_id | 139 | #define current_cpu() (raw_smp_processor_id()) |
139 | #define raw_smp_processor_id() smp_processor_id() | ||
140 | #endif | ||
141 | #define current_cpu() raw_smp_processor_id() | ||
142 | #define current_pid() (current->pid) | 140 | #define current_pid() (current->pid) |
143 | #define current_fsuid(cred) (current->fsuid) | 141 | #define current_fsuid(cred) (current->fsuid) |
144 | #define current_fsgid(cred) (current->fsgid) | 142 | #define current_fsgid(cred) (current->fsgid) |
143 | #define current_set_flags(f) (current->flags |= (f)) | ||
144 | #define current_test_flags(f) (current->flags & (f)) | ||
145 | #define current_clear_flags(f) (current->flags & ~(f)) | ||
146 | #define current_set_flags_nested(sp, f) \ | ||
147 | (*(sp) = current->flags, current->flags |= (f)) | ||
148 | #define current_clear_flags_nested(sp, f) \ | ||
149 | (*(sp) = current->flags, current->flags &= ~(f)) | ||
150 | #define current_restore_flags_nested(sp, f) \ | ||
151 | (current->flags = ((current->flags & ~(f)) | (*(sp) & (f)))) | ||
145 | 152 | ||
146 | #define NBPP PAGE_SIZE | 153 | #define NBPP PAGE_SIZE |
147 | #define DPPSHFT (PAGE_SHIFT - 9) | 154 | #define DPPSHFT (PAGE_SHIFT - 9) |
@@ -187,25 +194,9 @@ BUFFER_FNS(PrivateStart, unwritten); | |||
187 | /* bytes to clicks */ | 194 | /* bytes to clicks */ |
188 | #define btoc(x) (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT) | 195 | #define btoc(x) (((__psunsigned_t)(x)+(NBPC-1))>>BPCSHIFT) |
189 | 196 | ||
190 | #ifndef ENOATTR | ||
191 | #define ENOATTR ENODATA /* Attribute not found */ | 197 | #define ENOATTR ENODATA /* Attribute not found */ |
192 | #endif | 198 | #define EWRONGFS EINVAL /* Mount with wrong filesystem type */ |
193 | 199 | #define EFSCORRUPTED EUCLEAN /* Filesystem is corrupted */ | |
194 | /* Note: EWRONGFS never visible outside the kernel */ | ||
195 | #define EWRONGFS EINVAL /* Mount with wrong filesystem type */ | ||
196 | |||
197 | /* | ||
198 | * XXX EFSCORRUPTED needs a real value in errno.h. asm-i386/errno.h won't | ||
199 | * return codes out of its known range in errno. | ||
200 | * XXX Also note: needs to be < 1000 and fairly unique on Linux (mustn't | ||
201 | * conflict with any code we use already or any code a driver may use) | ||
202 | * XXX Some options (currently we do #2): | ||
203 | * 1/ New error code ["Filesystem is corrupted", _after_ glibc updated] | ||
204 | * 2/ 990 ["Unknown error 990"] | ||
205 | * 3/ EUCLEAN ["Structure needs cleaning"] | ||
206 | * 4/ Convert EFSCORRUPTED to EIO [just prior to return into userspace] | ||
207 | */ | ||
208 | #define EFSCORRUPTED 990 /* Filesystem is corrupted */ | ||
209 | 200 | ||
210 | #define SYNCHRONIZE() barrier() | 201 | #define SYNCHRONIZE() barrier() |
211 | #define __return_address __builtin_return_address(0) | 202 | #define __return_address __builtin_return_address(0) |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.c b/fs/xfs/linux-2.6/xfs_lrw.c index 67efe3308980..5d9cfd91ad08 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.c +++ b/fs/xfs/linux-2.6/xfs_lrw.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -206,7 +204,7 @@ xfs_read( | |||
206 | xfs_fsize_t n; | 204 | xfs_fsize_t n; |
207 | xfs_inode_t *ip; | 205 | xfs_inode_t *ip; |
208 | xfs_mount_t *mp; | 206 | xfs_mount_t *mp; |
209 | vnode_t *vp; | 207 | bhv_vnode_t *vp; |
210 | unsigned long seg; | 208 | unsigned long seg; |
211 | 209 | ||
212 | ip = XFS_BHVTOI(bdp); | 210 | ip = XFS_BHVTOI(bdp); |
@@ -258,7 +256,7 @@ xfs_read( | |||
258 | 256 | ||
259 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && | 257 | if (DM_EVENT_ENABLED(vp->v_vfsp, ip, DM_EVENT_READ) && |
260 | !(ioflags & IO_INVIS)) { | 258 | !(ioflags & IO_INVIS)) { |
261 | vrwlock_t locktype = VRWLOCK_READ; | 259 | bhv_vrwlock_t locktype = VRWLOCK_READ; |
262 | int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); | 260 | int dmflags = FILP_DELAY_FLAG(file) | DM_SEM_FLAG_RD(ioflags); |
263 | 261 | ||
264 | ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, | 262 | ret = -XFS_SEND_DATA(mp, DM_EVENT_READ, |
@@ -271,7 +269,7 @@ xfs_read( | |||
271 | } | 269 | } |
272 | 270 | ||
273 | if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp))) | 271 | if (unlikely((ioflags & IO_ISDIRECT) && VN_CACHED(vp))) |
274 | VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(*offset)), | 272 | bhv_vop_flushinval_pages(vp, ctooff(offtoct(*offset)), |
275 | -1, FI_REMAPF_LOCKED); | 273 | -1, FI_REMAPF_LOCKED); |
276 | 274 | ||
277 | xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, | 275 | xfs_rw_enter_trace(XFS_READ_ENTER, &ip->i_iocore, |
@@ -313,7 +311,7 @@ xfs_sendfile( | |||
313 | 311 | ||
314 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && | 312 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && |
315 | (!(ioflags & IO_INVIS))) { | 313 | (!(ioflags & IO_INVIS))) { |
316 | vrwlock_t locktype = VRWLOCK_READ; | 314 | bhv_vrwlock_t locktype = VRWLOCK_READ; |
317 | int error; | 315 | int error; |
318 | 316 | ||
319 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), | 317 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), |
@@ -357,7 +355,7 @@ xfs_splice_read( | |||
357 | 355 | ||
358 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && | 356 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_READ) && |
359 | (!(ioflags & IO_INVIS))) { | 357 | (!(ioflags & IO_INVIS))) { |
360 | vrwlock_t locktype = VRWLOCK_READ; | 358 | bhv_vrwlock_t locktype = VRWLOCK_READ; |
361 | int error; | 359 | int error; |
362 | 360 | ||
363 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), | 361 | error = XFS_SEND_DATA(mp, DM_EVENT_READ, BHV_TO_VNODE(bdp), |
@@ -401,7 +399,7 @@ xfs_splice_write( | |||
401 | 399 | ||
402 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && | 400 | if (DM_EVENT_ENABLED(BHV_TO_VNODE(bdp)->v_vfsp, ip, DM_EVENT_WRITE) && |
403 | (!(ioflags & IO_INVIS))) { | 401 | (!(ioflags & IO_INVIS))) { |
404 | vrwlock_t locktype = VRWLOCK_WRITE; | 402 | bhv_vrwlock_t locktype = VRWLOCK_WRITE; |
405 | int error; | 403 | int error; |
406 | 404 | ||
407 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), | 405 | error = XFS_SEND_DATA(mp, DM_EVENT_WRITE, BHV_TO_VNODE(bdp), |
@@ -458,7 +456,7 @@ xfs_zero_last_block( | |||
458 | last_fsb = XFS_B_TO_FSBT(mp, isize); | 456 | last_fsb = XFS_B_TO_FSBT(mp, isize); |
459 | nimaps = 1; | 457 | nimaps = 1; |
460 | error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap, | 458 | error = XFS_BMAPI(mp, NULL, io, last_fsb, 1, 0, NULL, 0, &imap, |
461 | &nimaps, NULL); | 459 | &nimaps, NULL, NULL); |
462 | if (error) { | 460 | if (error) { |
463 | return error; | 461 | return error; |
464 | } | 462 | } |
@@ -499,7 +497,7 @@ xfs_zero_last_block( | |||
499 | 497 | ||
500 | int /* error (positive) */ | 498 | int /* error (positive) */ |
501 | xfs_zero_eof( | 499 | xfs_zero_eof( |
502 | vnode_t *vp, | 500 | bhv_vnode_t *vp, |
503 | xfs_iocore_t *io, | 501 | xfs_iocore_t *io, |
504 | xfs_off_t offset, /* starting I/O offset */ | 502 | xfs_off_t offset, /* starting I/O offset */ |
505 | xfs_fsize_t isize, /* current inode size */ | 503 | xfs_fsize_t isize, /* current inode size */ |
@@ -510,7 +508,6 @@ xfs_zero_eof( | |||
510 | xfs_fileoff_t end_zero_fsb; | 508 | xfs_fileoff_t end_zero_fsb; |
511 | xfs_fileoff_t zero_count_fsb; | 509 | xfs_fileoff_t zero_count_fsb; |
512 | xfs_fileoff_t last_fsb; | 510 | xfs_fileoff_t last_fsb; |
513 | xfs_extlen_t buf_len_fsb; | ||
514 | xfs_mount_t *mp = io->io_mount; | 511 | xfs_mount_t *mp = io->io_mount; |
515 | int nimaps; | 512 | int nimaps; |
516 | int error = 0; | 513 | int error = 0; |
@@ -556,7 +553,7 @@ xfs_zero_eof( | |||
556 | nimaps = 1; | 553 | nimaps = 1; |
557 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; | 554 | zero_count_fsb = end_zero_fsb - start_zero_fsb + 1; |
558 | error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb, | 555 | error = XFS_BMAPI(mp, NULL, io, start_zero_fsb, zero_count_fsb, |
559 | 0, NULL, 0, &imap, &nimaps, NULL); | 556 | 0, NULL, 0, &imap, &nimaps, NULL, NULL); |
560 | if (error) { | 557 | if (error) { |
561 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); | 558 | ASSERT(ismrlocked(io->io_lock, MR_UPDATE)); |
562 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); | 559 | ASSERT(ismrlocked(io->io_iolock, MR_UPDATE)); |
@@ -579,16 +576,7 @@ xfs_zero_eof( | |||
579 | } | 576 | } |
580 | 577 | ||
581 | /* | 578 | /* |
582 | * There are blocks in the range requested. | 579 | * There are blocks we need to zero. |
583 | * Zero them a single write at a time. We actually | ||
584 | * don't zero the entire range returned if it is | ||
585 | * too big and simply loop around to get the rest. | ||
586 | * That is not the most efficient thing to do, but it | ||
587 | * is simple and this path should not be exercised often. | ||
588 | */ | ||
589 | buf_len_fsb = XFS_FILBLKS_MIN(imap.br_blockcount, | ||
590 | mp->m_writeio_blocks << 8); | ||
591 | /* | ||
592 | * Drop the inode lock while we're doing the I/O. | 580 | * Drop the inode lock while we're doing the I/O. |
593 | * We'll still have the iolock to protect us. | 581 | * We'll still have the iolock to protect us. |
594 | */ | 582 | */ |
@@ -596,14 +584,13 @@ xfs_zero_eof( | |||
596 | 584 | ||
597 | error = xfs_iozero(ip, | 585 | error = xfs_iozero(ip, |
598 | XFS_FSB_TO_B(mp, start_zero_fsb), | 586 | XFS_FSB_TO_B(mp, start_zero_fsb), |
599 | XFS_FSB_TO_B(mp, buf_len_fsb), | 587 | XFS_FSB_TO_B(mp, imap.br_blockcount), |
600 | end_size); | 588 | end_size); |
601 | |||
602 | if (error) { | 589 | if (error) { |
603 | goto out_lock; | 590 | goto out_lock; |
604 | } | 591 | } |
605 | 592 | ||
606 | start_zero_fsb = imap.br_startoff + buf_len_fsb; | 593 | start_zero_fsb = imap.br_startoff + imap.br_blockcount; |
607 | ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); | 594 | ASSERT(start_zero_fsb <= (end_zero_fsb + 1)); |
608 | 595 | ||
609 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); | 596 | XFS_ILOCK(mp, io, XFS_ILOCK_EXCL|XFS_EXTSIZE_RD); |
@@ -637,11 +624,11 @@ xfs_write( | |||
637 | ssize_t ret = 0, error = 0; | 624 | ssize_t ret = 0, error = 0; |
638 | xfs_fsize_t isize, new_size; | 625 | xfs_fsize_t isize, new_size; |
639 | xfs_iocore_t *io; | 626 | xfs_iocore_t *io; |
640 | vnode_t *vp; | 627 | bhv_vnode_t *vp; |
641 | unsigned long seg; | 628 | unsigned long seg; |
642 | int iolock; | 629 | int iolock; |
643 | int eventsent = 0; | 630 | int eventsent = 0; |
644 | vrwlock_t locktype; | 631 | bhv_vrwlock_t locktype; |
645 | size_t ocount = 0, count; | 632 | size_t ocount = 0, count; |
646 | loff_t pos; | 633 | loff_t pos; |
647 | int need_i_mutex = 1, need_flush = 0; | 634 | int need_i_mutex = 1, need_flush = 0; |
@@ -679,11 +666,11 @@ xfs_write( | |||
679 | io = &xip->i_iocore; | 666 | io = &xip->i_iocore; |
680 | mp = io->io_mount; | 667 | mp = io->io_mount; |
681 | 668 | ||
669 | vfs_wait_for_freeze(vp->v_vfsp, SB_FREEZE_WRITE); | ||
670 | |||
682 | if (XFS_FORCED_SHUTDOWN(mp)) | 671 | if (XFS_FORCED_SHUTDOWN(mp)) |
683 | return -EIO; | 672 | return -EIO; |
684 | 673 | ||
685 | fs_check_frozen(vp->v_vfsp, SB_FREEZE_WRITE); | ||
686 | |||
687 | if (ioflags & IO_ISDIRECT) { | 674 | if (ioflags & IO_ISDIRECT) { |
688 | xfs_buftarg_t *target = | 675 | xfs_buftarg_t *target = |
689 | (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? | 676 | (xip->i_d.di_flags & XFS_DIFLAG_REALTIME) ? |
@@ -814,7 +801,7 @@ retry: | |||
814 | if (need_flush) { | 801 | if (need_flush) { |
815 | xfs_inval_cached_trace(io, pos, -1, | 802 | xfs_inval_cached_trace(io, pos, -1, |
816 | ctooff(offtoct(pos)), -1); | 803 | ctooff(offtoct(pos)), -1); |
817 | VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(pos)), | 804 | bhv_vop_flushinval_pages(vp, ctooff(offtoct(pos)), |
818 | -1, FI_REMAPF_LOCKED); | 805 | -1, FI_REMAPF_LOCKED); |
819 | } | 806 | } |
820 | 807 | ||
@@ -903,79 +890,9 @@ retry: | |||
903 | 890 | ||
904 | /* Handle various SYNC-type writes */ | 891 | /* Handle various SYNC-type writes */ |
905 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { | 892 | if ((file->f_flags & O_SYNC) || IS_SYNC(inode)) { |
906 | /* | 893 | error = xfs_write_sync_logforce(mp, xip); |
907 | * If we're treating this as O_DSYNC and we have not updated the | 894 | if (error) |
908 | * size, force the log. | 895 | goto out_unlock_internal; |
909 | */ | ||
910 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
911 | !(xip->i_update_size)) { | ||
912 | xfs_inode_log_item_t *iip = xip->i_itemp; | ||
913 | |||
914 | /* | ||
915 | * If an allocation transaction occurred | ||
916 | * without extending the size, then we have to force | ||
917 | * the log up the proper point to ensure that the | ||
918 | * allocation is permanent. We can't count on | ||
919 | * the fact that buffered writes lock out direct I/O | ||
920 | * writes - the direct I/O write could have extended | ||
921 | * the size nontransactionally, then finished before | ||
922 | * we started. xfs_write_file will think that the file | ||
923 | * didn't grow but the update isn't safe unless the | ||
924 | * size change is logged. | ||
925 | * | ||
926 | * Force the log if we've committed a transaction | ||
927 | * against the inode or if someone else has and | ||
928 | * the commit record hasn't gone to disk (e.g. | ||
929 | * the inode is pinned). This guarantees that | ||
930 | * all changes affecting the inode are permanent | ||
931 | * when we return. | ||
932 | */ | ||
933 | if (iip && iip->ili_last_lsn) { | ||
934 | xfs_log_force(mp, iip->ili_last_lsn, | ||
935 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
936 | } else if (xfs_ipincount(xip) > 0) { | ||
937 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
938 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
939 | } | ||
940 | |||
941 | } else { | ||
942 | xfs_trans_t *tp; | ||
943 | |||
944 | /* | ||
945 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
946 | * the same way. | ||
947 | * | ||
948 | * If the write was synchronous then we need to make | ||
949 | * sure that the inode modification time is permanent. | ||
950 | * We'll have updated the timestamp above, so here | ||
951 | * we use a synchronous transaction to log the inode. | ||
952 | * It's not fast, but it's necessary. | ||
953 | * | ||
954 | * If this a dsync write and the size got changed | ||
955 | * non-transactionally, then we need to ensure that | ||
956 | * the size change gets logged in a synchronous | ||
957 | * transaction. | ||
958 | */ | ||
959 | |||
960 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
961 | if ((error = xfs_trans_reserve(tp, 0, | ||
962 | XFS_SWRITE_LOG_RES(mp), | ||
963 | 0, 0, 0))) { | ||
964 | /* Transaction reserve failed */ | ||
965 | xfs_trans_cancel(tp, 0); | ||
966 | } else { | ||
967 | /* Transaction reserve successful */ | ||
968 | xfs_ilock(xip, XFS_ILOCK_EXCL); | ||
969 | xfs_trans_ijoin(tp, xip, XFS_ILOCK_EXCL); | ||
970 | xfs_trans_ihold(tp, xip); | ||
971 | xfs_trans_log_inode(tp, xip, XFS_ILOG_CORE); | ||
972 | xfs_trans_set_sync(tp); | ||
973 | error = xfs_trans_commit(tp, 0, NULL); | ||
974 | xfs_iunlock(xip, XFS_ILOCK_EXCL); | ||
975 | } | ||
976 | if (error) | ||
977 | goto out_unlock_internal; | ||
978 | } | ||
979 | 896 | ||
980 | xfs_rwunlock(bdp, locktype); | 897 | xfs_rwunlock(bdp, locktype); |
981 | if (need_i_mutex) | 898 | if (need_i_mutex) |
diff --git a/fs/xfs/linux-2.6/xfs_lrw.h b/fs/xfs/linux-2.6/xfs_lrw.h index 8f4539952350..c77e62efb742 100644 --- a/fs/xfs/linux-2.6/xfs_lrw.h +++ b/fs/xfs/linux-2.6/xfs_lrw.h | |||
@@ -18,8 +18,8 @@ | |||
18 | #ifndef __XFS_LRW_H__ | 18 | #ifndef __XFS_LRW_H__ |
19 | #define __XFS_LRW_H__ | 19 | #define __XFS_LRW_H__ |
20 | 20 | ||
21 | struct vnode; | ||
22 | struct bhv_desc; | 21 | struct bhv_desc; |
22 | struct bhv_vnode; | ||
23 | struct xfs_mount; | 23 | struct xfs_mount; |
24 | struct xfs_iocore; | 24 | struct xfs_iocore; |
25 | struct xfs_inode; | 25 | struct xfs_inode; |
@@ -49,7 +49,7 @@ struct xfs_iomap; | |||
49 | #define XFS_CTRUNC4 14 | 49 | #define XFS_CTRUNC4 14 |
50 | #define XFS_CTRUNC5 15 | 50 | #define XFS_CTRUNC5 15 |
51 | #define XFS_CTRUNC6 16 | 51 | #define XFS_CTRUNC6 16 |
52 | #define XFS_BUNMAPI 17 | 52 | #define XFS_BUNMAP 17 |
53 | #define XFS_INVAL_CACHED 18 | 53 | #define XFS_INVAL_CACHED 18 |
54 | #define XFS_DIORD_ENTER 19 | 54 | #define XFS_DIORD_ENTER 19 |
55 | #define XFS_DIOWR_ENTER 20 | 55 | #define XFS_DIOWR_ENTER 20 |
@@ -82,7 +82,7 @@ extern int xfsbdstrat(struct xfs_mount *, struct xfs_buf *); | |||
82 | extern int xfs_bdstrat_cb(struct xfs_buf *); | 82 | extern int xfs_bdstrat_cb(struct xfs_buf *); |
83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); | 83 | extern int xfs_dev_is_read_only(struct xfs_mount *, char *); |
84 | 84 | ||
85 | extern int xfs_zero_eof(struct vnode *, struct xfs_iocore *, xfs_off_t, | 85 | extern int xfs_zero_eof(struct bhv_vnode *, struct xfs_iocore *, xfs_off_t, |
86 | xfs_fsize_t, xfs_fsize_t); | 86 | xfs_fsize_t, xfs_fsize_t); |
87 | extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, | 87 | extern ssize_t xfs_read(struct bhv_desc *, struct kiocb *, |
88 | const struct iovec *, unsigned int, | 88 | const struct iovec *, unsigned int, |
diff --git a/fs/xfs/linux-2.6/xfs_stats.c b/fs/xfs/linux-2.6/xfs_stats.c index 1f0589a05eca..e480b6102051 100644 --- a/fs/xfs/linux-2.6/xfs_stats.c +++ b/fs/xfs/linux-2.6/xfs_stats.c | |||
@@ -62,7 +62,7 @@ xfs_read_xfsstats( | |||
62 | while (j < xstats[i].endpoint) { | 62 | while (j < xstats[i].endpoint) { |
63 | val = 0; | 63 | val = 0; |
64 | /* sum over all cpus */ | 64 | /* sum over all cpus */ |
65 | for_each_cpu(c) | 65 | for_each_possible_cpu(c) |
66 | val += *(((__u32*)&per_cpu(xfsstats, c) + j)); | 66 | val += *(((__u32*)&per_cpu(xfsstats, c) + j)); |
67 | len += sprintf(buffer + len, " %u", val); | 67 | len += sprintf(buffer + len, " %u", val); |
68 | j++; | 68 | j++; |
@@ -70,7 +70,7 @@ xfs_read_xfsstats( | |||
70 | buffer[len++] = '\n'; | 70 | buffer[len++] = '\n'; |
71 | } | 71 | } |
72 | /* extra precision counters */ | 72 | /* extra precision counters */ |
73 | for_each_cpu(i) { | 73 | for_each_possible_cpu(i) { |
74 | xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes; | 74 | xs_xstrat_bytes += per_cpu(xfsstats, i).xs_xstrat_bytes; |
75 | xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes; | 75 | xs_write_bytes += per_cpu(xfsstats, i).xs_write_bytes; |
76 | xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; | 76 | xs_read_bytes += per_cpu(xfsstats, i).xs_read_bytes; |
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 68f4793e8a11..9bdef9d51900 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -151,7 +149,7 @@ xfs_set_inodeops( | |||
151 | STATIC __inline__ void | 149 | STATIC __inline__ void |
152 | xfs_revalidate_inode( | 150 | xfs_revalidate_inode( |
153 | xfs_mount_t *mp, | 151 | xfs_mount_t *mp, |
154 | vnode_t *vp, | 152 | bhv_vnode_t *vp, |
155 | xfs_inode_t *ip) | 153 | xfs_inode_t *ip) |
156 | { | 154 | { |
157 | struct inode *inode = vn_to_inode(vp); | 155 | struct inode *inode = vn_to_inode(vp); |
@@ -206,7 +204,7 @@ xfs_revalidate_inode( | |||
206 | void | 204 | void |
207 | xfs_initialize_vnode( | 205 | xfs_initialize_vnode( |
208 | bhv_desc_t *bdp, | 206 | bhv_desc_t *bdp, |
209 | vnode_t *vp, | 207 | bhv_vnode_t *vp, |
210 | bhv_desc_t *inode_bhv, | 208 | bhv_desc_t *inode_bhv, |
211 | int unlock) | 209 | int unlock) |
212 | { | 210 | { |
@@ -336,7 +334,7 @@ STATIC struct inode * | |||
336 | xfs_fs_alloc_inode( | 334 | xfs_fs_alloc_inode( |
337 | struct super_block *sb) | 335 | struct super_block *sb) |
338 | { | 336 | { |
339 | vnode_t *vp; | 337 | bhv_vnode_t *vp; |
340 | 338 | ||
341 | vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); | 339 | vp = kmem_zone_alloc(xfs_vnode_zone, KM_SLEEP); |
342 | if (unlikely(!vp)) | 340 | if (unlikely(!vp)) |
@@ -359,13 +357,13 @@ xfs_fs_inode_init_once( | |||
359 | { | 357 | { |
360 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == | 358 | if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == |
361 | SLAB_CTOR_CONSTRUCTOR) | 359 | SLAB_CTOR_CONSTRUCTOR) |
362 | inode_init_once(vn_to_inode((vnode_t *)vnode)); | 360 | inode_init_once(vn_to_inode((bhv_vnode_t *)vnode)); |
363 | } | 361 | } |
364 | 362 | ||
365 | STATIC int | 363 | STATIC int |
366 | xfs_init_zones(void) | 364 | xfs_init_zones(void) |
367 | { | 365 | { |
368 | xfs_vnode_zone = kmem_zone_init_flags(sizeof(vnode_t), "xfs_vnode_t", | 366 | xfs_vnode_zone = kmem_zone_init_flags(sizeof(bhv_vnode_t), "xfs_vnode", |
369 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | | 367 | KM_ZONE_HWALIGN | KM_ZONE_RECLAIM | |
370 | KM_ZONE_SPREAD, | 368 | KM_ZONE_SPREAD, |
371 | xfs_fs_inode_init_once); | 369 | xfs_fs_inode_init_once); |
@@ -409,22 +407,17 @@ xfs_fs_write_inode( | |||
409 | struct inode *inode, | 407 | struct inode *inode, |
410 | int sync) | 408 | int sync) |
411 | { | 409 | { |
412 | vnode_t *vp = vn_from_inode(inode); | 410 | bhv_vnode_t *vp = vn_from_inode(inode); |
413 | int error = 0, flags = FLUSH_INODE; | 411 | int error = 0, flags = FLUSH_INODE; |
414 | 412 | ||
415 | if (vp) { | 413 | if (vp) { |
416 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 414 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
417 | if (sync) | 415 | if (sync) |
418 | flags |= FLUSH_SYNC; | 416 | flags |= FLUSH_SYNC; |
419 | VOP_IFLUSH(vp, flags, error); | 417 | error = bhv_vop_iflush(vp, flags); |
420 | if (error == EAGAIN) { | 418 | if (error == EAGAIN) |
421 | if (sync) | 419 | error = sync? bhv_vop_iflush(vp, flags | FLUSH_LOG) : 0; |
422 | VOP_IFLUSH(vp, flags | FLUSH_LOG, error); | ||
423 | else | ||
424 | error = 0; | ||
425 | } | ||
426 | } | 420 | } |
427 | |||
428 | return -error; | 421 | return -error; |
429 | } | 422 | } |
430 | 423 | ||
@@ -432,8 +425,7 @@ STATIC void | |||
432 | xfs_fs_clear_inode( | 425 | xfs_fs_clear_inode( |
433 | struct inode *inode) | 426 | struct inode *inode) |
434 | { | 427 | { |
435 | vnode_t *vp = vn_from_inode(inode); | 428 | bhv_vnode_t *vp = vn_from_inode(inode); |
436 | int error, cache; | ||
437 | 429 | ||
438 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 430 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
439 | 431 | ||
@@ -446,20 +438,18 @@ xfs_fs_clear_inode( | |||
446 | * This can happen because xfs_iget_core calls xfs_idestroy if we | 438 | * This can happen because xfs_iget_core calls xfs_idestroy if we |
447 | * find an inode with di_mode == 0 but without IGET_CREATE set. | 439 | * find an inode with di_mode == 0 but without IGET_CREATE set. |
448 | */ | 440 | */ |
449 | if (vp->v_fbhv) | 441 | if (VNHEAD(vp)) |
450 | VOP_INACTIVE(vp, NULL, cache); | 442 | bhv_vop_inactive(vp, NULL); |
451 | 443 | ||
452 | VN_LOCK(vp); | 444 | VN_LOCK(vp); |
453 | vp->v_flag &= ~VMODIFIED; | 445 | vp->v_flag &= ~VMODIFIED; |
454 | VN_UNLOCK(vp, 0); | 446 | VN_UNLOCK(vp, 0); |
455 | 447 | ||
456 | if (vp->v_fbhv) { | 448 | if (VNHEAD(vp)) |
457 | VOP_RECLAIM(vp, error); | 449 | if (bhv_vop_reclaim(vp)) |
458 | if (error) | 450 | panic("%s: cannot reclaim 0x%p\n", __FUNCTION__, vp); |
459 | panic("vn_purge: cannot reclaim"); | ||
460 | } | ||
461 | 451 | ||
462 | ASSERT(vp->v_fbhv == NULL); | 452 | ASSERT(VNHEAD(vp) == NULL); |
463 | 453 | ||
464 | #ifdef XFS_VNODE_TRACE | 454 | #ifdef XFS_VNODE_TRACE |
465 | ktrace_free(vp->v_trace); | 455 | ktrace_free(vp->v_trace); |
@@ -475,13 +465,13 @@ xfs_fs_clear_inode( | |||
475 | */ | 465 | */ |
476 | STATIC void | 466 | STATIC void |
477 | xfs_syncd_queue_work( | 467 | xfs_syncd_queue_work( |
478 | struct vfs *vfs, | 468 | struct bhv_vfs *vfs, |
479 | void *data, | 469 | void *data, |
480 | void (*syncer)(vfs_t *, void *)) | 470 | void (*syncer)(bhv_vfs_t *, void *)) |
481 | { | 471 | { |
482 | vfs_sync_work_t *work; | 472 | struct bhv_vfs_sync_work *work; |
483 | 473 | ||
484 | work = kmem_alloc(sizeof(struct vfs_sync_work), KM_SLEEP); | 474 | work = kmem_alloc(sizeof(struct bhv_vfs_sync_work), KM_SLEEP); |
485 | INIT_LIST_HEAD(&work->w_list); | 475 | INIT_LIST_HEAD(&work->w_list); |
486 | work->w_syncer = syncer; | 476 | work->w_syncer = syncer; |
487 | work->w_data = data; | 477 | work->w_data = data; |
@@ -500,7 +490,7 @@ xfs_syncd_queue_work( | |||
500 | */ | 490 | */ |
501 | STATIC void | 491 | STATIC void |
502 | xfs_flush_inode_work( | 492 | xfs_flush_inode_work( |
503 | vfs_t *vfs, | 493 | bhv_vfs_t *vfs, |
504 | void *inode) | 494 | void *inode) |
505 | { | 495 | { |
506 | filemap_flush(((struct inode *)inode)->i_mapping); | 496 | filemap_flush(((struct inode *)inode)->i_mapping); |
@@ -512,7 +502,7 @@ xfs_flush_inode( | |||
512 | xfs_inode_t *ip) | 502 | xfs_inode_t *ip) |
513 | { | 503 | { |
514 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); | 504 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); |
515 | struct vfs *vfs = XFS_MTOVFS(ip->i_mount); | 505 | struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); |
516 | 506 | ||
517 | igrab(inode); | 507 | igrab(inode); |
518 | xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work); | 508 | xfs_syncd_queue_work(vfs, inode, xfs_flush_inode_work); |
@@ -525,7 +515,7 @@ xfs_flush_inode( | |||
525 | */ | 515 | */ |
526 | STATIC void | 516 | STATIC void |
527 | xfs_flush_device_work( | 517 | xfs_flush_device_work( |
528 | vfs_t *vfs, | 518 | bhv_vfs_t *vfs, |
529 | void *inode) | 519 | void *inode) |
530 | { | 520 | { |
531 | sync_blockdev(vfs->vfs_super->s_bdev); | 521 | sync_blockdev(vfs->vfs_super->s_bdev); |
@@ -537,7 +527,7 @@ xfs_flush_device( | |||
537 | xfs_inode_t *ip) | 527 | xfs_inode_t *ip) |
538 | { | 528 | { |
539 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); | 529 | struct inode *inode = vn_to_inode(XFS_ITOV(ip)); |
540 | struct vfs *vfs = XFS_MTOVFS(ip->i_mount); | 530 | struct bhv_vfs *vfs = XFS_MTOVFS(ip->i_mount); |
541 | 531 | ||
542 | igrab(inode); | 532 | igrab(inode); |
543 | xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work); | 533 | xfs_syncd_queue_work(vfs, inode, xfs_flush_device_work); |
@@ -545,16 +535,16 @@ xfs_flush_device( | |||
545 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); | 535 | xfs_log_force(ip->i_mount, (xfs_lsn_t)0, XFS_LOG_FORCE|XFS_LOG_SYNC); |
546 | } | 536 | } |
547 | 537 | ||
548 | #define SYNCD_FLAGS (SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR|SYNC_REFCACHE) | ||
549 | STATIC void | 538 | STATIC void |
550 | vfs_sync_worker( | 539 | vfs_sync_worker( |
551 | vfs_t *vfsp, | 540 | bhv_vfs_t *vfsp, |
552 | void *unused) | 541 | void *unused) |
553 | { | 542 | { |
554 | int error; | 543 | int error; |
555 | 544 | ||
556 | if (!(vfsp->vfs_flag & VFS_RDONLY)) | 545 | if (!(vfsp->vfs_flag & VFS_RDONLY)) |
557 | VFS_SYNC(vfsp, SYNCD_FLAGS, NULL, error); | 546 | error = bhv_vfs_sync(vfsp, SYNC_FSDATA | SYNC_BDFLUSH | \ |
547 | SYNC_ATTR | SYNC_REFCACHE, NULL); | ||
558 | vfsp->vfs_sync_seq++; | 548 | vfsp->vfs_sync_seq++; |
559 | wmb(); | 549 | wmb(); |
560 | wake_up(&vfsp->vfs_wait_single_sync_task); | 550 | wake_up(&vfsp->vfs_wait_single_sync_task); |
@@ -565,8 +555,8 @@ xfssyncd( | |||
565 | void *arg) | 555 | void *arg) |
566 | { | 556 | { |
567 | long timeleft; | 557 | long timeleft; |
568 | vfs_t *vfsp = (vfs_t *) arg; | 558 | bhv_vfs_t *vfsp = (bhv_vfs_t *) arg; |
569 | struct vfs_sync_work *work, *n; | 559 | bhv_vfs_sync_work_t *work, *n; |
570 | LIST_HEAD (tmp); | 560 | LIST_HEAD (tmp); |
571 | 561 | ||
572 | timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); | 562 | timeleft = xfs_syncd_centisecs * msecs_to_jiffies(10); |
@@ -600,7 +590,7 @@ xfssyncd( | |||
600 | list_del(&work->w_list); | 590 | list_del(&work->w_list); |
601 | if (work == &vfsp->vfs_sync_work) | 591 | if (work == &vfsp->vfs_sync_work) |
602 | continue; | 592 | continue; |
603 | kmem_free(work, sizeof(struct vfs_sync_work)); | 593 | kmem_free(work, sizeof(struct bhv_vfs_sync_work)); |
604 | } | 594 | } |
605 | } | 595 | } |
606 | 596 | ||
@@ -609,7 +599,7 @@ xfssyncd( | |||
609 | 599 | ||
610 | STATIC int | 600 | STATIC int |
611 | xfs_fs_start_syncd( | 601 | xfs_fs_start_syncd( |
612 | vfs_t *vfsp) | 602 | bhv_vfs_t *vfsp) |
613 | { | 603 | { |
614 | vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; | 604 | vfsp->vfs_sync_work.w_syncer = vfs_sync_worker; |
615 | vfsp->vfs_sync_work.w_vfs = vfsp; | 605 | vfsp->vfs_sync_work.w_vfs = vfsp; |
@@ -621,7 +611,7 @@ xfs_fs_start_syncd( | |||
621 | 611 | ||
622 | STATIC void | 612 | STATIC void |
623 | xfs_fs_stop_syncd( | 613 | xfs_fs_stop_syncd( |
624 | vfs_t *vfsp) | 614 | bhv_vfs_t *vfsp) |
625 | { | 615 | { |
626 | kthread_stop(vfsp->vfs_sync_task); | 616 | kthread_stop(vfsp->vfs_sync_task); |
627 | } | 617 | } |
@@ -630,35 +620,26 @@ STATIC void | |||
630 | xfs_fs_put_super( | 620 | xfs_fs_put_super( |
631 | struct super_block *sb) | 621 | struct super_block *sb) |
632 | { | 622 | { |
633 | vfs_t *vfsp = vfs_from_sb(sb); | 623 | bhv_vfs_t *vfsp = vfs_from_sb(sb); |
634 | int error; | 624 | int error; |
635 | 625 | ||
636 | xfs_fs_stop_syncd(vfsp); | 626 | xfs_fs_stop_syncd(vfsp); |
637 | VFS_SYNC(vfsp, SYNC_ATTR|SYNC_DELWRI, NULL, error); | 627 | bhv_vfs_sync(vfsp, SYNC_ATTR | SYNC_DELWRI, NULL); |
638 | if (!error) | 628 | error = bhv_vfs_unmount(vfsp, 0, NULL); |
639 | VFS_UNMOUNT(vfsp, 0, NULL, error); | ||
640 | if (error) { | 629 | if (error) { |
641 | printk("XFS unmount got error %d\n", error); | 630 | printk("XFS: unmount got error=%d\n", error); |
642 | printk("%s: vfsp/0x%p left dangling!\n", __FUNCTION__, vfsp); | 631 | printk("%s: vfs=0x%p left dangling!\n", __FUNCTION__, vfsp); |
643 | return; | 632 | } else { |
633 | vfs_deallocate(vfsp); | ||
644 | } | 634 | } |
645 | |||
646 | vfs_deallocate(vfsp); | ||
647 | } | 635 | } |
648 | 636 | ||
649 | STATIC void | 637 | STATIC void |
650 | xfs_fs_write_super( | 638 | xfs_fs_write_super( |
651 | struct super_block *sb) | 639 | struct super_block *sb) |
652 | { | 640 | { |
653 | vfs_t *vfsp = vfs_from_sb(sb); | 641 | if (!(sb->s_flags & MS_RDONLY)) |
654 | int error; | 642 | bhv_vfs_sync(vfs_from_sb(sb), SYNC_FSDATA, NULL); |
655 | |||
656 | if (sb->s_flags & MS_RDONLY) { | ||
657 | sb->s_dirt = 0; /* paranoia */ | ||
658 | return; | ||
659 | } | ||
660 | /* Push the log and superblock a little */ | ||
661 | VFS_SYNC(vfsp, SYNC_FSDATA, NULL, error); | ||
662 | sb->s_dirt = 0; | 643 | sb->s_dirt = 0; |
663 | } | 644 | } |
664 | 645 | ||
@@ -667,16 +648,16 @@ xfs_fs_sync_super( | |||
667 | struct super_block *sb, | 648 | struct super_block *sb, |
668 | int wait) | 649 | int wait) |
669 | { | 650 | { |
670 | vfs_t *vfsp = vfs_from_sb(sb); | 651 | bhv_vfs_t *vfsp = vfs_from_sb(sb); |
671 | int error; | 652 | int error; |
672 | int flags = SYNC_FSDATA; | 653 | int flags; |
673 | 654 | ||
674 | if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) | 655 | if (unlikely(sb->s_frozen == SB_FREEZE_WRITE)) |
675 | flags = SYNC_QUIESCE; | 656 | flags = SYNC_QUIESCE; |
676 | else | 657 | else |
677 | flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); | 658 | flags = SYNC_FSDATA | (wait ? SYNC_WAIT : 0); |
678 | 659 | ||
679 | VFS_SYNC(vfsp, flags, NULL, error); | 660 | error = bhv_vfs_sync(vfsp, flags, NULL); |
680 | sb->s_dirt = 0; | 661 | sb->s_dirt = 0; |
681 | 662 | ||
682 | if (unlikely(laptop_mode)) { | 663 | if (unlikely(laptop_mode)) { |
@@ -703,14 +684,11 @@ xfs_fs_sync_super( | |||
703 | 684 | ||
704 | STATIC int | 685 | STATIC int |
705 | xfs_fs_statfs( | 686 | xfs_fs_statfs( |
706 | struct super_block *sb, | 687 | struct dentry *dentry, |
707 | struct kstatfs *statp) | 688 | struct kstatfs *statp) |
708 | { | 689 | { |
709 | vfs_t *vfsp = vfs_from_sb(sb); | 690 | return -bhv_vfs_statvfs(vfs_from_sb(dentry->d_sb), statp, |
710 | int error; | 691 | vn_from_inode(dentry->d_inode)); |
711 | |||
712 | VFS_STATVFS(vfsp, statp, NULL, error); | ||
713 | return -error; | ||
714 | } | 692 | } |
715 | 693 | ||
716 | STATIC int | 694 | STATIC int |
@@ -719,13 +697,13 @@ xfs_fs_remount( | |||
719 | int *flags, | 697 | int *flags, |
720 | char *options) | 698 | char *options) |
721 | { | 699 | { |
722 | vfs_t *vfsp = vfs_from_sb(sb); | 700 | bhv_vfs_t *vfsp = vfs_from_sb(sb); |
723 | struct xfs_mount_args *args = xfs_args_allocate(sb, 0); | 701 | struct xfs_mount_args *args = xfs_args_allocate(sb, 0); |
724 | int error; | 702 | int error; |
725 | 703 | ||
726 | VFS_PARSEARGS(vfsp, options, args, 1, error); | 704 | error = bhv_vfs_parseargs(vfsp, options, args, 1); |
727 | if (!error) | 705 | if (!error) |
728 | VFS_MNTUPDATE(vfsp, flags, args, error); | 706 | error = bhv_vfs_mntupdate(vfsp, flags, args); |
729 | kmem_free(args, sizeof(*args)); | 707 | kmem_free(args, sizeof(*args)); |
730 | return -error; | 708 | return -error; |
731 | } | 709 | } |
@@ -734,7 +712,7 @@ STATIC void | |||
734 | xfs_fs_lockfs( | 712 | xfs_fs_lockfs( |
735 | struct super_block *sb) | 713 | struct super_block *sb) |
736 | { | 714 | { |
737 | VFS_FREEZE(vfs_from_sb(sb)); | 715 | bhv_vfs_freeze(vfs_from_sb(sb)); |
738 | } | 716 | } |
739 | 717 | ||
740 | STATIC int | 718 | STATIC int |
@@ -742,11 +720,7 @@ xfs_fs_show_options( | |||
742 | struct seq_file *m, | 720 | struct seq_file *m, |
743 | struct vfsmount *mnt) | 721 | struct vfsmount *mnt) |
744 | { | 722 | { |
745 | struct vfs *vfsp = vfs_from_sb(mnt->mnt_sb); | 723 | return -bhv_vfs_showargs(vfs_from_sb(mnt->mnt_sb), m); |
746 | int error; | ||
747 | |||
748 | VFS_SHOWARGS(vfsp, m, error); | ||
749 | return error; | ||
750 | } | 724 | } |
751 | 725 | ||
752 | STATIC int | 726 | STATIC int |
@@ -754,11 +728,7 @@ xfs_fs_quotasync( | |||
754 | struct super_block *sb, | 728 | struct super_block *sb, |
755 | int type) | 729 | int type) |
756 | { | 730 | { |
757 | struct vfs *vfsp = vfs_from_sb(sb); | 731 | return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XQUOTASYNC, 0, NULL); |
758 | int error; | ||
759 | |||
760 | VFS_QUOTACTL(vfsp, Q_XQUOTASYNC, 0, (caddr_t)NULL, error); | ||
761 | return -error; | ||
762 | } | 732 | } |
763 | 733 | ||
764 | STATIC int | 734 | STATIC int |
@@ -766,11 +736,7 @@ xfs_fs_getxstate( | |||
766 | struct super_block *sb, | 736 | struct super_block *sb, |
767 | struct fs_quota_stat *fqs) | 737 | struct fs_quota_stat *fqs) |
768 | { | 738 | { |
769 | struct vfs *vfsp = vfs_from_sb(sb); | 739 | return -bhv_vfs_quotactl(vfs_from_sb(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); |
770 | int error; | ||
771 | |||
772 | VFS_QUOTACTL(vfsp, Q_XGETQSTAT, 0, (caddr_t)fqs, error); | ||
773 | return -error; | ||
774 | } | 740 | } |
775 | 741 | ||
776 | STATIC int | 742 | STATIC int |
@@ -779,11 +745,7 @@ xfs_fs_setxstate( | |||
779 | unsigned int flags, | 745 | unsigned int flags, |
780 | int op) | 746 | int op) |
781 | { | 747 | { |
782 | struct vfs *vfsp = vfs_from_sb(sb); | 748 | return -bhv_vfs_quotactl(vfs_from_sb(sb), op, 0, (caddr_t)&flags); |
783 | int error; | ||
784 | |||
785 | VFS_QUOTACTL(vfsp, op, 0, (caddr_t)&flags, error); | ||
786 | return -error; | ||
787 | } | 749 | } |
788 | 750 | ||
789 | STATIC int | 751 | STATIC int |
@@ -793,13 +755,10 @@ xfs_fs_getxquota( | |||
793 | qid_t id, | 755 | qid_t id, |
794 | struct fs_disk_quota *fdq) | 756 | struct fs_disk_quota *fdq) |
795 | { | 757 | { |
796 | struct vfs *vfsp = vfs_from_sb(sb); | 758 | return -bhv_vfs_quotactl(vfs_from_sb(sb), |
797 | int error, getmode; | 759 | (type == USRQUOTA) ? Q_XGETQUOTA : |
798 | 760 | ((type == GRPQUOTA) ? Q_XGETGQUOTA : | |
799 | getmode = (type == USRQUOTA) ? Q_XGETQUOTA : | 761 | Q_XGETPQUOTA), id, (caddr_t)fdq); |
800 | ((type == GRPQUOTA) ? Q_XGETGQUOTA : Q_XGETPQUOTA); | ||
801 | VFS_QUOTACTL(vfsp, getmode, id, (caddr_t)fdq, error); | ||
802 | return -error; | ||
803 | } | 762 | } |
804 | 763 | ||
805 | STATIC int | 764 | STATIC int |
@@ -809,13 +768,10 @@ xfs_fs_setxquota( | |||
809 | qid_t id, | 768 | qid_t id, |
810 | struct fs_disk_quota *fdq) | 769 | struct fs_disk_quota *fdq) |
811 | { | 770 | { |
812 | struct vfs *vfsp = vfs_from_sb(sb); | 771 | return -bhv_vfs_quotactl(vfs_from_sb(sb), |
813 | int error, setmode; | 772 | (type == USRQUOTA) ? Q_XSETQLIM : |
814 | 773 | ((type == GRPQUOTA) ? Q_XSETGQLIM : | |
815 | setmode = (type == USRQUOTA) ? Q_XSETQLIM : | 774 | Q_XSETPQLIM), id, (caddr_t)fdq); |
816 | ((type == GRPQUOTA) ? Q_XSETGQLIM : Q_XSETPQLIM); | ||
817 | VFS_QUOTACTL(vfsp, setmode, id, (caddr_t)fdq, error); | ||
818 | return -error; | ||
819 | } | 775 | } |
820 | 776 | ||
821 | STATIC int | 777 | STATIC int |
@@ -824,34 +780,32 @@ xfs_fs_fill_super( | |||
824 | void *data, | 780 | void *data, |
825 | int silent) | 781 | int silent) |
826 | { | 782 | { |
827 | vnode_t *rootvp; | 783 | struct bhv_vnode *rootvp; |
828 | struct vfs *vfsp = vfs_allocate(sb); | 784 | struct bhv_vfs *vfsp = vfs_allocate(sb); |
829 | struct xfs_mount_args *args = xfs_args_allocate(sb, silent); | 785 | struct xfs_mount_args *args = xfs_args_allocate(sb, silent); |
830 | struct kstatfs statvfs; | 786 | struct kstatfs statvfs; |
831 | int error, error2; | 787 | int error; |
832 | 788 | ||
833 | bhv_insert_all_vfsops(vfsp); | 789 | bhv_insert_all_vfsops(vfsp); |
834 | 790 | ||
835 | VFS_PARSEARGS(vfsp, (char *)data, args, 0, error); | 791 | error = bhv_vfs_parseargs(vfsp, (char *)data, args, 0); |
836 | if (error) { | 792 | if (error) { |
837 | bhv_remove_all_vfsops(vfsp, 1); | 793 | bhv_remove_all_vfsops(vfsp, 1); |
838 | goto fail_vfsop; | 794 | goto fail_vfsop; |
839 | } | 795 | } |
840 | 796 | ||
841 | sb_min_blocksize(sb, BBSIZE); | 797 | sb_min_blocksize(sb, BBSIZE); |
842 | #ifdef CONFIG_XFS_EXPORT | ||
843 | sb->s_export_op = &xfs_export_operations; | 798 | sb->s_export_op = &xfs_export_operations; |
844 | #endif | ||
845 | sb->s_qcop = &xfs_quotactl_operations; | 799 | sb->s_qcop = &xfs_quotactl_operations; |
846 | sb->s_op = &xfs_super_operations; | 800 | sb->s_op = &xfs_super_operations; |
847 | 801 | ||
848 | VFS_MOUNT(vfsp, args, NULL, error); | 802 | error = bhv_vfs_mount(vfsp, args, NULL); |
849 | if (error) { | 803 | if (error) { |
850 | bhv_remove_all_vfsops(vfsp, 1); | 804 | bhv_remove_all_vfsops(vfsp, 1); |
851 | goto fail_vfsop; | 805 | goto fail_vfsop; |
852 | } | 806 | } |
853 | 807 | ||
854 | VFS_STATVFS(vfsp, &statvfs, NULL, error); | 808 | error = bhv_vfs_statvfs(vfsp, &statvfs, NULL); |
855 | if (error) | 809 | if (error) |
856 | goto fail_unmount; | 810 | goto fail_unmount; |
857 | 811 | ||
@@ -863,7 +817,7 @@ xfs_fs_fill_super( | |||
863 | sb->s_time_gran = 1; | 817 | sb->s_time_gran = 1; |
864 | set_posix_acl_flag(sb); | 818 | set_posix_acl_flag(sb); |
865 | 819 | ||
866 | VFS_ROOT(vfsp, &rootvp, error); | 820 | error = bhv_vfs_root(vfsp, &rootvp); |
867 | if (error) | 821 | if (error) |
868 | goto fail_unmount; | 822 | goto fail_unmount; |
869 | 823 | ||
@@ -892,7 +846,7 @@ fail_vnrele: | |||
892 | } | 846 | } |
893 | 847 | ||
894 | fail_unmount: | 848 | fail_unmount: |
895 | VFS_UNMOUNT(vfsp, 0, NULL, error2); | 849 | bhv_vfs_unmount(vfsp, 0, NULL); |
896 | 850 | ||
897 | fail_vfsop: | 851 | fail_vfsop: |
898 | vfs_deallocate(vfsp); | 852 | vfs_deallocate(vfsp); |
@@ -900,14 +854,16 @@ fail_vfsop: | |||
900 | return -error; | 854 | return -error; |
901 | } | 855 | } |
902 | 856 | ||
903 | STATIC struct super_block * | 857 | STATIC int |
904 | xfs_fs_get_sb( | 858 | xfs_fs_get_sb( |
905 | struct file_system_type *fs_type, | 859 | struct file_system_type *fs_type, |
906 | int flags, | 860 | int flags, |
907 | const char *dev_name, | 861 | const char *dev_name, |
908 | void *data) | 862 | void *data, |
863 | struct vfsmount *mnt) | ||
909 | { | 864 | { |
910 | return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super); | 865 | return get_sb_bdev(fs_type, flags, dev_name, data, xfs_fs_fill_super, |
866 | mnt); | ||
911 | } | 867 | } |
912 | 868 | ||
913 | STATIC struct super_operations xfs_super_operations = { | 869 | STATIC struct super_operations xfs_super_operations = { |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index 376b96cb513a..33dd1ca13245 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -105,7 +105,7 @@ struct block_device; | |||
105 | 105 | ||
106 | extern __uint64_t xfs_max_file_offset(unsigned int); | 106 | extern __uint64_t xfs_max_file_offset(unsigned int); |
107 | 107 | ||
108 | extern void xfs_initialize_vnode(bhv_desc_t *, vnode_t *, bhv_desc_t *, int); | 108 | extern void xfs_initialize_vnode(bhv_desc_t *, bhv_vnode_t *, bhv_desc_t *, int); |
109 | 109 | ||
110 | extern void xfs_flush_inode(struct xfs_inode *); | 110 | extern void xfs_flush_inode(struct xfs_inode *); |
111 | extern void xfs_flush_device(struct xfs_inode *); | 111 | extern void xfs_flush_device(struct xfs_inode *); |
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.c b/fs/xfs/linux-2.6/xfs_sysctl.c index 7079cc837210..af246532fbfb 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.c +++ b/fs/xfs/linux-2.6/xfs_sysctl.c | |||
@@ -38,7 +38,7 @@ xfs_stats_clear_proc_handler( | |||
38 | 38 | ||
39 | if (!ret && write && *valp) { | 39 | if (!ret && write && *valp) { |
40 | printk("XFS Clearing xfsstats\n"); | 40 | printk("XFS Clearing xfsstats\n"); |
41 | for_each_cpu(c) { | 41 | for_each_possible_cpu(c) { |
42 | preempt_disable(); | 42 | preempt_disable(); |
43 | /* save vn_active, it's a universal truth! */ | 43 | /* save vn_active, it's a universal truth! */ |
44 | vn_active = per_cpu(xfsstats, c).vn_active; | 44 | vn_active = per_cpu(xfsstats, c).vn_active; |
@@ -120,6 +120,11 @@ STATIC ctl_table xfs_table[] = { | |||
120 | &sysctl_intvec, NULL, | 120 | &sysctl_intvec, NULL, |
121 | &xfs_params.rotorstep.min, &xfs_params.rotorstep.max}, | 121 | &xfs_params.rotorstep.min, &xfs_params.rotorstep.max}, |
122 | 122 | ||
123 | {XFS_INHERIT_NODFRG, "inherit_nodefrag", &xfs_params.inherit_nodfrg.val, | ||
124 | sizeof(int), 0644, NULL, &proc_dointvec_minmax, | ||
125 | &sysctl_intvec, NULL, | ||
126 | &xfs_params.inherit_nodfrg.min, &xfs_params.inherit_nodfrg.max}, | ||
127 | |||
123 | /* please keep this the last entry */ | 128 | /* please keep this the last entry */ |
124 | #ifdef CONFIG_PROC_FS | 129 | #ifdef CONFIG_PROC_FS |
125 | {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val, | 130 | {XFS_STATS_CLEAR, "stats_clear", &xfs_params.stats_clear.val, |
diff --git a/fs/xfs/linux-2.6/xfs_sysctl.h b/fs/xfs/linux-2.6/xfs_sysctl.h index bc8c11f13722..a631fb8cc5ac 100644 --- a/fs/xfs/linux-2.6/xfs_sysctl.h +++ b/fs/xfs/linux-2.6/xfs_sysctl.h | |||
@@ -46,6 +46,7 @@ typedef struct xfs_param { | |||
46 | xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */ | 46 | xfs_sysctl_val_t xfs_buf_age; /* Metadata buffer age before flush. */ |
47 | xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */ | 47 | xfs_sysctl_val_t inherit_nosym; /* Inherit the "nosymlinks" flag. */ |
48 | xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */ | 48 | xfs_sysctl_val_t rotorstep; /* inode32 AG rotoring control knob */ |
49 | xfs_sysctl_val_t inherit_nodfrg;/* Inherit the "nodefrag" inode flag. */ | ||
49 | } xfs_param_t; | 50 | } xfs_param_t; |
50 | 51 | ||
51 | /* | 52 | /* |
@@ -84,6 +85,7 @@ enum { | |||
84 | /* XFS_IO_BYPASS = 18 */ | 85 | /* XFS_IO_BYPASS = 18 */ |
85 | XFS_INHERIT_NOSYM = 19, | 86 | XFS_INHERIT_NOSYM = 19, |
86 | XFS_ROTORSTEP = 20, | 87 | XFS_ROTORSTEP = 20, |
88 | XFS_INHERIT_NODFRG = 21, | ||
87 | }; | 89 | }; |
88 | 90 | ||
89 | extern xfs_param_t xfs_params; | 91 | extern xfs_param_t xfs_params; |
diff --git a/fs/xfs/linux-2.6/xfs_vfs.c b/fs/xfs/linux-2.6/xfs_vfs.c index 6f7c9f7a8624..6145e8bd0be2 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.c +++ b/fs/xfs/linux-2.6/xfs_vfs.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_imap.h" | 27 | #include "xfs_imap.h" |
29 | #include "xfs_alloc.h" | 28 | #include "xfs_alloc.h" |
@@ -104,7 +103,7 @@ vfs_mntupdate( | |||
104 | int | 103 | int |
105 | vfs_root( | 104 | vfs_root( |
106 | struct bhv_desc *bdp, | 105 | struct bhv_desc *bdp, |
107 | struct vnode **vpp) | 106 | struct bhv_vnode **vpp) |
108 | { | 107 | { |
109 | struct bhv_desc *next = bdp; | 108 | struct bhv_desc *next = bdp; |
110 | 109 | ||
@@ -117,15 +116,15 @@ vfs_root( | |||
117 | int | 116 | int |
118 | vfs_statvfs( | 117 | vfs_statvfs( |
119 | struct bhv_desc *bdp, | 118 | struct bhv_desc *bdp, |
120 | xfs_statfs_t *sp, | 119 | bhv_statvfs_t *statp, |
121 | struct vnode *vp) | 120 | struct bhv_vnode *vp) |
122 | { | 121 | { |
123 | struct bhv_desc *next = bdp; | 122 | struct bhv_desc *next = bdp; |
124 | 123 | ||
125 | ASSERT(next); | 124 | ASSERT(next); |
126 | while (! (bhvtovfsops(next))->vfs_statvfs) | 125 | while (! (bhvtovfsops(next))->vfs_statvfs) |
127 | next = BHV_NEXT(next); | 126 | next = BHV_NEXT(next); |
128 | return ((*bhvtovfsops(next)->vfs_statvfs)(next, sp, vp)); | 127 | return ((*bhvtovfsops(next)->vfs_statvfs)(next, statp, vp)); |
129 | } | 128 | } |
130 | 129 | ||
131 | int | 130 | int |
@@ -145,7 +144,7 @@ vfs_sync( | |||
145 | int | 144 | int |
146 | vfs_vget( | 145 | vfs_vget( |
147 | struct bhv_desc *bdp, | 146 | struct bhv_desc *bdp, |
148 | struct vnode **vpp, | 147 | struct bhv_vnode **vpp, |
149 | struct fid *fidp) | 148 | struct fid *fidp) |
150 | { | 149 | { |
151 | struct bhv_desc *next = bdp; | 150 | struct bhv_desc *next = bdp; |
@@ -187,7 +186,7 @@ vfs_quotactl( | |||
187 | void | 186 | void |
188 | vfs_init_vnode( | 187 | vfs_init_vnode( |
189 | struct bhv_desc *bdp, | 188 | struct bhv_desc *bdp, |
190 | struct vnode *vp, | 189 | struct bhv_vnode *vp, |
191 | struct bhv_desc *bp, | 190 | struct bhv_desc *bp, |
192 | int unlock) | 191 | int unlock) |
193 | { | 192 | { |
@@ -226,13 +225,13 @@ vfs_freeze( | |||
226 | ((*bhvtovfsops(next)->vfs_freeze)(next)); | 225 | ((*bhvtovfsops(next)->vfs_freeze)(next)); |
227 | } | 226 | } |
228 | 227 | ||
229 | vfs_t * | 228 | bhv_vfs_t * |
230 | vfs_allocate( | 229 | vfs_allocate( |
231 | struct super_block *sb) | 230 | struct super_block *sb) |
232 | { | 231 | { |
233 | struct vfs *vfsp; | 232 | struct bhv_vfs *vfsp; |
234 | 233 | ||
235 | vfsp = kmem_zalloc(sizeof(vfs_t), KM_SLEEP); | 234 | vfsp = kmem_zalloc(sizeof(bhv_vfs_t), KM_SLEEP); |
236 | bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); | 235 | bhv_head_init(VFS_BHVHEAD(vfsp), "vfs"); |
237 | INIT_LIST_HEAD(&vfsp->vfs_sync_list); | 236 | INIT_LIST_HEAD(&vfsp->vfs_sync_list); |
238 | spin_lock_init(&vfsp->vfs_sync_lock); | 237 | spin_lock_init(&vfsp->vfs_sync_lock); |
@@ -247,25 +246,25 @@ vfs_allocate( | |||
247 | return vfsp; | 246 | return vfsp; |
248 | } | 247 | } |
249 | 248 | ||
250 | vfs_t * | 249 | bhv_vfs_t * |
251 | vfs_from_sb( | 250 | vfs_from_sb( |
252 | struct super_block *sb) | 251 | struct super_block *sb) |
253 | { | 252 | { |
254 | return (vfs_t *)sb->s_fs_info; | 253 | return (bhv_vfs_t *)sb->s_fs_info; |
255 | } | 254 | } |
256 | 255 | ||
257 | void | 256 | void |
258 | vfs_deallocate( | 257 | vfs_deallocate( |
259 | struct vfs *vfsp) | 258 | struct bhv_vfs *vfsp) |
260 | { | 259 | { |
261 | bhv_head_destroy(VFS_BHVHEAD(vfsp)); | 260 | bhv_head_destroy(VFS_BHVHEAD(vfsp)); |
262 | kmem_free(vfsp, sizeof(vfs_t)); | 261 | kmem_free(vfsp, sizeof(bhv_vfs_t)); |
263 | } | 262 | } |
264 | 263 | ||
265 | void | 264 | void |
266 | vfs_insertops( | 265 | vfs_insertops( |
267 | struct vfs *vfsp, | 266 | struct bhv_vfs *vfsp, |
268 | struct bhv_vfsops *vfsops) | 267 | struct bhv_module_vfsops *vfsops) |
269 | { | 268 | { |
270 | struct bhv_desc *bdp; | 269 | struct bhv_desc *bdp; |
271 | 270 | ||
@@ -276,9 +275,9 @@ vfs_insertops( | |||
276 | 275 | ||
277 | void | 276 | void |
278 | vfs_insertbhv( | 277 | vfs_insertbhv( |
279 | struct vfs *vfsp, | 278 | struct bhv_vfs *vfsp, |
280 | struct bhv_desc *bdp, | 279 | struct bhv_desc *bdp, |
281 | struct vfsops *vfsops, | 280 | struct bhv_vfsops *vfsops, |
282 | void *mount) | 281 | void *mount) |
283 | { | 282 | { |
284 | bhv_desc_init(bdp, mount, vfsp, vfsops); | 283 | bhv_desc_init(bdp, mount, vfsp, vfsops); |
@@ -287,7 +286,7 @@ vfs_insertbhv( | |||
287 | 286 | ||
288 | void | 287 | void |
289 | bhv_remove_vfsops( | 288 | bhv_remove_vfsops( |
290 | struct vfs *vfsp, | 289 | struct bhv_vfs *vfsp, |
291 | int pos) | 290 | int pos) |
292 | { | 291 | { |
293 | struct bhv_desc *bhv; | 292 | struct bhv_desc *bhv; |
@@ -301,7 +300,7 @@ bhv_remove_vfsops( | |||
301 | 300 | ||
302 | void | 301 | void |
303 | bhv_remove_all_vfsops( | 302 | bhv_remove_all_vfsops( |
304 | struct vfs *vfsp, | 303 | struct bhv_vfs *vfsp, |
305 | int freebase) | 304 | int freebase) |
306 | { | 305 | { |
307 | struct xfs_mount *mp; | 306 | struct xfs_mount *mp; |
@@ -317,7 +316,7 @@ bhv_remove_all_vfsops( | |||
317 | 316 | ||
318 | void | 317 | void |
319 | bhv_insert_all_vfsops( | 318 | bhv_insert_all_vfsops( |
320 | struct vfs *vfsp) | 319 | struct bhv_vfs *vfsp) |
321 | { | 320 | { |
322 | struct xfs_mount *mp; | 321 | struct xfs_mount *mp; |
323 | 322 | ||
diff --git a/fs/xfs/linux-2.6/xfs_vfs.h b/fs/xfs/linux-2.6/xfs_vfs.h index 841200c03092..91fc2c4b3353 100644 --- a/fs/xfs/linux-2.6/xfs_vfs.h +++ b/fs/xfs/linux-2.6/xfs_vfs.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -21,42 +21,40 @@ | |||
21 | #include <linux/vfs.h> | 21 | #include <linux/vfs.h> |
22 | #include "xfs_fs.h" | 22 | #include "xfs_fs.h" |
23 | 23 | ||
24 | struct bhv_vfs; | ||
25 | struct bhv_vnode; | ||
26 | |||
24 | struct fid; | 27 | struct fid; |
25 | struct vfs; | ||
26 | struct cred; | 28 | struct cred; |
27 | struct vnode; | ||
28 | struct kstatfs; | ||
29 | struct seq_file; | 29 | struct seq_file; |
30 | struct super_block; | 30 | struct super_block; |
31 | struct xfs_mount_args; | 31 | struct xfs_mount_args; |
32 | 32 | ||
33 | typedef struct kstatfs xfs_statfs_t; | 33 | typedef struct kstatfs bhv_statvfs_t; |
34 | 34 | ||
35 | typedef struct vfs_sync_work { | 35 | typedef struct bhv_vfs_sync_work { |
36 | struct list_head w_list; | 36 | struct list_head w_list; |
37 | struct vfs *w_vfs; | 37 | struct bhv_vfs *w_vfs; |
38 | void *w_data; /* syncer routine argument */ | 38 | void *w_data; /* syncer routine argument */ |
39 | void (*w_syncer)(struct vfs *, void *); | 39 | void (*w_syncer)(struct bhv_vfs *, void *); |
40 | } vfs_sync_work_t; | 40 | } bhv_vfs_sync_work_t; |
41 | 41 | ||
42 | typedef struct vfs { | 42 | typedef struct bhv_vfs { |
43 | u_int vfs_flag; /* flags */ | 43 | u_int vfs_flag; /* flags */ |
44 | xfs_fsid_t vfs_fsid; /* file system ID */ | 44 | xfs_fsid_t vfs_fsid; /* file system ID */ |
45 | xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ | 45 | xfs_fsid_t *vfs_altfsid; /* An ID fixed for life of FS */ |
46 | bhv_head_t vfs_bh; /* head of vfs behavior chain */ | 46 | bhv_head_t vfs_bh; /* head of vfs behavior chain */ |
47 | struct super_block *vfs_super; /* generic superblock pointer */ | 47 | struct super_block *vfs_super; /* generic superblock pointer */ |
48 | struct task_struct *vfs_sync_task; /* generalised sync thread */ | 48 | struct task_struct *vfs_sync_task; /* generalised sync thread */ |
49 | vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ | 49 | bhv_vfs_sync_work_t vfs_sync_work; /* work item for VFS_SYNC */ |
50 | struct list_head vfs_sync_list; /* sync thread work item list */ | 50 | struct list_head vfs_sync_list; /* sync thread work item list */ |
51 | spinlock_t vfs_sync_lock; /* work item list lock */ | 51 | spinlock_t vfs_sync_lock; /* work item list lock */ |
52 | int vfs_sync_seq; /* sync thread generation no. */ | 52 | int vfs_sync_seq; /* sync thread generation no. */ |
53 | wait_queue_head_t vfs_wait_single_sync_task; | 53 | wait_queue_head_t vfs_wait_single_sync_task; |
54 | } vfs_t; | 54 | } bhv_vfs_t; |
55 | |||
56 | #define vfs_fbhv vfs_bh.bh_first /* 1st on vfs behavior chain */ | ||
57 | 55 | ||
58 | #define bhvtovfs(bdp) ( (struct vfs *)BHV_VOBJ(bdp) ) | 56 | #define bhvtovfs(bdp) ( (struct bhv_vfs *)BHV_VOBJ(bdp) ) |
59 | #define bhvtovfsops(bdp) ( (struct vfsops *)BHV_OPS(bdp) ) | 57 | #define bhvtovfsops(bdp) ( (struct bhv_vfsops *)BHV_OPS(bdp) ) |
60 | #define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) | 58 | #define VFS_BHVHEAD(vfs) ( &(vfs)->vfs_bh ) |
61 | #define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) | 59 | #define VFS_REMOVEBHV(vfs, bdp) ( bhv_remove(VFS_BHVHEAD(vfs), bdp) ) |
62 | 60 | ||
@@ -71,7 +69,7 @@ typedef enum { | |||
71 | VFS_BHV_QM, /* quota manager */ | 69 | VFS_BHV_QM, /* quota manager */ |
72 | VFS_BHV_IO, /* IO path */ | 70 | VFS_BHV_IO, /* IO path */ |
73 | VFS_BHV_END /* housekeeping end-of-range */ | 71 | VFS_BHV_END /* housekeeping end-of-range */ |
74 | } vfs_bhv_t; | 72 | } bhv_vfs_type_t; |
75 | 73 | ||
76 | #define VFS_POSITION_XFS (BHV_POSITION_BASE) | 74 | #define VFS_POSITION_XFS (BHV_POSITION_BASE) |
77 | #define VFS_POSITION_DM (VFS_POSITION_BASE+10) | 75 | #define VFS_POSITION_DM (VFS_POSITION_BASE+10) |
@@ -81,8 +79,9 @@ typedef enum { | |||
81 | #define VFS_RDONLY 0x0001 /* read-only vfs */ | 79 | #define VFS_RDONLY 0x0001 /* read-only vfs */ |
82 | #define VFS_GRPID 0x0002 /* group-ID assigned from directory */ | 80 | #define VFS_GRPID 0x0002 /* group-ID assigned from directory */ |
83 | #define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ | 81 | #define VFS_DMI 0x0004 /* filesystem has the DMI enabled */ |
84 | #define VFS_32BITINODES 0x0008 /* do not use inums above 32 bits */ | 82 | #define VFS_UMOUNT 0x0008 /* unmount in progress */ |
85 | #define VFS_END 0x0008 /* max flag */ | 83 | #define VFS_32BITINODES 0x0010 /* do not use inums above 32 bits */ |
84 | #define VFS_END 0x0010 /* max flag */ | ||
86 | 85 | ||
87 | #define SYNC_ATTR 0x0001 /* sync attributes */ | 86 | #define SYNC_ATTR 0x0001 /* sync attributes */ |
88 | #define SYNC_CLOSE 0x0002 /* close file system down */ | 87 | #define SYNC_CLOSE 0x0002 /* close file system down */ |
@@ -92,7 +91,14 @@ typedef enum { | |||
92 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ | 91 | #define SYNC_FSDATA 0x0020 /* flush fs data (e.g. superblocks) */ |
93 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ | 92 | #define SYNC_REFCACHE 0x0040 /* prune some of the nfs ref cache */ |
94 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ | 93 | #define SYNC_REMOUNT 0x0080 /* remount readonly, no dummy LRs */ |
95 | #define SYNC_QUIESCE 0x0100 /* quiesce filesystem for a snapshot */ | 94 | #define SYNC_QUIESCE 0x0100 /* quiesce fileystem for a snapshot */ |
95 | |||
96 | #define SHUTDOWN_META_IO_ERROR 0x0001 /* write attempt to metadata failed */ | ||
97 | #define SHUTDOWN_LOG_IO_ERROR 0x0002 /* write attempt to the log failed */ | ||
98 | #define SHUTDOWN_FORCE_UMOUNT 0x0004 /* shutdown from a forced unmount */ | ||
99 | #define SHUTDOWN_CORRUPT_INCORE 0x0008 /* corrupt in-memory data structures */ | ||
100 | #define SHUTDOWN_REMOTE_REQ 0x0010 /* shutdown came from remote cell */ | ||
101 | #define SHUTDOWN_DEVICE_REQ 0x0020 /* failed all paths to the device */ | ||
96 | 102 | ||
97 | typedef int (*vfs_mount_t)(bhv_desc_t *, | 103 | typedef int (*vfs_mount_t)(bhv_desc_t *, |
98 | struct xfs_mount_args *, struct cred *); | 104 | struct xfs_mount_args *, struct cred *); |
@@ -102,18 +108,19 @@ typedef int (*vfs_showargs_t)(bhv_desc_t *, struct seq_file *); | |||
102 | typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); | 108 | typedef int (*vfs_unmount_t)(bhv_desc_t *, int, struct cred *); |
103 | typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, | 109 | typedef int (*vfs_mntupdate_t)(bhv_desc_t *, int *, |
104 | struct xfs_mount_args *); | 110 | struct xfs_mount_args *); |
105 | typedef int (*vfs_root_t)(bhv_desc_t *, struct vnode **); | 111 | typedef int (*vfs_root_t)(bhv_desc_t *, struct bhv_vnode **); |
106 | typedef int (*vfs_statvfs_t)(bhv_desc_t *, xfs_statfs_t *, struct vnode *); | 112 | typedef int (*vfs_statvfs_t)(bhv_desc_t *, bhv_statvfs_t *, |
113 | struct bhv_vnode *); | ||
107 | typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); | 114 | typedef int (*vfs_sync_t)(bhv_desc_t *, int, struct cred *); |
108 | typedef int (*vfs_vget_t)(bhv_desc_t *, struct vnode **, struct fid *); | 115 | typedef int (*vfs_vget_t)(bhv_desc_t *, struct bhv_vnode **, struct fid *); |
109 | typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t); | 116 | typedef int (*vfs_dmapiops_t)(bhv_desc_t *, caddr_t); |
110 | typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t); | 117 | typedef int (*vfs_quotactl_t)(bhv_desc_t *, int, int, caddr_t); |
111 | typedef void (*vfs_init_vnode_t)(bhv_desc_t *, | 118 | typedef void (*vfs_init_vnode_t)(bhv_desc_t *, |
112 | struct vnode *, bhv_desc_t *, int); | 119 | struct bhv_vnode *, bhv_desc_t *, int); |
113 | typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); | 120 | typedef void (*vfs_force_shutdown_t)(bhv_desc_t *, int, char *, int); |
114 | typedef void (*vfs_freeze_t)(bhv_desc_t *); | 121 | typedef void (*vfs_freeze_t)(bhv_desc_t *); |
115 | 122 | ||
116 | typedef struct vfsops { | 123 | typedef struct bhv_vfsops { |
117 | bhv_position_t vf_position; /* behavior chain position */ | 124 | bhv_position_t vf_position; /* behavior chain position */ |
118 | vfs_mount_t vfs_mount; /* mount file system */ | 125 | vfs_mount_t vfs_mount; /* mount file system */ |
119 | vfs_parseargs_t vfs_parseargs; /* parse mount options */ | 126 | vfs_parseargs_t vfs_parseargs; /* parse mount options */ |
@@ -129,82 +136,82 @@ typedef struct vfsops { | |||
129 | vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ | 136 | vfs_init_vnode_t vfs_init_vnode; /* initialize a new vnode */ |
130 | vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ | 137 | vfs_force_shutdown_t vfs_force_shutdown; /* crash and burn */ |
131 | vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ | 138 | vfs_freeze_t vfs_freeze; /* freeze fs for snapshot */ |
132 | } vfsops_t; | 139 | } bhv_vfsops_t; |
133 | 140 | ||
134 | /* | 141 | /* |
135 | * VFS's. Operates on vfs structure pointers (starts at bhv head). | 142 | * Virtual filesystem operations, operating from head bhv. |
136 | */ | 143 | */ |
137 | #define VHEAD(v) ((v)->vfs_fbhv) | 144 | #define VFSHEAD(v) ((v)->vfs_bh.bh_first) |
138 | #define VFS_MOUNT(v, ma,cr, rv) ((rv) = vfs_mount(VHEAD(v), ma,cr)) | 145 | #define bhv_vfs_mount(v, ma,cr) vfs_mount(VFSHEAD(v), ma,cr) |
139 | #define VFS_PARSEARGS(v, o,ma,f, rv) ((rv) = vfs_parseargs(VHEAD(v), o,ma,f)) | 146 | #define bhv_vfs_parseargs(v, o,ma,f) vfs_parseargs(VFSHEAD(v), o,ma,f) |
140 | #define VFS_SHOWARGS(v, m, rv) ((rv) = vfs_showargs(VHEAD(v), m)) | 147 | #define bhv_vfs_showargs(v, m) vfs_showargs(VFSHEAD(v), m) |
141 | #define VFS_UNMOUNT(v, f, cr, rv) ((rv) = vfs_unmount(VHEAD(v), f,cr)) | 148 | #define bhv_vfs_unmount(v, f,cr) vfs_unmount(VFSHEAD(v), f,cr) |
142 | #define VFS_MNTUPDATE(v, fl, args, rv) ((rv) = vfs_mntupdate(VHEAD(v), fl, args)) | 149 | #define bhv_vfs_mntupdate(v, fl,args) vfs_mntupdate(VFSHEAD(v), fl,args) |
143 | #define VFS_ROOT(v, vpp, rv) ((rv) = vfs_root(VHEAD(v), vpp)) | 150 | #define bhv_vfs_root(v, vpp) vfs_root(VFSHEAD(v), vpp) |
144 | #define VFS_STATVFS(v, sp,vp, rv) ((rv) = vfs_statvfs(VHEAD(v), sp,vp)) | 151 | #define bhv_vfs_statvfs(v, sp,vp) vfs_statvfs(VFSHEAD(v), sp,vp) |
145 | #define VFS_SYNC(v, flag,cr, rv) ((rv) = vfs_sync(VHEAD(v), flag,cr)) | 152 | #define bhv_vfs_sync(v, flag,cr) vfs_sync(VFSHEAD(v), flag,cr) |
146 | #define VFS_VGET(v, vpp,fidp, rv) ((rv) = vfs_vget(VHEAD(v), vpp,fidp)) | 153 | #define bhv_vfs_vget(v, vpp,fidp) vfs_vget(VFSHEAD(v), vpp,fidp) |
147 | #define VFS_DMAPIOPS(v, p, rv) ((rv) = vfs_dmapiops(VHEAD(v), p)) | 154 | #define bhv_vfs_dmapiops(v, p) vfs_dmapiops(VFSHEAD(v), p) |
148 | #define VFS_QUOTACTL(v, c,id,p, rv) ((rv) = vfs_quotactl(VHEAD(v), c,id,p)) | 155 | #define bhv_vfs_quotactl(v, c,id,p) vfs_quotactl(VFSHEAD(v), c,id,p) |
149 | #define VFS_INIT_VNODE(v, vp,b,ul) ( vfs_init_vnode(VHEAD(v), vp,b,ul) ) | 156 | #define bhv_vfs_init_vnode(v, vp,b,ul) vfs_init_vnode(VFSHEAD(v), vp,b,ul) |
150 | #define VFS_FORCE_SHUTDOWN(v, fl,f,l) ( vfs_force_shutdown(VHEAD(v), fl,f,l) ) | 157 | #define bhv_vfs_force_shutdown(v,u,f,l) vfs_force_shutdown(VFSHEAD(v), u,f,l) |
151 | #define VFS_FREEZE(v) ( vfs_freeze(VHEAD(v)) ) | 158 | #define bhv_vfs_freeze(v) vfs_freeze(VFSHEAD(v)) |
152 | 159 | ||
153 | /* | 160 | /* |
154 | * PVFS's. Operates on behavior descriptor pointers. | 161 | * Virtual filesystem operations, operating from next bhv. |
155 | */ | 162 | */ |
156 | #define PVFS_MOUNT(b, ma,cr, rv) ((rv) = vfs_mount(b, ma,cr)) | 163 | #define bhv_next_vfs_mount(b, ma,cr) vfs_mount(b, ma,cr) |
157 | #define PVFS_PARSEARGS(b, o,ma,f, rv) ((rv) = vfs_parseargs(b, o,ma,f)) | 164 | #define bhv_next_vfs_parseargs(b, o,ma,f) vfs_parseargs(b, o,ma,f) |
158 | #define PVFS_SHOWARGS(b, m, rv) ((rv) = vfs_showargs(b, m)) | 165 | #define bhv_next_vfs_showargs(b, m) vfs_showargs(b, m) |
159 | #define PVFS_UNMOUNT(b, f,cr, rv) ((rv) = vfs_unmount(b, f,cr)) | 166 | #define bhv_next_vfs_unmount(b, f,cr) vfs_unmount(b, f,cr) |
160 | #define PVFS_MNTUPDATE(b, fl, args, rv) ((rv) = vfs_mntupdate(b, fl, args)) | 167 | #define bhv_next_vfs_mntupdate(b, fl,args) vfs_mntupdate(b, fl, args) |
161 | #define PVFS_ROOT(b, vpp, rv) ((rv) = vfs_root(b, vpp)) | 168 | #define bhv_next_vfs_root(b, vpp) vfs_root(b, vpp) |
162 | #define PVFS_STATVFS(b, sp,vp, rv) ((rv) = vfs_statvfs(b, sp,vp)) | 169 | #define bhv_next_vfs_statvfs(b, sp,vp) vfs_statvfs(b, sp,vp) |
163 | #define PVFS_SYNC(b, flag,cr, rv) ((rv) = vfs_sync(b, flag,cr)) | 170 | #define bhv_next_vfs_sync(b, flag,cr) vfs_sync(b, flag,cr) |
164 | #define PVFS_VGET(b, vpp,fidp, rv) ((rv) = vfs_vget(b, vpp,fidp)) | 171 | #define bhv_next_vfs_vget(b, vpp,fidp) vfs_vget(b, vpp,fidp) |
165 | #define PVFS_DMAPIOPS(b, p, rv) ((rv) = vfs_dmapiops(b, p)) | 172 | #define bhv_next_vfs_dmapiops(b, p) vfs_dmapiops(b, p) |
166 | #define PVFS_QUOTACTL(b, c,id,p, rv) ((rv) = vfs_quotactl(b, c,id,p)) | 173 | #define bhv_next_vfs_quotactl(b, c,id,p) vfs_quotactl(b, c,id,p) |
167 | #define PVFS_INIT_VNODE(b, vp,b2,ul) ( vfs_init_vnode(b, vp,b2,ul) ) | 174 | #define bhv_next_vfs_init_vnode(b, vp,b2,ul) vfs_init_vnode(b, vp,b2,ul) |
168 | #define PVFS_FORCE_SHUTDOWN(b, fl,f,l) ( vfs_force_shutdown(b, fl,f,l) ) | 175 | #define bhv_next_force_shutdown(b, fl,f,l) vfs_force_shutdown(b, fl,f,l) |
169 | #define PVFS_FREEZE(b) ( vfs_freeze(b) ) | 176 | #define bhv_next_vfs_freeze(b) vfs_freeze(b) |
170 | 177 | ||
171 | extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); | 178 | extern int vfs_mount(bhv_desc_t *, struct xfs_mount_args *, struct cred *); |
172 | extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); | 179 | extern int vfs_parseargs(bhv_desc_t *, char *, struct xfs_mount_args *, int); |
173 | extern int vfs_showargs(bhv_desc_t *, struct seq_file *); | 180 | extern int vfs_showargs(bhv_desc_t *, struct seq_file *); |
174 | extern int vfs_unmount(bhv_desc_t *, int, struct cred *); | 181 | extern int vfs_unmount(bhv_desc_t *, int, struct cred *); |
175 | extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); | 182 | extern int vfs_mntupdate(bhv_desc_t *, int *, struct xfs_mount_args *); |
176 | extern int vfs_root(bhv_desc_t *, struct vnode **); | 183 | extern int vfs_root(bhv_desc_t *, struct bhv_vnode **); |
177 | extern int vfs_statvfs(bhv_desc_t *, xfs_statfs_t *, struct vnode *); | 184 | extern int vfs_statvfs(bhv_desc_t *, bhv_statvfs_t *, struct bhv_vnode *); |
178 | extern int vfs_sync(bhv_desc_t *, int, struct cred *); | 185 | extern int vfs_sync(bhv_desc_t *, int, struct cred *); |
179 | extern int vfs_vget(bhv_desc_t *, struct vnode **, struct fid *); | 186 | extern int vfs_vget(bhv_desc_t *, struct bhv_vnode **, struct fid *); |
180 | extern int vfs_dmapiops(bhv_desc_t *, caddr_t); | 187 | extern int vfs_dmapiops(bhv_desc_t *, caddr_t); |
181 | extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t); | 188 | extern int vfs_quotactl(bhv_desc_t *, int, int, caddr_t); |
182 | extern void vfs_init_vnode(bhv_desc_t *, struct vnode *, bhv_desc_t *, int); | 189 | extern void vfs_init_vnode(bhv_desc_t *, struct bhv_vnode *, bhv_desc_t *, int); |
183 | extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); | 190 | extern void vfs_force_shutdown(bhv_desc_t *, int, char *, int); |
184 | extern void vfs_freeze(bhv_desc_t *); | 191 | extern void vfs_freeze(bhv_desc_t *); |
185 | 192 | ||
186 | typedef struct bhv_vfsops { | 193 | #define vfs_test_for_freeze(vfs) ((vfs)->vfs_super->s_frozen) |
187 | struct vfsops bhv_common; | 194 | #define vfs_wait_for_freeze(vfs,l) vfs_check_frozen((vfs)->vfs_super, (l)) |
195 | |||
196 | typedef struct bhv_module_vfsops { | ||
197 | struct bhv_vfsops bhv_common; | ||
188 | void * bhv_custom; | 198 | void * bhv_custom; |
189 | } bhv_vfsops_t; | 199 | } bhv_module_vfsops_t; |
190 | 200 | ||
191 | #define vfs_bhv_lookup(v, id) ( bhv_lookup_range(&(v)->vfs_bh, (id), (id)) ) | 201 | #define vfs_bhv_lookup(v, id) (bhv_lookup_range(&(v)->vfs_bh, (id), (id))) |
192 | #define vfs_bhv_custom(b) ( ((bhv_vfsops_t *)BHV_OPS(b))->bhv_custom ) | 202 | #define vfs_bhv_custom(b) (((bhv_module_vfsops_t*)BHV_OPS(b))->bhv_custom) |
193 | #define vfs_bhv_set_custom(b,o) ( (b)->bhv_custom = (void *)(o)) | 203 | #define vfs_bhv_set_custom(b,o) ((b)->bhv_custom = (void *)(o)) |
194 | #define vfs_bhv_clr_custom(b) ( (b)->bhv_custom = NULL ) | 204 | #define vfs_bhv_clr_custom(b) ((b)->bhv_custom = NULL) |
195 | 205 | ||
196 | extern vfs_t *vfs_allocate(struct super_block *); | 206 | extern bhv_vfs_t *vfs_allocate(struct super_block *); |
197 | extern vfs_t *vfs_from_sb(struct super_block *); | 207 | extern bhv_vfs_t *vfs_from_sb(struct super_block *); |
198 | extern void vfs_deallocate(vfs_t *); | 208 | extern void vfs_deallocate(bhv_vfs_t *); |
199 | extern void vfs_insertops(vfs_t *, bhv_vfsops_t *); | 209 | extern void vfs_insertbhv(bhv_vfs_t *, bhv_desc_t *, bhv_vfsops_t *, void *); |
200 | extern void vfs_insertbhv(vfs_t *, bhv_desc_t *, vfsops_t *, void *); | ||
201 | 210 | ||
202 | extern void bhv_insert_all_vfsops(struct vfs *); | 211 | extern void vfs_insertops(bhv_vfs_t *, bhv_module_vfsops_t *); |
203 | extern void bhv_remove_all_vfsops(struct vfs *, int); | ||
204 | extern void bhv_remove_vfsops(struct vfs *, int); | ||
205 | 212 | ||
206 | #define fs_frozen(vfsp) ((vfsp)->vfs_super->s_frozen) | 213 | extern void bhv_insert_all_vfsops(struct bhv_vfs *); |
207 | #define fs_check_frozen(vfsp, level) \ | 214 | extern void bhv_remove_all_vfsops(struct bhv_vfs *, int); |
208 | vfs_check_frozen(vfsp->vfs_super, level); | 215 | extern void bhv_remove_vfsops(struct bhv_vfs *, int); |
209 | 216 | ||
210 | #endif /* __XFS_VFS_H__ */ | 217 | #endif /* __XFS_VFS_H__ */ |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.c b/fs/xfs/linux-2.6/xfs_vnode.c index d27c25b27ccd..6628d96b6fd6 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.c +++ b/fs/xfs/linux-2.6/xfs_vnode.c | |||
@@ -39,7 +39,7 @@ vn_init(void) | |||
39 | 39 | ||
40 | void | 40 | void |
41 | vn_iowait( | 41 | vn_iowait( |
42 | struct vnode *vp) | 42 | bhv_vnode_t *vp) |
43 | { | 43 | { |
44 | wait_queue_head_t *wq = vptosync(vp); | 44 | wait_queue_head_t *wq = vptosync(vp); |
45 | 45 | ||
@@ -48,17 +48,33 @@ vn_iowait( | |||
48 | 48 | ||
49 | void | 49 | void |
50 | vn_iowake( | 50 | vn_iowake( |
51 | struct vnode *vp) | 51 | bhv_vnode_t *vp) |
52 | { | 52 | { |
53 | if (atomic_dec_and_test(&vp->v_iocount)) | 53 | if (atomic_dec_and_test(&vp->v_iocount)) |
54 | wake_up(vptosync(vp)); | 54 | wake_up(vptosync(vp)); |
55 | } | 55 | } |
56 | 56 | ||
57 | struct vnode * | 57 | /* |
58 | * Volume managers supporting multiple paths can send back ENODEV when the | ||
59 | * final path disappears. In this case continuing to fill the page cache | ||
60 | * with dirty data which cannot be written out is evil, so prevent that. | ||
61 | */ | ||
62 | void | ||
63 | vn_ioerror( | ||
64 | bhv_vnode_t *vp, | ||
65 | int error, | ||
66 | char *f, | ||
67 | int l) | ||
68 | { | ||
69 | if (unlikely(error == -ENODEV)) | ||
70 | bhv_vfs_force_shutdown(vp->v_vfsp, SHUTDOWN_DEVICE_REQ, f, l); | ||
71 | } | ||
72 | |||
73 | bhv_vnode_t * | ||
58 | vn_initialize( | 74 | vn_initialize( |
59 | struct inode *inode) | 75 | struct inode *inode) |
60 | { | 76 | { |
61 | struct vnode *vp = vn_from_inode(inode); | 77 | bhv_vnode_t *vp = vn_from_inode(inode); |
62 | 78 | ||
63 | XFS_STATS_INC(vn_active); | 79 | XFS_STATS_INC(vn_active); |
64 | XFS_STATS_INC(vn_alloc); | 80 | XFS_STATS_INC(vn_alloc); |
@@ -94,8 +110,8 @@ vn_initialize( | |||
94 | */ | 110 | */ |
95 | void | 111 | void |
96 | vn_revalidate_core( | 112 | vn_revalidate_core( |
97 | struct vnode *vp, | 113 | bhv_vnode_t *vp, |
98 | vattr_t *vap) | 114 | bhv_vattr_t *vap) |
99 | { | 115 | { |
100 | struct inode *inode = vn_to_inode(vp); | 116 | struct inode *inode = vn_to_inode(vp); |
101 | 117 | ||
@@ -130,14 +146,14 @@ vn_revalidate_core( | |||
130 | */ | 146 | */ |
131 | int | 147 | int |
132 | __vn_revalidate( | 148 | __vn_revalidate( |
133 | struct vnode *vp, | 149 | bhv_vnode_t *vp, |
134 | struct vattr *vattr) | 150 | bhv_vattr_t *vattr) |
135 | { | 151 | { |
136 | int error; | 152 | int error; |
137 | 153 | ||
138 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 154 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
139 | vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS; | 155 | vattr->va_mask = XFS_AT_STAT | XFS_AT_XFLAGS; |
140 | VOP_GETATTR(vp, vattr, 0, NULL, error); | 156 | error = bhv_vop_getattr(vp, vattr, 0, NULL); |
141 | if (likely(!error)) { | 157 | if (likely(!error)) { |
142 | vn_revalidate_core(vp, vattr); | 158 | vn_revalidate_core(vp, vattr); |
143 | VUNMODIFY(vp); | 159 | VUNMODIFY(vp); |
@@ -147,9 +163,9 @@ __vn_revalidate( | |||
147 | 163 | ||
148 | int | 164 | int |
149 | vn_revalidate( | 165 | vn_revalidate( |
150 | struct vnode *vp) | 166 | bhv_vnode_t *vp) |
151 | { | 167 | { |
152 | vattr_t vattr; | 168 | bhv_vattr_t vattr; |
153 | 169 | ||
154 | return __vn_revalidate(vp, &vattr); | 170 | return __vn_revalidate(vp, &vattr); |
155 | } | 171 | } |
@@ -157,9 +173,9 @@ vn_revalidate( | |||
157 | /* | 173 | /* |
158 | * Add a reference to a referenced vnode. | 174 | * Add a reference to a referenced vnode. |
159 | */ | 175 | */ |
160 | struct vnode * | 176 | bhv_vnode_t * |
161 | vn_hold( | 177 | vn_hold( |
162 | struct vnode *vp) | 178 | bhv_vnode_t *vp) |
163 | { | 179 | { |
164 | struct inode *inode; | 180 | struct inode *inode; |
165 | 181 | ||
@@ -192,31 +208,31 @@ vn_hold( | |||
192 | * Vnode tracing code. | 208 | * Vnode tracing code. |
193 | */ | 209 | */ |
194 | void | 210 | void |
195 | vn_trace_entry(vnode_t *vp, const char *func, inst_t *ra) | 211 | vn_trace_entry(bhv_vnode_t *vp, const char *func, inst_t *ra) |
196 | { | 212 | { |
197 | KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); | 213 | KTRACE_ENTER(vp, VNODE_KTRACE_ENTRY, func, 0, ra); |
198 | } | 214 | } |
199 | 215 | ||
200 | void | 216 | void |
201 | vn_trace_exit(vnode_t *vp, const char *func, inst_t *ra) | 217 | vn_trace_exit(bhv_vnode_t *vp, const char *func, inst_t *ra) |
202 | { | 218 | { |
203 | KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); | 219 | KTRACE_ENTER(vp, VNODE_KTRACE_EXIT, func, 0, ra); |
204 | } | 220 | } |
205 | 221 | ||
206 | void | 222 | void |
207 | vn_trace_hold(vnode_t *vp, char *file, int line, inst_t *ra) | 223 | vn_trace_hold(bhv_vnode_t *vp, char *file, int line, inst_t *ra) |
208 | { | 224 | { |
209 | KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra); | 225 | KTRACE_ENTER(vp, VNODE_KTRACE_HOLD, file, line, ra); |
210 | } | 226 | } |
211 | 227 | ||
212 | void | 228 | void |
213 | vn_trace_ref(vnode_t *vp, char *file, int line, inst_t *ra) | 229 | vn_trace_ref(bhv_vnode_t *vp, char *file, int line, inst_t *ra) |
214 | { | 230 | { |
215 | KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra); | 231 | KTRACE_ENTER(vp, VNODE_KTRACE_REF, file, line, ra); |
216 | } | 232 | } |
217 | 233 | ||
218 | void | 234 | void |
219 | vn_trace_rele(vnode_t *vp, char *file, int line, inst_t *ra) | 235 | vn_trace_rele(bhv_vnode_t *vp, char *file, int line, inst_t *ra) |
220 | { | 236 | { |
221 | KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra); | 237 | KTRACE_ENTER(vp, VNODE_KTRACE_RELE, file, line, ra); |
222 | } | 238 | } |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index 2a8e16c22353..35c6a01963a7 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -14,57 +14,35 @@ | |||
14 | * You should have received a copy of the GNU General Public License | 14 | * You should have received a copy of the GNU General Public License |
15 | * along with this program; if not, write the Free Software Foundation, | 15 | * along with this program; if not, write the Free Software Foundation, |
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | * | ||
18 | * Portions Copyright (c) 1989, 1993 | ||
19 | * The Regents of the University of California. All rights reserved. | ||
20 | * | ||
21 | * Redistribution and use in source and binary forms, with or without | ||
22 | * modification, are permitted provided that the following conditions | ||
23 | * are met: | ||
24 | * 1. Redistributions of source code must retain the above copyright | ||
25 | * notice, this list of conditions and the following disclaimer. | ||
26 | * 2. Redistributions in binary form must reproduce the above copyright | ||
27 | * notice, this list of conditions and the following disclaimer in the | ||
28 | * documentation and/or other materials provided with the distribution. | ||
29 | * 3. Neither the name of the University nor the names of its contributors | ||
30 | * may be used to endorse or promote products derived from this software | ||
31 | * without specific prior written permission. | ||
32 | * | ||
33 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||
34 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
35 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
36 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||
37 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
39 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
40 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
41 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
42 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
43 | * SUCH DAMAGE. | ||
44 | */ | 17 | */ |
45 | #ifndef __XFS_VNODE_H__ | 18 | #ifndef __XFS_VNODE_H__ |
46 | #define __XFS_VNODE_H__ | 19 | #define __XFS_VNODE_H__ |
47 | 20 | ||
48 | struct uio; | 21 | struct uio; |
49 | struct file; | 22 | struct file; |
50 | struct vattr; | 23 | struct bhv_vfs; |
24 | struct bhv_vattr; | ||
51 | struct xfs_iomap; | 25 | struct xfs_iomap; |
52 | struct attrlist_cursor_kern; | 26 | struct attrlist_cursor_kern; |
53 | 27 | ||
28 | typedef struct dentry bhv_vname_t; | ||
29 | typedef __u64 bhv_vnumber_t; | ||
54 | 30 | ||
55 | typedef xfs_ino_t vnumber_t; | 31 | typedef enum bhv_vflags { |
56 | typedef struct dentry vname_t; | 32 | VMODIFIED = 0x08, /* XFS inode state possibly differs */ |
57 | typedef bhv_head_t vn_bhv_head_t; | 33 | /* to the Linux inode state. */ |
34 | VTRUNCATED = 0x40, /* truncated down so flush-on-close */ | ||
35 | } bhv_vflags_t; | ||
58 | 36 | ||
59 | /* | 37 | /* |
60 | * MP locking protocols: | 38 | * MP locking protocols: |
61 | * v_flag, v_vfsp VN_LOCK/VN_UNLOCK | 39 | * v_flag, v_vfsp VN_LOCK/VN_UNLOCK |
62 | */ | 40 | */ |
63 | typedef struct vnode { | 41 | typedef struct bhv_vnode { |
64 | __u32 v_flag; /* vnode flags (see below) */ | 42 | bhv_vflags_t v_flag; /* vnode flags (see above) */ |
65 | struct vfs *v_vfsp; /* ptr to containing VFS */ | 43 | bhv_vfs_t *v_vfsp; /* ptr to containing VFS */ |
66 | vnumber_t v_number; /* in-core vnode number */ | 44 | bhv_vnumber_t v_number; /* in-core vnode number */ |
67 | vn_bhv_head_t v_bh; /* behavior head */ | 45 | bhv_head_t v_bh; /* behavior head */ |
68 | spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ | 46 | spinlock_t v_lock; /* VN_LOCK/VN_UNLOCK */ |
69 | atomic_t v_iocount; /* outstanding I/O count */ | 47 | atomic_t v_iocount; /* outstanding I/O count */ |
70 | #ifdef XFS_VNODE_TRACE | 48 | #ifdef XFS_VNODE_TRACE |
@@ -72,7 +50,7 @@ typedef struct vnode { | |||
72 | #endif | 50 | #endif |
73 | struct inode v_inode; /* Linux inode */ | 51 | struct inode v_inode; /* Linux inode */ |
74 | /* inode MUST be last */ | 52 | /* inode MUST be last */ |
75 | } vnode_t; | 53 | } bhv_vnode_t; |
76 | 54 | ||
77 | #define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode) | 55 | #define VN_ISLNK(vp) S_ISLNK((vp)->v_inode.i_mode) |
78 | #define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode) | 56 | #define VN_ISREG(vp) S_ISREG((vp)->v_inode.i_mode) |
@@ -80,9 +58,6 @@ typedef struct vnode { | |||
80 | #define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode) | 58 | #define VN_ISCHR(vp) S_ISCHR((vp)->v_inode.i_mode) |
81 | #define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode) | 59 | #define VN_ISBLK(vp) S_ISBLK((vp)->v_inode.i_mode) |
82 | 60 | ||
83 | #define v_fbhv v_bh.bh_first /* first behavior */ | ||
84 | #define v_fops v_bh.bh_first->bd_ops /* first behavior ops */ | ||
85 | |||
86 | #define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ | 61 | #define VNODE_POSITION_BASE BHV_POSITION_BASE /* chain bottom */ |
87 | #define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */ | 62 | #define VNODE_POSITION_TOP BHV_POSITION_TOP /* chain top */ |
88 | #define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ | 63 | #define VNODE_POSITION_INVALID BHV_POSITION_INVALID /* invalid pos. num */ |
@@ -104,8 +79,8 @@ typedef enum { | |||
104 | /* | 79 | /* |
105 | * Macros for dealing with the behavior descriptor inside of the vnode. | 80 | * Macros for dealing with the behavior descriptor inside of the vnode. |
106 | */ | 81 | */ |
107 | #define BHV_TO_VNODE(bdp) ((vnode_t *)BHV_VOBJ(bdp)) | 82 | #define BHV_TO_VNODE(bdp) ((bhv_vnode_t *)BHV_VOBJ(bdp)) |
108 | #define BHV_TO_VNODE_NULL(bdp) ((vnode_t *)BHV_VOBJNULL(bdp)) | 83 | #define BHV_TO_VNODE_NULL(bdp) ((bhv_vnode_t *)BHV_VOBJNULL(bdp)) |
109 | 84 | ||
110 | #define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) | 85 | #define VN_BHV_HEAD(vp) ((bhv_head_t *)(&((vp)->v_bh))) |
111 | #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) | 86 | #define vn_bhv_head_init(bhp,name) bhv_head_init(bhp,name) |
@@ -116,35 +91,29 @@ typedef enum { | |||
116 | /* | 91 | /* |
117 | * Vnode to Linux inode mapping. | 92 | * Vnode to Linux inode mapping. |
118 | */ | 93 | */ |
119 | static inline struct vnode *vn_from_inode(struct inode *inode) | 94 | static inline struct bhv_vnode *vn_from_inode(struct inode *inode) |
120 | { | 95 | { |
121 | return (vnode_t *)list_entry(inode, vnode_t, v_inode); | 96 | return (bhv_vnode_t *)list_entry(inode, bhv_vnode_t, v_inode); |
122 | } | 97 | } |
123 | static inline struct inode *vn_to_inode(struct vnode *vnode) | 98 | static inline struct inode *vn_to_inode(struct bhv_vnode *vnode) |
124 | { | 99 | { |
125 | return &vnode->v_inode; | 100 | return &vnode->v_inode; |
126 | } | 101 | } |
127 | 102 | ||
128 | /* | 103 | /* |
129 | * Vnode flags. | 104 | * Values for the vop_rwlock/rwunlock flags parameter. |
130 | */ | ||
131 | #define VMODIFIED 0x8 /* XFS inode state possibly differs */ | ||
132 | /* to the Linux inode state. */ | ||
133 | |||
134 | /* | ||
135 | * Values for the VOP_RWLOCK and VOP_RWUNLOCK flags parameter. | ||
136 | */ | 105 | */ |
137 | typedef enum vrwlock { | 106 | typedef enum bhv_vrwlock { |
138 | VRWLOCK_NONE, | 107 | VRWLOCK_NONE, |
139 | VRWLOCK_READ, | 108 | VRWLOCK_READ, |
140 | VRWLOCK_WRITE, | 109 | VRWLOCK_WRITE, |
141 | VRWLOCK_WRITE_DIRECT, | 110 | VRWLOCK_WRITE_DIRECT, |
142 | VRWLOCK_TRY_READ, | 111 | VRWLOCK_TRY_READ, |
143 | VRWLOCK_TRY_WRITE | 112 | VRWLOCK_TRY_WRITE |
144 | } vrwlock_t; | 113 | } bhv_vrwlock_t; |
145 | 114 | ||
146 | /* | 115 | /* |
147 | * Return values for VOP_INACTIVE. A return value of | 116 | * Return values for bhv_vop_inactive. A return value of |
148 | * VN_INACTIVE_NOCACHE implies that the file system behavior | 117 | * VN_INACTIVE_NOCACHE implies that the file system behavior |
149 | * has disassociated its state and bhv_desc_t from the vnode. | 118 | * has disassociated its state and bhv_desc_t from the vnode. |
150 | */ | 119 | */ |
@@ -152,18 +121,20 @@ typedef enum vrwlock { | |||
152 | #define VN_INACTIVE_NOCACHE 1 | 121 | #define VN_INACTIVE_NOCACHE 1 |
153 | 122 | ||
154 | /* | 123 | /* |
155 | * Values for the cmd code given to VOP_VNODE_CHANGE. | 124 | * Values for the cmd code given to vop_vnode_change. |
156 | */ | 125 | */ |
157 | typedef enum vchange { | 126 | typedef enum bhv_vchange { |
158 | VCHANGE_FLAGS_FRLOCKS = 0, | 127 | VCHANGE_FLAGS_FRLOCKS = 0, |
159 | VCHANGE_FLAGS_ENF_LOCKING = 1, | 128 | VCHANGE_FLAGS_ENF_LOCKING = 1, |
160 | VCHANGE_FLAGS_TRUNCATED = 2, | 129 | VCHANGE_FLAGS_TRUNCATED = 2, |
161 | VCHANGE_FLAGS_PAGE_DIRTY = 3, | 130 | VCHANGE_FLAGS_PAGE_DIRTY = 3, |
162 | VCHANGE_FLAGS_IOEXCL_COUNT = 4 | 131 | VCHANGE_FLAGS_IOEXCL_COUNT = 4 |
163 | } vchange_t; | 132 | } bhv_vchange_t; |
164 | 133 | ||
134 | typedef enum { L_FALSE, L_TRUE } lastclose_t; | ||
165 | 135 | ||
166 | typedef int (*vop_open_t)(bhv_desc_t *, struct cred *); | 136 | typedef int (*vop_open_t)(bhv_desc_t *, struct cred *); |
137 | typedef int (*vop_close_t)(bhv_desc_t *, int, lastclose_t, struct cred *); | ||
167 | typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, | 138 | typedef ssize_t (*vop_read_t)(bhv_desc_t *, struct kiocb *, |
168 | const struct iovec *, unsigned int, | 139 | const struct iovec *, unsigned int, |
169 | loff_t *, int, struct cred *); | 140 | loff_t *, int, struct cred *); |
@@ -181,27 +152,27 @@ typedef ssize_t (*vop_splice_write_t)(bhv_desc_t *, struct pipe_inode_info *, | |||
181 | struct cred *); | 152 | struct cred *); |
182 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, | 153 | typedef int (*vop_ioctl_t)(bhv_desc_t *, struct inode *, struct file *, |
183 | int, unsigned int, void __user *); | 154 | int, unsigned int, void __user *); |
184 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct vattr *, int, | 155 | typedef int (*vop_getattr_t)(bhv_desc_t *, struct bhv_vattr *, int, |
185 | struct cred *); | 156 | struct cred *); |
186 | typedef int (*vop_setattr_t)(bhv_desc_t *, struct vattr *, int, | 157 | typedef int (*vop_setattr_t)(bhv_desc_t *, struct bhv_vattr *, int, |
187 | struct cred *); | 158 | struct cred *); |
188 | typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); | 159 | typedef int (*vop_access_t)(bhv_desc_t *, int, struct cred *); |
189 | typedef int (*vop_lookup_t)(bhv_desc_t *, vname_t *, vnode_t **, | 160 | typedef int (*vop_lookup_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t **, |
190 | int, vnode_t *, struct cred *); | 161 | int, bhv_vnode_t *, struct cred *); |
191 | typedef int (*vop_create_t)(bhv_desc_t *, vname_t *, struct vattr *, | 162 | typedef int (*vop_create_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, |
192 | vnode_t **, struct cred *); | 163 | bhv_vnode_t **, struct cred *); |
193 | typedef int (*vop_remove_t)(bhv_desc_t *, vname_t *, struct cred *); | 164 | typedef int (*vop_remove_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); |
194 | typedef int (*vop_link_t)(bhv_desc_t *, vnode_t *, vname_t *, | 165 | typedef int (*vop_link_t)(bhv_desc_t *, bhv_vnode_t *, bhv_vname_t *, |
195 | struct cred *); | ||
196 | typedef int (*vop_rename_t)(bhv_desc_t *, vname_t *, vnode_t *, vname_t *, | ||
197 | struct cred *); | 166 | struct cred *); |
198 | typedef int (*vop_mkdir_t)(bhv_desc_t *, vname_t *, struct vattr *, | 167 | typedef int (*vop_rename_t)(bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *, |
199 | vnode_t **, struct cred *); | 168 | bhv_vname_t *, struct cred *); |
200 | typedef int (*vop_rmdir_t)(bhv_desc_t *, vname_t *, struct cred *); | 169 | typedef int (*vop_mkdir_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr *, |
170 | bhv_vnode_t **, struct cred *); | ||
171 | typedef int (*vop_rmdir_t)(bhv_desc_t *, bhv_vname_t *, struct cred *); | ||
201 | typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, | 172 | typedef int (*vop_readdir_t)(bhv_desc_t *, struct uio *, struct cred *, |
202 | int *); | 173 | int *); |
203 | typedef int (*vop_symlink_t)(bhv_desc_t *, vname_t *, struct vattr *, | 174 | typedef int (*vop_symlink_t)(bhv_desc_t *, bhv_vname_t *, struct bhv_vattr*, |
204 | char *, vnode_t **, struct cred *); | 175 | char *, bhv_vnode_t **, struct cred *); |
205 | typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, | 176 | typedef int (*vop_readlink_t)(bhv_desc_t *, struct uio *, int, |
206 | struct cred *); | 177 | struct cred *); |
207 | typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, | 178 | typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, |
@@ -209,8 +180,8 @@ typedef int (*vop_fsync_t)(bhv_desc_t *, int, struct cred *, | |||
209 | typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); | 180 | typedef int (*vop_inactive_t)(bhv_desc_t *, struct cred *); |
210 | typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *); | 181 | typedef int (*vop_fid2_t)(bhv_desc_t *, struct fid *); |
211 | typedef int (*vop_release_t)(bhv_desc_t *); | 182 | typedef int (*vop_release_t)(bhv_desc_t *); |
212 | typedef int (*vop_rwlock_t)(bhv_desc_t *, vrwlock_t); | 183 | typedef int (*vop_rwlock_t)(bhv_desc_t *, bhv_vrwlock_t); |
213 | typedef void (*vop_rwunlock_t)(bhv_desc_t *, vrwlock_t); | 184 | typedef void (*vop_rwunlock_t)(bhv_desc_t *, bhv_vrwlock_t); |
214 | typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int, | 185 | typedef int (*vop_bmap_t)(bhv_desc_t *, xfs_off_t, ssize_t, int, |
215 | struct xfs_iomap *, int *); | 186 | struct xfs_iomap *, int *); |
216 | typedef int (*vop_reclaim_t)(bhv_desc_t *); | 187 | typedef int (*vop_reclaim_t)(bhv_desc_t *); |
@@ -222,8 +193,8 @@ typedef int (*vop_attr_remove_t)(bhv_desc_t *, const char *, | |||
222 | int, struct cred *); | 193 | int, struct cred *); |
223 | typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, | 194 | typedef int (*vop_attr_list_t)(bhv_desc_t *, char *, int, int, |
224 | struct attrlist_cursor_kern *, struct cred *); | 195 | struct attrlist_cursor_kern *, struct cred *); |
225 | typedef void (*vop_link_removed_t)(bhv_desc_t *, vnode_t *, int); | 196 | typedef void (*vop_link_removed_t)(bhv_desc_t *, bhv_vnode_t *, int); |
226 | typedef void (*vop_vnode_change_t)(bhv_desc_t *, vchange_t, __psint_t); | 197 | typedef void (*vop_vnode_change_t)(bhv_desc_t *, bhv_vchange_t, __psint_t); |
227 | typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); | 198 | typedef void (*vop_ptossvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); |
228 | typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); | 199 | typedef void (*vop_pflushinvalvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, int); |
229 | typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, | 200 | typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, |
@@ -231,9 +202,10 @@ typedef int (*vop_pflushvp_t)(bhv_desc_t *, xfs_off_t, xfs_off_t, | |||
231 | typedef int (*vop_iflush_t)(bhv_desc_t *, int); | 202 | typedef int (*vop_iflush_t)(bhv_desc_t *, int); |
232 | 203 | ||
233 | 204 | ||
234 | typedef struct vnodeops { | 205 | typedef struct bhv_vnodeops { |
235 | bhv_position_t vn_position; /* position within behavior chain */ | 206 | bhv_position_t vn_position; /* position within behavior chain */ |
236 | vop_open_t vop_open; | 207 | vop_open_t vop_open; |
208 | vop_close_t vop_close; | ||
237 | vop_read_t vop_read; | 209 | vop_read_t vop_read; |
238 | vop_write_t vop_write; | 210 | vop_write_t vop_write; |
239 | vop_sendfile_t vop_sendfile; | 211 | vop_sendfile_t vop_sendfile; |
@@ -271,103 +243,80 @@ typedef struct vnodeops { | |||
271 | vop_pflushvp_t vop_flush_pages; | 243 | vop_pflushvp_t vop_flush_pages; |
272 | vop_release_t vop_release; | 244 | vop_release_t vop_release; |
273 | vop_iflush_t vop_iflush; | 245 | vop_iflush_t vop_iflush; |
274 | } vnodeops_t; | 246 | } bhv_vnodeops_t; |
275 | 247 | ||
276 | /* | 248 | /* |
277 | * VOP's. | 249 | * Virtual node operations, operating from head bhv. |
278 | */ | ||
279 | #define _VOP_(op, vp) (*((vnodeops_t *)(vp)->v_fops)->op) | ||
280 | |||
281 | #define VOP_READ(vp,file,iov,segs,offset,ioflags,cr,rv) \ | ||
282 | rv = _VOP_(vop_read, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) | ||
283 | #define VOP_WRITE(vp,file,iov,segs,offset,ioflags,cr,rv) \ | ||
284 | rv = _VOP_(vop_write, vp)((vp)->v_fbhv,file,iov,segs,offset,ioflags,cr) | ||
285 | #define VOP_SENDFILE(vp,f,off,ioflags,cnt,act,targ,cr,rv) \ | ||
286 | rv = _VOP_(vop_sendfile, vp)((vp)->v_fbhv,f,off,ioflags,cnt,act,targ,cr) | ||
287 | #define VOP_SPLICE_READ(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ | ||
288 | rv = _VOP_(vop_splice_read, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) | ||
289 | #define VOP_SPLICE_WRITE(vp,f,o,pipe,cnt,fl,iofl,cr,rv) \ | ||
290 | rv = _VOP_(vop_splice_write, vp)((vp)->v_fbhv,f,o,pipe,cnt,fl,iofl,cr) | ||
291 | #define VOP_BMAP(vp,of,sz,rw,b,n,rv) \ | ||
292 | rv = _VOP_(vop_bmap, vp)((vp)->v_fbhv,of,sz,rw,b,n) | ||
293 | #define VOP_OPEN(vp, cr, rv) \ | ||
294 | rv = _VOP_(vop_open, vp)((vp)->v_fbhv, cr) | ||
295 | #define VOP_GETATTR(vp, vap, f, cr, rv) \ | ||
296 | rv = _VOP_(vop_getattr, vp)((vp)->v_fbhv, vap, f, cr) | ||
297 | #define VOP_SETATTR(vp, vap, f, cr, rv) \ | ||
298 | rv = _VOP_(vop_setattr, vp)((vp)->v_fbhv, vap, f, cr) | ||
299 | #define VOP_ACCESS(vp, mode, cr, rv) \ | ||
300 | rv = _VOP_(vop_access, vp)((vp)->v_fbhv, mode, cr) | ||
301 | #define VOP_LOOKUP(vp,d,vpp,f,rdir,cr,rv) \ | ||
302 | rv = _VOP_(vop_lookup, vp)((vp)->v_fbhv,d,vpp,f,rdir,cr) | ||
303 | #define VOP_CREATE(dvp,d,vap,vpp,cr,rv) \ | ||
304 | rv = _VOP_(vop_create, dvp)((dvp)->v_fbhv,d,vap,vpp,cr) | ||
305 | #define VOP_REMOVE(dvp,d,cr,rv) \ | ||
306 | rv = _VOP_(vop_remove, dvp)((dvp)->v_fbhv,d,cr) | ||
307 | #define VOP_LINK(tdvp,fvp,d,cr,rv) \ | ||
308 | rv = _VOP_(vop_link, tdvp)((tdvp)->v_fbhv,fvp,d,cr) | ||
309 | #define VOP_RENAME(fvp,fnm,tdvp,tnm,cr,rv) \ | ||
310 | rv = _VOP_(vop_rename, fvp)((fvp)->v_fbhv,fnm,tdvp,tnm,cr) | ||
311 | #define VOP_MKDIR(dp,d,vap,vpp,cr,rv) \ | ||
312 | rv = _VOP_(vop_mkdir, dp)((dp)->v_fbhv,d,vap,vpp,cr) | ||
313 | #define VOP_RMDIR(dp,d,cr,rv) \ | ||
314 | rv = _VOP_(vop_rmdir, dp)((dp)->v_fbhv,d,cr) | ||
315 | #define VOP_READDIR(vp,uiop,cr,eofp,rv) \ | ||
316 | rv = _VOP_(vop_readdir, vp)((vp)->v_fbhv,uiop,cr,eofp) | ||
317 | #define VOP_SYMLINK(dvp,d,vap,tnm,vpp,cr,rv) \ | ||
318 | rv = _VOP_(vop_symlink, dvp) ((dvp)->v_fbhv,d,vap,tnm,vpp,cr) | ||
319 | #define VOP_READLINK(vp,uiop,fl,cr,rv) \ | ||
320 | rv = _VOP_(vop_readlink, vp)((vp)->v_fbhv,uiop,fl,cr) | ||
321 | #define VOP_FSYNC(vp,f,cr,b,e,rv) \ | ||
322 | rv = _VOP_(vop_fsync, vp)((vp)->v_fbhv,f,cr,b,e) | ||
323 | #define VOP_INACTIVE(vp, cr, rv) \ | ||
324 | rv = _VOP_(vop_inactive, vp)((vp)->v_fbhv, cr) | ||
325 | #define VOP_RELEASE(vp, rv) \ | ||
326 | rv = _VOP_(vop_release, vp)((vp)->v_fbhv) | ||
327 | #define VOP_FID2(vp, fidp, rv) \ | ||
328 | rv = _VOP_(vop_fid2, vp)((vp)->v_fbhv, fidp) | ||
329 | #define VOP_RWLOCK(vp,i) \ | ||
330 | (void)_VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) | ||
331 | #define VOP_RWLOCK_TRY(vp,i) \ | ||
332 | _VOP_(vop_rwlock, vp)((vp)->v_fbhv, i) | ||
333 | #define VOP_RWUNLOCK(vp,i) \ | ||
334 | (void)_VOP_(vop_rwunlock, vp)((vp)->v_fbhv, i) | ||
335 | #define VOP_FRLOCK(vp,c,fl,flags,offset,fr,rv) \ | ||
336 | rv = _VOP_(vop_frlock, vp)((vp)->v_fbhv,c,fl,flags,offset,fr) | ||
337 | #define VOP_RECLAIM(vp, rv) \ | ||
338 | rv = _VOP_(vop_reclaim, vp)((vp)->v_fbhv) | ||
339 | #define VOP_ATTR_GET(vp, name, val, vallenp, fl, cred, rv) \ | ||
340 | rv = _VOP_(vop_attr_get, vp)((vp)->v_fbhv,name,val,vallenp,fl,cred) | ||
341 | #define VOP_ATTR_SET(vp, name, val, vallen, fl, cred, rv) \ | ||
342 | rv = _VOP_(vop_attr_set, vp)((vp)->v_fbhv,name,val,vallen,fl,cred) | ||
343 | #define VOP_ATTR_REMOVE(vp, name, flags, cred, rv) \ | ||
344 | rv = _VOP_(vop_attr_remove, vp)((vp)->v_fbhv,name,flags,cred) | ||
345 | #define VOP_ATTR_LIST(vp, buf, buflen, fl, cursor, cred, rv) \ | ||
346 | rv = _VOP_(vop_attr_list, vp)((vp)->v_fbhv,buf,buflen,fl,cursor,cred) | ||
347 | #define VOP_LINK_REMOVED(vp, dvp, linkzero) \ | ||
348 | (void)_VOP_(vop_link_removed, vp)((vp)->v_fbhv, dvp, linkzero) | ||
349 | #define VOP_VNODE_CHANGE(vp, cmd, val) \ | ||
350 | (void)_VOP_(vop_vnode_change, vp)((vp)->v_fbhv,cmd,val) | ||
351 | /* | ||
352 | * These are page cache functions that now go thru VOPs. | ||
353 | * 'last' parameter is unused and left in for IRIX compatibility | ||
354 | */ | 250 | */ |
355 | #define VOP_TOSS_PAGES(vp, first, last, fiopt) \ | 251 | #define VNHEAD(vp) ((vp)->v_bh.bh_first) |
356 | _VOP_(vop_tosspages, vp)((vp)->v_fbhv,first, last, fiopt) | 252 | #define VOP(op, vp) (*((bhv_vnodeops_t *)VNHEAD(vp)->bd_ops)->op) |
357 | /* | 253 | #define bhv_vop_open(vp, cr) VOP(vop_open, vp)(VNHEAD(vp),cr) |
358 | * 'last' parameter is unused and left in for IRIX compatibility | 254 | #define bhv_vop_close(vp, f,last,cr) VOP(vop_close, vp)(VNHEAD(vp),f,last,cr) |
359 | */ | 255 | #define bhv_vop_read(vp,file,iov,segs,offset,ioflags,cr) \ |
360 | #define VOP_FLUSHINVAL_PAGES(vp, first, last, fiopt) \ | 256 | VOP(vop_read, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) |
361 | _VOP_(vop_flushinval_pages, vp)((vp)->v_fbhv,first,last,fiopt) | 257 | #define bhv_vop_write(vp,file,iov,segs,offset,ioflags,cr) \ |
362 | /* | 258 | VOP(vop_write, vp)(VNHEAD(vp),file,iov,segs,offset,ioflags,cr) |
363 | * 'last' parameter is unused and left in for IRIX compatibility | 259 | #define bhv_vop_sendfile(vp,f,off,ioflags,cnt,act,targ,cr) \ |
364 | */ | 260 | VOP(vop_sendfile, vp)(VNHEAD(vp),f,off,ioflags,cnt,act,targ,cr) |
365 | #define VOP_FLUSH_PAGES(vp, first, last, flags, fiopt, rv) \ | 261 | #define bhv_vop_splice_read(vp,f,o,pipe,cnt,fl,iofl,cr) \ |
366 | rv = _VOP_(vop_flush_pages, vp)((vp)->v_fbhv,first,last,flags,fiopt) | 262 | VOP(vop_splice_read, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) |
367 | #define VOP_IOCTL(vp, inode, filp, fl, cmd, arg, rv) \ | 263 | #define bhv_vop_splice_write(vp,f,o,pipe,cnt,fl,iofl,cr) \ |
368 | rv = _VOP_(vop_ioctl, vp)((vp)->v_fbhv,inode,filp,fl,cmd,arg) | 264 | VOP(vop_splice_write, vp)(VNHEAD(vp),f,o,pipe,cnt,fl,iofl,cr) |
369 | #define VOP_IFLUSH(vp, flags, rv) \ | 265 | #define bhv_vop_bmap(vp,of,sz,rw,b,n) \ |
370 | rv = _VOP_(vop_iflush, vp)((vp)->v_fbhv, flags) | 266 | VOP(vop_bmap, vp)(VNHEAD(vp),of,sz,rw,b,n) |
267 | #define bhv_vop_getattr(vp, vap,f,cr) \ | ||
268 | VOP(vop_getattr, vp)(VNHEAD(vp), vap,f,cr) | ||
269 | #define bhv_vop_setattr(vp, vap,f,cr) \ | ||
270 | VOP(vop_setattr, vp)(VNHEAD(vp), vap,f,cr) | ||
271 | #define bhv_vop_access(vp, mode,cr) VOP(vop_access, vp)(VNHEAD(vp), mode,cr) | ||
272 | #define bhv_vop_lookup(vp,d,vpp,f,rdir,cr) \ | ||
273 | VOP(vop_lookup, vp)(VNHEAD(vp),d,vpp,f,rdir,cr) | ||
274 | #define bhv_vop_create(dvp,d,vap,vpp,cr) \ | ||
275 | VOP(vop_create, dvp)(VNHEAD(dvp),d,vap,vpp,cr) | ||
276 | #define bhv_vop_remove(dvp,d,cr) VOP(vop_remove, dvp)(VNHEAD(dvp),d,cr) | ||
277 | #define bhv_vop_link(dvp,fvp,d,cr) VOP(vop_link, dvp)(VNHEAD(dvp),fvp,d,cr) | ||
278 | #define bhv_vop_rename(fvp,fnm,tdvp,tnm,cr) \ | ||
279 | VOP(vop_rename, fvp)(VNHEAD(fvp),fnm,tdvp,tnm,cr) | ||
280 | #define bhv_vop_mkdir(dp,d,vap,vpp,cr) \ | ||
281 | VOP(vop_mkdir, dp)(VNHEAD(dp),d,vap,vpp,cr) | ||
282 | #define bhv_vop_rmdir(dp,d,cr) VOP(vop_rmdir, dp)(VNHEAD(dp),d,cr) | ||
283 | #define bhv_vop_readdir(vp,uiop,cr,eofp) \ | ||
284 | VOP(vop_readdir, vp)(VNHEAD(vp),uiop,cr,eofp) | ||
285 | #define bhv_vop_symlink(dvp,d,vap,tnm,vpp,cr) \ | ||
286 | VOP(vop_symlink, dvp)(VNHEAD(dvp),d,vap,tnm,vpp,cr) | ||
287 | #define bhv_vop_readlink(vp,uiop,fl,cr) \ | ||
288 | VOP(vop_readlink, vp)(VNHEAD(vp),uiop,fl,cr) | ||
289 | #define bhv_vop_fsync(vp,f,cr,b,e) VOP(vop_fsync, vp)(VNHEAD(vp),f,cr,b,e) | ||
290 | #define bhv_vop_inactive(vp,cr) VOP(vop_inactive, vp)(VNHEAD(vp),cr) | ||
291 | #define bhv_vop_release(vp) VOP(vop_release, vp)(VNHEAD(vp)) | ||
292 | #define bhv_vop_fid2(vp,fidp) VOP(vop_fid2, vp)(VNHEAD(vp),fidp) | ||
293 | #define bhv_vop_rwlock(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i) | ||
294 | #define bhv_vop_rwlock_try(vp,i) VOP(vop_rwlock, vp)(VNHEAD(vp),i) | ||
295 | #define bhv_vop_rwunlock(vp,i) VOP(vop_rwunlock, vp)(VNHEAD(vp),i) | ||
296 | #define bhv_vop_frlock(vp,c,fl,flags,offset,fr) \ | ||
297 | VOP(vop_frlock, vp)(VNHEAD(vp),c,fl,flags,offset,fr) | ||
298 | #define bhv_vop_reclaim(vp) VOP(vop_reclaim, vp)(VNHEAD(vp)) | ||
299 | #define bhv_vop_attr_get(vp, name, val, vallenp, fl, cred) \ | ||
300 | VOP(vop_attr_get, vp)(VNHEAD(vp),name,val,vallenp,fl,cred) | ||
301 | #define bhv_vop_attr_set(vp, name, val, vallen, fl, cred) \ | ||
302 | VOP(vop_attr_set, vp)(VNHEAD(vp),name,val,vallen,fl,cred) | ||
303 | #define bhv_vop_attr_remove(vp, name, flags, cred) \ | ||
304 | VOP(vop_attr_remove, vp)(VNHEAD(vp),name,flags,cred) | ||
305 | #define bhv_vop_attr_list(vp, buf, buflen, fl, cursor, cred) \ | ||
306 | VOP(vop_attr_list, vp)(VNHEAD(vp),buf,buflen,fl,cursor,cred) | ||
307 | #define bhv_vop_link_removed(vp, dvp, linkzero) \ | ||
308 | VOP(vop_link_removed, vp)(VNHEAD(vp), dvp, linkzero) | ||
309 | #define bhv_vop_vnode_change(vp, cmd, val) \ | ||
310 | VOP(vop_vnode_change, vp)(VNHEAD(vp), cmd, val) | ||
311 | #define bhv_vop_toss_pages(vp, first, last, fiopt) \ | ||
312 | VOP(vop_tosspages, vp)(VNHEAD(vp), first, last, fiopt) | ||
313 | #define bhv_vop_flushinval_pages(vp, first, last, fiopt) \ | ||
314 | VOP(vop_flushinval_pages, vp)(VNHEAD(vp),first,last,fiopt) | ||
315 | #define bhv_vop_flush_pages(vp, first, last, flags, fiopt) \ | ||
316 | VOP(vop_flush_pages, vp)(VNHEAD(vp),first,last,flags,fiopt) | ||
317 | #define bhv_vop_ioctl(vp, inode, filp, fl, cmd, arg) \ | ||
318 | VOP(vop_ioctl, vp)(VNHEAD(vp),inode,filp,fl,cmd,arg) | ||
319 | #define bhv_vop_iflush(vp, flags) VOP(vop_iflush, vp)(VNHEAD(vp), flags) | ||
371 | 320 | ||
372 | /* | 321 | /* |
373 | * Flags for read/write calls - same values as IRIX | 322 | * Flags for read/write calls - same values as IRIX |
@@ -377,7 +326,7 @@ typedef struct vnodeops { | |||
377 | #define IO_INVIS 0x00020 /* don't update inode timestamps */ | 326 | #define IO_INVIS 0x00020 /* don't update inode timestamps */ |
378 | 327 | ||
379 | /* | 328 | /* |
380 | * Flags for VOP_IFLUSH call | 329 | * Flags for vop_iflush call |
381 | */ | 330 | */ |
382 | #define FLUSH_SYNC 1 /* wait for flush to complete */ | 331 | #define FLUSH_SYNC 1 /* wait for flush to complete */ |
383 | #define FLUSH_INODE 2 /* flush the inode itself */ | 332 | #define FLUSH_INODE 2 /* flush the inode itself */ |
@@ -385,8 +334,7 @@ typedef struct vnodeops { | |||
385 | * this inode out to disk */ | 334 | * this inode out to disk */ |
386 | 335 | ||
387 | /* | 336 | /* |
388 | * Flush/Invalidate options for VOP_TOSS_PAGES, VOP_FLUSHINVAL_PAGES and | 337 | * Flush/Invalidate options for vop_toss/flush/flushinval_pages. |
389 | * VOP_FLUSH_PAGES. | ||
390 | */ | 338 | */ |
391 | #define FI_NONE 0 /* none */ | 339 | #define FI_NONE 0 /* none */ |
392 | #define FI_REMAPF 1 /* Do a remapf prior to the operation */ | 340 | #define FI_REMAPF 1 /* Do a remapf prior to the operation */ |
@@ -398,7 +346,7 @@ typedef struct vnodeops { | |||
398 | * Vnode attributes. va_mask indicates those attributes the caller | 346 | * Vnode attributes. va_mask indicates those attributes the caller |
399 | * wants to set or extract. | 347 | * wants to set or extract. |
400 | */ | 348 | */ |
401 | typedef struct vattr { | 349 | typedef struct bhv_vattr { |
402 | int va_mask; /* bit-mask of attributes present */ | 350 | int va_mask; /* bit-mask of attributes present */ |
403 | mode_t va_mode; /* file access mode and type */ | 351 | mode_t va_mode; /* file access mode and type */ |
404 | xfs_nlink_t va_nlink; /* number of references to file */ | 352 | xfs_nlink_t va_nlink; /* number of references to file */ |
@@ -418,7 +366,7 @@ typedef struct vattr { | |||
418 | u_long va_nextents; /* number of extents in file */ | 366 | u_long va_nextents; /* number of extents in file */ |
419 | u_long va_anextents; /* number of attr extents in file */ | 367 | u_long va_anextents; /* number of attr extents in file */ |
420 | prid_t va_projid; /* project id */ | 368 | prid_t va_projid; /* project id */ |
421 | } vattr_t; | 369 | } bhv_vattr_t; |
422 | 370 | ||
423 | /* | 371 | /* |
424 | * setattr or getattr attributes | 372 | * setattr or getattr attributes |
@@ -492,29 +440,17 @@ typedef struct vattr { | |||
492 | (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) | 440 | (VN_ISREG(vp) && ((mode) & (VSGID|(VEXEC>>3))) == VSGID) |
493 | 441 | ||
494 | extern void vn_init(void); | 442 | extern void vn_init(void); |
495 | extern vnode_t *vn_initialize(struct inode *); | 443 | extern bhv_vnode_t *vn_initialize(struct inode *); |
496 | 444 | extern int vn_revalidate(struct bhv_vnode *); | |
497 | /* | 445 | extern int __vn_revalidate(struct bhv_vnode *, bhv_vattr_t *); |
498 | * vnode_map structures _must_ match vn_epoch and vnode structure sizes. | 446 | extern void vn_revalidate_core(struct bhv_vnode *, bhv_vattr_t *); |
499 | */ | ||
500 | typedef struct vnode_map { | ||
501 | vfs_t *v_vfsp; | ||
502 | vnumber_t v_number; /* in-core vnode number */ | ||
503 | xfs_ino_t v_ino; /* inode # */ | ||
504 | } vmap_t; | ||
505 | |||
506 | #define VMAP(vp, vmap) {(vmap).v_vfsp = (vp)->v_vfsp, \ | ||
507 | (vmap).v_number = (vp)->v_number, \ | ||
508 | (vmap).v_ino = (vp)->v_inode.i_ino; } | ||
509 | 447 | ||
510 | extern int vn_revalidate(struct vnode *); | 448 | extern void vn_iowait(struct bhv_vnode *vp); |
511 | extern int __vn_revalidate(struct vnode *, vattr_t *); | 449 | extern void vn_iowake(struct bhv_vnode *vp); |
512 | extern void vn_revalidate_core(struct vnode *, vattr_t *); | ||
513 | 450 | ||
514 | extern void vn_iowait(struct vnode *vp); | 451 | extern void vn_ioerror(struct bhv_vnode *vp, int error, char *f, int l); |
515 | extern void vn_iowake(struct vnode *vp); | ||
516 | 452 | ||
517 | static inline int vn_count(struct vnode *vp) | 453 | static inline int vn_count(struct bhv_vnode *vp) |
518 | { | 454 | { |
519 | return atomic_read(&vn_to_inode(vp)->i_count); | 455 | return atomic_read(&vn_to_inode(vp)->i_count); |
520 | } | 456 | } |
@@ -522,7 +458,7 @@ static inline int vn_count(struct vnode *vp) | |||
522 | /* | 458 | /* |
523 | * Vnode reference counting functions (and macros for compatibility). | 459 | * Vnode reference counting functions (and macros for compatibility). |
524 | */ | 460 | */ |
525 | extern vnode_t *vn_hold(struct vnode *); | 461 | extern bhv_vnode_t *vn_hold(struct bhv_vnode *); |
526 | 462 | ||
527 | #if defined(XFS_VNODE_TRACE) | 463 | #if defined(XFS_VNODE_TRACE) |
528 | #define VN_HOLD(vp) \ | 464 | #define VN_HOLD(vp) \ |
@@ -536,7 +472,7 @@ extern vnode_t *vn_hold(struct vnode *); | |||
536 | #define VN_RELE(vp) (iput(vn_to_inode(vp))) | 472 | #define VN_RELE(vp) (iput(vn_to_inode(vp))) |
537 | #endif | 473 | #endif |
538 | 474 | ||
539 | static inline struct vnode *vn_grab(struct vnode *vp) | 475 | static inline struct bhv_vnode *vn_grab(struct bhv_vnode *vp) |
540 | { | 476 | { |
541 | struct inode *inode = igrab(vn_to_inode(vp)); | 477 | struct inode *inode = igrab(vn_to_inode(vp)); |
542 | return inode ? vn_from_inode(inode) : NULL; | 478 | return inode ? vn_from_inode(inode) : NULL; |
@@ -554,32 +490,39 @@ static inline struct vnode *vn_grab(struct vnode *vp) | |||
554 | */ | 490 | */ |
555 | #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) | 491 | #define VN_LOCK(vp) mutex_spinlock(&(vp)->v_lock) |
556 | #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) | 492 | #define VN_UNLOCK(vp, s) mutex_spinunlock(&(vp)->v_lock, s) |
557 | #define VN_FLAGSET(vp,b) vn_flagset(vp,b) | ||
558 | #define VN_FLAGCLR(vp,b) vn_flagclr(vp,b) | ||
559 | 493 | ||
560 | static __inline__ void vn_flagset(struct vnode *vp, uint flag) | 494 | static __inline__ void vn_flagset(struct bhv_vnode *vp, uint flag) |
561 | { | 495 | { |
562 | spin_lock(&vp->v_lock); | 496 | spin_lock(&vp->v_lock); |
563 | vp->v_flag |= flag; | 497 | vp->v_flag |= flag; |
564 | spin_unlock(&vp->v_lock); | 498 | spin_unlock(&vp->v_lock); |
565 | } | 499 | } |
566 | 500 | ||
567 | static __inline__ void vn_flagclr(struct vnode *vp, uint flag) | 501 | static __inline__ uint vn_flagclr(struct bhv_vnode *vp, uint flag) |
568 | { | 502 | { |
503 | uint cleared; | ||
504 | |||
569 | spin_lock(&vp->v_lock); | 505 | spin_lock(&vp->v_lock); |
506 | cleared = (vp->v_flag & flag); | ||
570 | vp->v_flag &= ~flag; | 507 | vp->v_flag &= ~flag; |
571 | spin_unlock(&vp->v_lock); | 508 | spin_unlock(&vp->v_lock); |
509 | return cleared; | ||
572 | } | 510 | } |
573 | 511 | ||
512 | #define VMODIFY(vp) vn_flagset(vp, VMODIFIED) | ||
513 | #define VUNMODIFY(vp) vn_flagclr(vp, VMODIFIED) | ||
514 | #define VTRUNCATE(vp) vn_flagset(vp, VTRUNCATED) | ||
515 | #define VUNTRUNCATE(vp) vn_flagclr(vp, VTRUNCATED) | ||
516 | |||
574 | /* | 517 | /* |
575 | * Dealing with bad inodes | 518 | * Dealing with bad inodes |
576 | */ | 519 | */ |
577 | static inline void vn_mark_bad(struct vnode *vp) | 520 | static inline void vn_mark_bad(struct bhv_vnode *vp) |
578 | { | 521 | { |
579 | make_bad_inode(vn_to_inode(vp)); | 522 | make_bad_inode(vn_to_inode(vp)); |
580 | } | 523 | } |
581 | 524 | ||
582 | static inline int VN_BAD(struct vnode *vp) | 525 | static inline int VN_BAD(struct bhv_vnode *vp) |
583 | { | 526 | { |
584 | return is_bad_inode(vn_to_inode(vp)); | 527 | return is_bad_inode(vn_to_inode(vp)); |
585 | } | 528 | } |
@@ -587,18 +530,18 @@ static inline int VN_BAD(struct vnode *vp) | |||
587 | /* | 530 | /* |
588 | * Extracting atime values in various formats | 531 | * Extracting atime values in various formats |
589 | */ | 532 | */ |
590 | static inline void vn_atime_to_bstime(struct vnode *vp, xfs_bstime_t *bs_atime) | 533 | static inline void vn_atime_to_bstime(bhv_vnode_t *vp, xfs_bstime_t *bs_atime) |
591 | { | 534 | { |
592 | bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec; | 535 | bs_atime->tv_sec = vp->v_inode.i_atime.tv_sec; |
593 | bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec; | 536 | bs_atime->tv_nsec = vp->v_inode.i_atime.tv_nsec; |
594 | } | 537 | } |
595 | 538 | ||
596 | static inline void vn_atime_to_timespec(struct vnode *vp, struct timespec *ts) | 539 | static inline void vn_atime_to_timespec(bhv_vnode_t *vp, struct timespec *ts) |
597 | { | 540 | { |
598 | *ts = vp->v_inode.i_atime; | 541 | *ts = vp->v_inode.i_atime; |
599 | } | 542 | } |
600 | 543 | ||
601 | static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) | 544 | static inline void vn_atime_to_time_t(bhv_vnode_t *vp, time_t *tt) |
602 | { | 545 | { |
603 | *tt = vp->v_inode.i_atime.tv_sec; | 546 | *tt = vp->v_inode.i_atime.tv_sec; |
604 | } | 547 | } |
@@ -610,11 +553,10 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) | |||
610 | #define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) | 553 | #define VN_CACHED(vp) (vn_to_inode(vp)->i_mapping->nrpages) |
611 | #define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ | 554 | #define VN_DIRTY(vp) mapping_tagged(vn_to_inode(vp)->i_mapping, \ |
612 | PAGECACHE_TAG_DIRTY) | 555 | PAGECACHE_TAG_DIRTY) |
613 | #define VMODIFY(vp) VN_FLAGSET(vp, VMODIFIED) | 556 | #define VN_TRUNC(vp) ((vp)->v_flag & VTRUNCATED) |
614 | #define VUNMODIFY(vp) VN_FLAGCLR(vp, VMODIFIED) | ||
615 | 557 | ||
616 | /* | 558 | /* |
617 | * Flags to VOP_SETATTR/VOP_GETATTR. | 559 | * Flags to vop_setattr/getattr. |
618 | */ | 560 | */ |
619 | #define ATTR_UTIME 0x01 /* non-default utime(2) request */ | 561 | #define ATTR_UTIME 0x01 /* non-default utime(2) request */ |
620 | #define ATTR_DMI 0x08 /* invocation from a DMI function */ | 562 | #define ATTR_DMI 0x08 /* invocation from a DMI function */ |
@@ -624,7 +566,7 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) | |||
624 | #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ | 566 | #define ATTR_NOSIZETOK 0x400 /* Don't get the SIZE token */ |
625 | 567 | ||
626 | /* | 568 | /* |
627 | * Flags to VOP_FSYNC and VOP_RECLAIM. | 569 | * Flags to vop_fsync/reclaim. |
628 | */ | 570 | */ |
629 | #define FSYNC_NOWAIT 0 /* asynchronous flush */ | 571 | #define FSYNC_NOWAIT 0 /* asynchronous flush */ |
630 | #define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ | 572 | #define FSYNC_WAIT 0x1 /* synchronous fsync or forced reclaim */ |
@@ -643,11 +585,11 @@ static inline void vn_atime_to_time_t(struct vnode *vp, time_t *tt) | |||
643 | #define VNODE_KTRACE_REF 4 | 585 | #define VNODE_KTRACE_REF 4 |
644 | #define VNODE_KTRACE_RELE 5 | 586 | #define VNODE_KTRACE_RELE 5 |
645 | 587 | ||
646 | extern void vn_trace_entry(struct vnode *, const char *, inst_t *); | 588 | extern void vn_trace_entry(struct bhv_vnode *, const char *, inst_t *); |
647 | extern void vn_trace_exit(struct vnode *, const char *, inst_t *); | 589 | extern void vn_trace_exit(struct bhv_vnode *, const char *, inst_t *); |
648 | extern void vn_trace_hold(struct vnode *, char *, int, inst_t *); | 590 | extern void vn_trace_hold(struct bhv_vnode *, char *, int, inst_t *); |
649 | extern void vn_trace_ref(struct vnode *, char *, int, inst_t *); | 591 | extern void vn_trace_ref(struct bhv_vnode *, char *, int, inst_t *); |
650 | extern void vn_trace_rele(struct vnode *, char *, int, inst_t *); | 592 | extern void vn_trace_rele(struct bhv_vnode *, char *, int, inst_t *); |
651 | 593 | ||
652 | #define VN_TRACE(vp) \ | 594 | #define VN_TRACE(vp) \ |
653 | vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address) | 595 | vn_trace_ref(vp, __FILE__, __LINE__, (inst_t *)__return_address) |
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 772ac48329ea..3aa771531856 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -444,7 +442,7 @@ xfs_qm_dqalloc( | |||
444 | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, | 442 | XFS_BMAPI_METADATA | XFS_BMAPI_WRITE, |
445 | &firstblock, | 443 | &firstblock, |
446 | XFS_QM_DQALLOC_SPACE_RES(mp), | 444 | XFS_QM_DQALLOC_SPACE_RES(mp), |
447 | &map, &nmaps, &flist))) { | 445 | &map, &nmaps, &flist, NULL))) { |
448 | goto error0; | 446 | goto error0; |
449 | } | 447 | } |
450 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); | 448 | ASSERT(map.br_blockcount == XFS_DQUOT_CLUSTER_SIZE_FSB); |
@@ -559,7 +557,7 @@ xfs_qm_dqtobp( | |||
559 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, | 557 | error = xfs_bmapi(NULL, quotip, dqp->q_fileoffset, |
560 | XFS_DQUOT_CLUSTER_SIZE_FSB, | 558 | XFS_DQUOT_CLUSTER_SIZE_FSB, |
561 | XFS_BMAPI_METADATA, | 559 | XFS_BMAPI_METADATA, |
562 | NULL, 0, &map, &nmaps, NULL); | 560 | NULL, 0, &map, &nmaps, NULL, NULL); |
563 | 561 | ||
564 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); | 562 | xfs_iunlock(quotip, XFS_ILOCK_SHARED); |
565 | if (error) | 563 | if (error) |
@@ -1261,7 +1259,7 @@ xfs_qm_dqflush( | |||
1261 | 1259 | ||
1262 | if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), | 1260 | if (xfs_qm_dqcheck(&dqp->q_core, be32_to_cpu(ddqp->d_id), |
1263 | 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { | 1261 | 0, XFS_QMOPT_DOWARN, "dqflush (incore copy)")) { |
1264 | xfs_force_shutdown(dqp->q_mount, XFS_CORRUPT_INCORE); | 1262 | xfs_force_shutdown(dqp->q_mount, SHUTDOWN_CORRUPT_INCORE); |
1265 | return XFS_ERROR(EIO); | 1263 | return XFS_ERROR(EIO); |
1266 | } | 1264 | } |
1267 | 1265 | ||
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index c0c629663a5c..78d3ab95c5fd 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h | |||
@@ -119,7 +119,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) | |||
119 | */ | 119 | */ |
120 | #define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ | 120 | #define xfs_dqflock(dqp) { psema(&((dqp)->q_flock), PINOD | PRECALC);\ |
121 | (dqp)->dq_flags |= XFS_DQ_FLOCKED; } | 121 | (dqp)->dq_flags |= XFS_DQ_FLOCKED; } |
122 | #define xfs_dqfunlock(dqp) { ASSERT(valusema(&((dqp)->q_flock)) <= 0); \ | 122 | #define xfs_dqfunlock(dqp) { ASSERT(issemalocked(&((dqp)->q_flock))); \ |
123 | vsema(&((dqp)->q_flock)); \ | 123 | vsema(&((dqp)->q_flock)); \ |
124 | (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } | 124 | (dqp)->dq_flags &= ~(XFS_DQ_FLOCKED); } |
125 | 125 | ||
@@ -128,7 +128,7 @@ XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) | |||
128 | #define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \ | 128 | #define XFS_DQ_PINUNLOCK(dqp, s) mutex_spinunlock( \ |
129 | &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s) | 129 | &(XFS_DQ_TO_QINF(dqp)->qi_pinlock), s) |
130 | 130 | ||
131 | #define XFS_DQ_IS_FLUSH_LOCKED(dqp) (valusema(&((dqp)->q_flock)) <= 0) | 131 | #define XFS_DQ_IS_FLUSH_LOCKED(dqp) (issemalocked(&((dqp)->q_flock))) |
132 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) | 132 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) |
133 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) | 133 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) |
134 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) | 134 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) |
diff --git a/fs/xfs/quota/xfs_dquot_item.c b/fs/xfs/quota/xfs_dquot_item.c index 546f48af882a..5b2dcc58b244 100644 --- a/fs/xfs/quota/xfs_dquot_item.c +++ b/fs/xfs/quota/xfs_dquot_item.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -248,7 +246,7 @@ xfs_qm_dquot_logitem_pushbuf( | |||
248 | * inode flush completed and the inode was taken off the AIL. | 246 | * inode flush completed and the inode was taken off the AIL. |
249 | * So, just get out. | 247 | * So, just get out. |
250 | */ | 248 | */ |
251 | if ((valusema(&(dqp->q_flock)) > 0) || | 249 | if (!issemalocked(&(dqp->q_flock)) || |
252 | ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 250 | ((qip->qli_item.li_flags & XFS_LI_IN_AIL) == 0)) { |
253 | qip->qli_pushbuf_flag = 0; | 251 | qip->qli_pushbuf_flag = 0; |
254 | xfs_dqunlock(dqp); | 252 | xfs_dqunlock(dqp); |
@@ -261,7 +259,7 @@ xfs_qm_dquot_logitem_pushbuf( | |||
261 | if (bp != NULL) { | 259 | if (bp != NULL) { |
262 | if (XFS_BUF_ISDELAYWRITE(bp)) { | 260 | if (XFS_BUF_ISDELAYWRITE(bp)) { |
263 | dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && | 261 | dopush = ((qip->qli_item.li_flags & XFS_LI_IN_AIL) && |
264 | (valusema(&(dqp->q_flock)) <= 0)); | 262 | issemalocked(&(dqp->q_flock))); |
265 | qip->qli_pushbuf_flag = 0; | 263 | qip->qli_pushbuf_flag = 0; |
266 | xfs_dqunlock(dqp); | 264 | xfs_dqunlock(dqp); |
267 | 265 | ||
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7fb5eca9bd50..e23e45535c48 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_alloc.h" | 28 | #include "xfs_alloc.h" |
30 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
@@ -33,7 +32,6 @@ | |||
33 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
39 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
@@ -1603,7 +1601,7 @@ xfs_qm_dqiterate( | |||
1603 | maxlblkcnt - lblkno, | 1601 | maxlblkcnt - lblkno, |
1604 | XFS_BMAPI_METADATA, | 1602 | XFS_BMAPI_METADATA, |
1605 | NULL, | 1603 | NULL, |
1606 | 0, map, &nmaps, NULL); | 1604 | 0, map, &nmaps, NULL, NULL); |
1607 | xfs_iunlock(qip, XFS_ILOCK_SHARED); | 1605 | xfs_iunlock(qip, XFS_ILOCK_SHARED); |
1608 | if (error) | 1606 | if (error) |
1609 | break; | 1607 | break; |
@@ -1905,9 +1903,7 @@ xfs_qm_quotacheck( | |||
1905 | */ | 1903 | */ |
1906 | if ((error = xfs_bulkstat(mp, &lastino, &count, | 1904 | if ((error = xfs_bulkstat(mp, &lastino, &count, |
1907 | xfs_qm_dqusage_adjust, NULL, | 1905 | xfs_qm_dqusage_adjust, NULL, |
1908 | structsz, NULL, | 1906 | structsz, NULL, BULKSTAT_FG_IGET, &done))) |
1909 | BULKSTAT_FG_IGET|BULKSTAT_FG_VFSLOCKED, | ||
1910 | &done))) | ||
1911 | break; | 1907 | break; |
1912 | 1908 | ||
1913 | } while (! done); | 1909 | } while (! done); |
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index 6838b36d95a9..e95e99f7168f 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_alloc.h" | 28 | #include "xfs_alloc.h" |
30 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
@@ -33,7 +32,6 @@ | |||
33 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
39 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
@@ -129,7 +127,7 @@ xfs_qm_parseargs( | |||
129 | return XFS_ERROR(EINVAL); | 127 | return XFS_ERROR(EINVAL); |
130 | } | 128 | } |
131 | 129 | ||
132 | PVFS_PARSEARGS(BHV_NEXT(bhv), options, args, update, error); | 130 | error = bhv_next_vfs_parseargs(BHV_NEXT(bhv), options, args, update); |
133 | if (!error && !referenced) | 131 | if (!error && !referenced) |
134 | bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); | 132 | bhv_remove_vfsops(bhvtovfs(bhv), VFS_POSITION_QM); |
135 | return error; | 133 | return error; |
@@ -140,9 +138,8 @@ xfs_qm_showargs( | |||
140 | struct bhv_desc *bhv, | 138 | struct bhv_desc *bhv, |
141 | struct seq_file *m) | 139 | struct seq_file *m) |
142 | { | 140 | { |
143 | struct vfs *vfsp = bhvtovfs(bhv); | 141 | struct bhv_vfs *vfsp = bhvtovfs(bhv); |
144 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); | 142 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); |
145 | int error; | ||
146 | 143 | ||
147 | if (mp->m_qflags & XFS_UQUOTA_ACCT) { | 144 | if (mp->m_qflags & XFS_UQUOTA_ACCT) { |
148 | (mp->m_qflags & XFS_UQUOTA_ENFD) ? | 145 | (mp->m_qflags & XFS_UQUOTA_ENFD) ? |
@@ -165,8 +162,7 @@ xfs_qm_showargs( | |||
165 | if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) | 162 | if (!(mp->m_qflags & XFS_ALL_QUOTA_ACCT)) |
166 | seq_puts(m, "," MNTOPT_NOQUOTA); | 163 | seq_puts(m, "," MNTOPT_NOQUOTA); |
167 | 164 | ||
168 | PVFS_SHOWARGS(BHV_NEXT(bhv), m, error); | 165 | return bhv_next_vfs_showargs(BHV_NEXT(bhv), m); |
169 | return error; | ||
170 | } | 166 | } |
171 | 167 | ||
172 | STATIC int | 168 | STATIC int |
@@ -175,14 +171,67 @@ xfs_qm_mount( | |||
175 | struct xfs_mount_args *args, | 171 | struct xfs_mount_args *args, |
176 | struct cred *cr) | 172 | struct cred *cr) |
177 | { | 173 | { |
178 | struct vfs *vfsp = bhvtovfs(bhv); | 174 | struct bhv_vfs *vfsp = bhvtovfs(bhv); |
179 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); | 175 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); |
180 | int error; | ||
181 | 176 | ||
182 | if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA)) | 177 | if (args->flags & (XFSMNT_UQUOTA | XFSMNT_GQUOTA | XFSMNT_PQUOTA)) |
183 | xfs_qm_mount_quotainit(mp, args->flags); | 178 | xfs_qm_mount_quotainit(mp, args->flags); |
184 | PVFS_MOUNT(BHV_NEXT(bhv), args, cr, error); | 179 | return bhv_next_vfs_mount(BHV_NEXT(bhv), args, cr); |
185 | return error; | 180 | } |
181 | |||
182 | /* | ||
183 | * Directory tree accounting is implemented using project quotas, where | ||
184 | * the project identifier is inherited from parent directories. | ||
185 | * A statvfs (df, etc.) of a directory that is using project quota should | ||
186 | * return a statvfs of the project, not the entire filesystem. | ||
187 | * This makes such trees appear as if they are filesystems in themselves. | ||
188 | */ | ||
189 | STATIC int | ||
190 | xfs_qm_statvfs( | ||
191 | struct bhv_desc *bhv, | ||
192 | bhv_statvfs_t *statp, | ||
193 | struct bhv_vnode *vnode) | ||
194 | { | ||
195 | xfs_mount_t *mp; | ||
196 | xfs_inode_t *ip; | ||
197 | xfs_dquot_t *dqp; | ||
198 | xfs_disk_dquot_t *dp; | ||
199 | __uint64_t limit; | ||
200 | int error; | ||
201 | |||
202 | error = bhv_next_vfs_statvfs(BHV_NEXT(bhv), statp, vnode); | ||
203 | if (error || !vnode) | ||
204 | return error; | ||
205 | |||
206 | mp = XFS_BHVTOM(bhv); | ||
207 | ip = xfs_vtoi(vnode); | ||
208 | |||
209 | if (!(ip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT)) | ||
210 | return 0; | ||
211 | if (!(mp->m_qflags & XFS_PQUOTA_ACCT)) | ||
212 | return 0; | ||
213 | if (!(mp->m_qflags & XFS_OQUOTA_ENFD)) | ||
214 | return 0; | ||
215 | |||
216 | if (xfs_qm_dqget(mp, NULL, ip->i_d.di_projid, XFS_DQ_PROJ, 0, &dqp)) | ||
217 | return 0; | ||
218 | dp = &dqp->q_core; | ||
219 | |||
220 | limit = dp->d_blk_softlimit ? dp->d_blk_softlimit : dp->d_blk_hardlimit; | ||
221 | if (limit && statp->f_blocks > limit) { | ||
222 | statp->f_blocks = limit; | ||
223 | statp->f_bfree = (statp->f_blocks > dp->d_bcount) ? | ||
224 | (statp->f_blocks - dp->d_bcount) : 0; | ||
225 | } | ||
226 | limit = dp->d_ino_softlimit ? dp->d_ino_softlimit : dp->d_ino_hardlimit; | ||
227 | if (limit && statp->f_files > limit) { | ||
228 | statp->f_files = limit; | ||
229 | statp->f_ffree = (statp->f_files > dp->d_icount) ? | ||
230 | (statp->f_ffree - dp->d_icount) : 0; | ||
231 | } | ||
232 | |||
233 | xfs_qm_dqput(dqp); | ||
234 | return 0; | ||
186 | } | 235 | } |
187 | 236 | ||
188 | STATIC int | 237 | STATIC int |
@@ -191,7 +240,7 @@ xfs_qm_syncall( | |||
191 | int flags, | 240 | int flags, |
192 | cred_t *credp) | 241 | cred_t *credp) |
193 | { | 242 | { |
194 | struct vfs *vfsp = bhvtovfs(bhv); | 243 | struct bhv_vfs *vfsp = bhvtovfs(bhv); |
195 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); | 244 | struct xfs_mount *mp = XFS_VFSTOM(vfsp); |
196 | int error; | 245 | int error; |
197 | 246 | ||
@@ -210,8 +259,7 @@ xfs_qm_syncall( | |||
210 | } | 259 | } |
211 | } | 260 | } |
212 | } | 261 | } |
213 | PVFS_SYNC(BHV_NEXT(bhv), flags, credp, error); | 262 | return bhv_next_vfs_sync(BHV_NEXT(bhv), flags, credp); |
214 | return error; | ||
215 | } | 263 | } |
216 | 264 | ||
217 | STATIC int | 265 | STATIC int |
@@ -346,11 +394,12 @@ STATIC struct xfs_qmops xfs_qmcore_xfs = { | |||
346 | .xfs_dqtrxops = &xfs_trans_dquot_ops, | 394 | .xfs_dqtrxops = &xfs_trans_dquot_ops, |
347 | }; | 395 | }; |
348 | 396 | ||
349 | struct bhv_vfsops xfs_qmops = { { | 397 | struct bhv_module_vfsops xfs_qmops = { { |
350 | BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), | 398 | BHV_IDENTITY_INIT(VFS_BHV_QM, VFS_POSITION_QM), |
351 | .vfs_parseargs = xfs_qm_parseargs, | 399 | .vfs_parseargs = xfs_qm_parseargs, |
352 | .vfs_showargs = xfs_qm_showargs, | 400 | .vfs_showargs = xfs_qm_showargs, |
353 | .vfs_mount = xfs_qm_mount, | 401 | .vfs_mount = xfs_qm_mount, |
402 | .vfs_statvfs = xfs_qm_statvfs, | ||
354 | .vfs_sync = xfs_qm_syncall, | 403 | .vfs_sync = xfs_qm_syncall, |
355 | .vfs_quotactl = xfs_qm_quotactl, }, | 404 | .vfs_quotactl = xfs_qm_quotactl, }, |
356 | }; | 405 | }; |
diff --git a/fs/xfs/quota/xfs_qm_stats.c b/fs/xfs/quota/xfs_qm_stats.c index 0570f7733550..6f858fb81a36 100644 --- a/fs/xfs/quota/xfs_qm_stats.c +++ b/fs/xfs/quota/xfs_qm_stats.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index c55db463bbf2..ed620c4d1594 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include "xfs_trans.h" | 26 | #include "xfs_trans.h" |
27 | #include "xfs_sb.h" | 27 | #include "xfs_sb.h" |
28 | #include "xfs_ag.h" | 28 | #include "xfs_ag.h" |
29 | #include "xfs_dir.h" | ||
30 | #include "xfs_dir2.h" | 29 | #include "xfs_dir2.h" |
31 | #include "xfs_alloc.h" | 30 | #include "xfs_alloc.h" |
32 | #include "xfs_dmapi.h" | 31 | #include "xfs_dmapi.h" |
@@ -35,7 +34,6 @@ | |||
35 | #include "xfs_bmap_btree.h" | 34 | #include "xfs_bmap_btree.h" |
36 | #include "xfs_alloc_btree.h" | 35 | #include "xfs_alloc_btree.h" |
37 | #include "xfs_ialloc_btree.h" | 36 | #include "xfs_ialloc_btree.h" |
38 | #include "xfs_dir_sf.h" | ||
39 | #include "xfs_dir2_sf.h" | 37 | #include "xfs_dir2_sf.h" |
40 | #include "xfs_attr_sf.h" | 38 | #include "xfs_attr_sf.h" |
41 | #include "xfs_dinode.h" | 39 | #include "xfs_dinode.h" |
@@ -91,8 +89,8 @@ xfs_qm_quotactl( | |||
91 | xfs_caddr_t addr) | 89 | xfs_caddr_t addr) |
92 | { | 90 | { |
93 | xfs_mount_t *mp; | 91 | xfs_mount_t *mp; |
92 | bhv_vfs_t *vfsp; | ||
94 | int error; | 93 | int error; |
95 | struct vfs *vfsp; | ||
96 | 94 | ||
97 | vfsp = bhvtovfs(bdp); | 95 | vfsp = bhvtovfs(bdp); |
98 | mp = XFS_VFSTOM(vfsp); | 96 | mp = XFS_VFSTOM(vfsp); |
@@ -1035,7 +1033,7 @@ xfs_qm_dqrele_all_inodes( | |||
1035 | { | 1033 | { |
1036 | xfs_inode_t *ip, *topino; | 1034 | xfs_inode_t *ip, *topino; |
1037 | uint ireclaims; | 1035 | uint ireclaims; |
1038 | vnode_t *vp; | 1036 | bhv_vnode_t *vp; |
1039 | boolean_t vnode_refd; | 1037 | boolean_t vnode_refd; |
1040 | 1038 | ||
1041 | ASSERT(mp->m_quotainfo); | 1039 | ASSERT(mp->m_quotainfo); |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 9168918db252..0242e9666e8e 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -33,7 +32,6 @@ | |||
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
39 | #include "xfs_inode.h" | 37 | #include "xfs_inode.h" |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index b08b3d9345b7..36fbeccdc722 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -47,7 +47,7 @@ cmn_err(register int level, char *fmt, ...) | |||
47 | va_start(ap, fmt); | 47 | va_start(ap, fmt); |
48 | if (*fmt == '!') fp++; | 48 | if (*fmt == '!') fp++; |
49 | len = vsprintf(message, fp, ap); | 49 | len = vsprintf(message, fp, ap); |
50 | if (message[len-1] != '\n') | 50 | if (level != CE_DEBUG && message[len-1] != '\n') |
51 | strcat(message, "\n"); | 51 | strcat(message, "\n"); |
52 | printk("%s%s", err_level[level], message); | 52 | printk("%s%s", err_level[level], message); |
53 | va_end(ap); | 53 | va_end(ap); |
@@ -68,7 +68,7 @@ icmn_err(register int level, char *fmt, va_list ap) | |||
68 | level = XFS_MAX_ERR_LEVEL; | 68 | level = XFS_MAX_ERR_LEVEL; |
69 | spin_lock_irqsave(&xfs_err_lock,flags); | 69 | spin_lock_irqsave(&xfs_err_lock,flags); |
70 | len = vsprintf(message, fmt, ap); | 70 | len = vsprintf(message, fmt, ap); |
71 | if (message[len-1] != '\n') | 71 | if (level != CE_DEBUG && message[len-1] != '\n') |
72 | strcat(message, "\n"); | 72 | strcat(message, "\n"); |
73 | spin_unlock_irqrestore(&xfs_err_lock,flags); | 73 | spin_unlock_irqrestore(&xfs_err_lock,flags); |
74 | printk("%s%s", err_level[level], message); | 74 | printk("%s%s", err_level[level], message); |
diff --git a/fs/xfs/support/debug.h b/fs/xfs/support/debug.h index e3bf58112e7e..4f54dca662a8 100644 --- a/fs/xfs/support/debug.h +++ b/fs/xfs/support/debug.h | |||
@@ -33,9 +33,6 @@ extern void cmn_err(int, char *, ...) | |||
33 | __attribute__ ((format (printf, 2, 3))); | 33 | __attribute__ ((format (printf, 2, 3))); |
34 | extern void assfail(char *expr, char *f, int l); | 34 | extern void assfail(char *expr, char *f, int l); |
35 | 35 | ||
36 | #define prdev(fmt,targ,args...) \ | ||
37 | printk("Device %s - " fmt "\n", XFS_BUFTARG_NAME(targ), ## args) | ||
38 | |||
39 | #define ASSERT_ALWAYS(expr) \ | 36 | #define ASSERT_ALWAYS(expr) \ |
40 | (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) | 37 | (unlikely((expr) != 0) ? (void)0 : assfail(#expr, __FILE__, __LINE__)) |
41 | 38 | ||
diff --git a/fs/xfs/xfs_acl.c b/fs/xfs/xfs_acl.c index 2539af34eb63..4b0cb474be4c 100644 --- a/fs/xfs/xfs_acl.c +++ b/fs/xfs/xfs_acl.c | |||
@@ -21,12 +21,10 @@ | |||
21 | #include "xfs_bit.h" | 21 | #include "xfs_bit.h" |
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_ag.h" | 23 | #include "xfs_ag.h" |
24 | #include "xfs_dir.h" | ||
25 | #include "xfs_dir2.h" | 24 | #include "xfs_dir2.h" |
26 | #include "xfs_bmap_btree.h" | 25 | #include "xfs_bmap_btree.h" |
27 | #include "xfs_alloc_btree.h" | 26 | #include "xfs_alloc_btree.h" |
28 | #include "xfs_ialloc_btree.h" | 27 | #include "xfs_ialloc_btree.h" |
29 | #include "xfs_dir_sf.h" | ||
30 | #include "xfs_dir2_sf.h" | 28 | #include "xfs_dir2_sf.h" |
31 | #include "xfs_attr_sf.h" | 29 | #include "xfs_attr_sf.h" |
32 | #include "xfs_dinode.h" | 30 | #include "xfs_dinode.h" |
@@ -39,15 +37,15 @@ | |||
39 | #include <linux/capability.h> | 37 | #include <linux/capability.h> |
40 | #include <linux/posix_acl_xattr.h> | 38 | #include <linux/posix_acl_xattr.h> |
41 | 39 | ||
42 | STATIC int xfs_acl_setmode(vnode_t *, xfs_acl_t *, int *); | 40 | STATIC int xfs_acl_setmode(bhv_vnode_t *, xfs_acl_t *, int *); |
43 | STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); | 41 | STATIC void xfs_acl_filter_mode(mode_t, xfs_acl_t *); |
44 | STATIC void xfs_acl_get_endian(xfs_acl_t *); | 42 | STATIC void xfs_acl_get_endian(xfs_acl_t *); |
45 | STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); | 43 | STATIC int xfs_acl_access(uid_t, gid_t, xfs_acl_t *, mode_t, cred_t *); |
46 | STATIC int xfs_acl_invalid(xfs_acl_t *); | 44 | STATIC int xfs_acl_invalid(xfs_acl_t *); |
47 | STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); | 45 | STATIC void xfs_acl_sync_mode(mode_t, xfs_acl_t *); |
48 | STATIC void xfs_acl_get_attr(vnode_t *, xfs_acl_t *, int, int, int *); | 46 | STATIC void xfs_acl_get_attr(bhv_vnode_t *, xfs_acl_t *, int, int, int *); |
49 | STATIC void xfs_acl_set_attr(vnode_t *, xfs_acl_t *, int, int *); | 47 | STATIC void xfs_acl_set_attr(bhv_vnode_t *, xfs_acl_t *, int, int *); |
50 | STATIC int xfs_acl_allow_set(vnode_t *, int); | 48 | STATIC int xfs_acl_allow_set(bhv_vnode_t *, int); |
51 | 49 | ||
52 | kmem_zone_t *xfs_acl_zone; | 50 | kmem_zone_t *xfs_acl_zone; |
53 | 51 | ||
@@ -57,7 +55,7 @@ kmem_zone_t *xfs_acl_zone; | |||
57 | */ | 55 | */ |
58 | int | 56 | int |
59 | xfs_acl_vhasacl_access( | 57 | xfs_acl_vhasacl_access( |
60 | vnode_t *vp) | 58 | bhv_vnode_t *vp) |
61 | { | 59 | { |
62 | int error; | 60 | int error; |
63 | 61 | ||
@@ -70,7 +68,7 @@ xfs_acl_vhasacl_access( | |||
70 | */ | 68 | */ |
71 | int | 69 | int |
72 | xfs_acl_vhasacl_default( | 70 | xfs_acl_vhasacl_default( |
73 | vnode_t *vp) | 71 | bhv_vnode_t *vp) |
74 | { | 72 | { |
75 | int error; | 73 | int error; |
76 | 74 | ||
@@ -209,7 +207,7 @@ posix_acl_xfs_to_xattr( | |||
209 | 207 | ||
210 | int | 208 | int |
211 | xfs_acl_vget( | 209 | xfs_acl_vget( |
212 | vnode_t *vp, | 210 | bhv_vnode_t *vp, |
213 | void *acl, | 211 | void *acl, |
214 | size_t size, | 212 | size_t size, |
215 | int kind) | 213 | int kind) |
@@ -241,10 +239,10 @@ xfs_acl_vget( | |||
241 | goto out; | 239 | goto out; |
242 | } | 240 | } |
243 | if (kind == _ACL_TYPE_ACCESS) { | 241 | if (kind == _ACL_TYPE_ACCESS) { |
244 | vattr_t va; | 242 | bhv_vattr_t va; |
245 | 243 | ||
246 | va.va_mask = XFS_AT_MODE; | 244 | va.va_mask = XFS_AT_MODE; |
247 | VOP_GETATTR(vp, &va, 0, sys_cred, error); | 245 | error = bhv_vop_getattr(vp, &va, 0, sys_cred); |
248 | if (error) | 246 | if (error) |
249 | goto out; | 247 | goto out; |
250 | xfs_acl_sync_mode(va.va_mode, xfs_acl); | 248 | xfs_acl_sync_mode(va.va_mode, xfs_acl); |
@@ -260,7 +258,7 @@ out: | |||
260 | 258 | ||
261 | int | 259 | int |
262 | xfs_acl_vremove( | 260 | xfs_acl_vremove( |
263 | vnode_t *vp, | 261 | bhv_vnode_t *vp, |
264 | int kind) | 262 | int kind) |
265 | { | 263 | { |
266 | int error; | 264 | int error; |
@@ -268,9 +266,9 @@ xfs_acl_vremove( | |||
268 | VN_HOLD(vp); | 266 | VN_HOLD(vp); |
269 | error = xfs_acl_allow_set(vp, kind); | 267 | error = xfs_acl_allow_set(vp, kind); |
270 | if (!error) { | 268 | if (!error) { |
271 | VOP_ATTR_REMOVE(vp, kind == _ACL_TYPE_DEFAULT? | 269 | error = bhv_vop_attr_remove(vp, kind == _ACL_TYPE_DEFAULT? |
272 | SGI_ACL_DEFAULT: SGI_ACL_FILE, | 270 | SGI_ACL_DEFAULT: SGI_ACL_FILE, |
273 | ATTR_ROOT, sys_cred, error); | 271 | ATTR_ROOT, sys_cred); |
274 | if (error == ENOATTR) | 272 | if (error == ENOATTR) |
275 | error = 0; /* 'scool */ | 273 | error = 0; /* 'scool */ |
276 | } | 274 | } |
@@ -280,7 +278,7 @@ xfs_acl_vremove( | |||
280 | 278 | ||
281 | int | 279 | int |
282 | xfs_acl_vset( | 280 | xfs_acl_vset( |
283 | vnode_t *vp, | 281 | bhv_vnode_t *vp, |
284 | void *acl, | 282 | void *acl, |
285 | size_t size, | 283 | size_t size, |
286 | int kind) | 284 | int kind) |
@@ -370,10 +368,10 @@ xfs_acl_iaccess( | |||
370 | 368 | ||
371 | STATIC int | 369 | STATIC int |
372 | xfs_acl_allow_set( | 370 | xfs_acl_allow_set( |
373 | vnode_t *vp, | 371 | bhv_vnode_t *vp, |
374 | int kind) | 372 | int kind) |
375 | { | 373 | { |
376 | vattr_t va; | 374 | bhv_vattr_t va; |
377 | int error; | 375 | int error; |
378 | 376 | ||
379 | if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) | 377 | if (vp->v_inode.i_flags & (S_IMMUTABLE|S_APPEND)) |
@@ -383,7 +381,7 @@ xfs_acl_allow_set( | |||
383 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) | 381 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) |
384 | return EROFS; | 382 | return EROFS; |
385 | va.va_mask = XFS_AT_UID; | 383 | va.va_mask = XFS_AT_UID; |
386 | VOP_GETATTR(vp, &va, 0, NULL, error); | 384 | error = bhv_vop_getattr(vp, &va, 0, NULL); |
387 | if (error) | 385 | if (error) |
388 | return error; | 386 | return error; |
389 | if (va.va_uid != current->fsuid && !capable(CAP_FOWNER)) | 387 | if (va.va_uid != current->fsuid && !capable(CAP_FOWNER)) |
@@ -606,7 +604,7 @@ xfs_acl_get_endian( | |||
606 | */ | 604 | */ |
607 | STATIC void | 605 | STATIC void |
608 | xfs_acl_get_attr( | 606 | xfs_acl_get_attr( |
609 | vnode_t *vp, | 607 | bhv_vnode_t *vp, |
610 | xfs_acl_t *aclp, | 608 | xfs_acl_t *aclp, |
611 | int kind, | 609 | int kind, |
612 | int flags, | 610 | int flags, |
@@ -616,9 +614,9 @@ xfs_acl_get_attr( | |||
616 | 614 | ||
617 | ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); | 615 | ASSERT((flags & ATTR_KERNOVAL) ? (aclp == NULL) : 1); |
618 | flags |= ATTR_ROOT; | 616 | flags |= ATTR_ROOT; |
619 | VOP_ATTR_GET(vp, | 617 | *error = bhv_vop_attr_get(vp, kind == _ACL_TYPE_ACCESS ? |
620 | kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE : SGI_ACL_DEFAULT, | 618 | SGI_ACL_FILE : SGI_ACL_DEFAULT, |
621 | (char *)aclp, &len, flags, sys_cred, *error); | 619 | (char *)aclp, &len, flags, sys_cred); |
622 | if (*error || (flags & ATTR_KERNOVAL)) | 620 | if (*error || (flags & ATTR_KERNOVAL)) |
623 | return; | 621 | return; |
624 | xfs_acl_get_endian(aclp); | 622 | xfs_acl_get_endian(aclp); |
@@ -629,7 +627,7 @@ xfs_acl_get_attr( | |||
629 | */ | 627 | */ |
630 | STATIC void | 628 | STATIC void |
631 | xfs_acl_set_attr( | 629 | xfs_acl_set_attr( |
632 | vnode_t *vp, | 630 | bhv_vnode_t *vp, |
633 | xfs_acl_t *aclp, | 631 | xfs_acl_t *aclp, |
634 | int kind, | 632 | int kind, |
635 | int *error) | 633 | int *error) |
@@ -654,19 +652,19 @@ xfs_acl_set_attr( | |||
654 | INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); | 652 | INT_SET(newace->ae_perm, ARCH_CONVERT, ace->ae_perm); |
655 | } | 653 | } |
656 | INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); | 654 | INT_SET(newacl->acl_cnt, ARCH_CONVERT, aclp->acl_cnt); |
657 | VOP_ATTR_SET(vp, | 655 | *error = bhv_vop_attr_set(vp, kind == _ACL_TYPE_ACCESS ? |
658 | kind == _ACL_TYPE_ACCESS ? SGI_ACL_FILE: SGI_ACL_DEFAULT, | 656 | SGI_ACL_FILE: SGI_ACL_DEFAULT, |
659 | (char *)newacl, len, ATTR_ROOT, sys_cred, *error); | 657 | (char *)newacl, len, ATTR_ROOT, sys_cred); |
660 | _ACL_FREE(newacl); | 658 | _ACL_FREE(newacl); |
661 | } | 659 | } |
662 | 660 | ||
663 | int | 661 | int |
664 | xfs_acl_vtoacl( | 662 | xfs_acl_vtoacl( |
665 | vnode_t *vp, | 663 | bhv_vnode_t *vp, |
666 | xfs_acl_t *access_acl, | 664 | xfs_acl_t *access_acl, |
667 | xfs_acl_t *default_acl) | 665 | xfs_acl_t *default_acl) |
668 | { | 666 | { |
669 | vattr_t va; | 667 | bhv_vattr_t va; |
670 | int error = 0; | 668 | int error = 0; |
671 | 669 | ||
672 | if (access_acl) { | 670 | if (access_acl) { |
@@ -678,7 +676,7 @@ xfs_acl_vtoacl( | |||
678 | if (!error) { | 676 | if (!error) { |
679 | /* Got the ACL, need the mode... */ | 677 | /* Got the ACL, need the mode... */ |
680 | va.va_mask = XFS_AT_MODE; | 678 | va.va_mask = XFS_AT_MODE; |
681 | VOP_GETATTR(vp, &va, 0, sys_cred, error); | 679 | error = bhv_vop_getattr(vp, &va, 0, sys_cred); |
682 | } | 680 | } |
683 | 681 | ||
684 | if (error) | 682 | if (error) |
@@ -701,8 +699,8 @@ xfs_acl_vtoacl( | |||
701 | */ | 699 | */ |
702 | int | 700 | int |
703 | xfs_acl_inherit( | 701 | xfs_acl_inherit( |
704 | vnode_t *vp, | 702 | bhv_vnode_t *vp, |
705 | vattr_t *vap, | 703 | bhv_vattr_t *vap, |
706 | xfs_acl_t *pdaclp) | 704 | xfs_acl_t *pdaclp) |
707 | { | 705 | { |
708 | xfs_acl_t *cacl; | 706 | xfs_acl_t *cacl; |
@@ -757,11 +755,11 @@ xfs_acl_inherit( | |||
757 | */ | 755 | */ |
758 | STATIC int | 756 | STATIC int |
759 | xfs_acl_setmode( | 757 | xfs_acl_setmode( |
760 | vnode_t *vp, | 758 | bhv_vnode_t *vp, |
761 | xfs_acl_t *acl, | 759 | xfs_acl_t *acl, |
762 | int *basicperms) | 760 | int *basicperms) |
763 | { | 761 | { |
764 | vattr_t va; | 762 | bhv_vattr_t va; |
765 | xfs_acl_entry_t *ap; | 763 | xfs_acl_entry_t *ap; |
766 | xfs_acl_entry_t *gap = NULL; | 764 | xfs_acl_entry_t *gap = NULL; |
767 | int i, error, nomask = 1; | 765 | int i, error, nomask = 1; |
@@ -776,7 +774,7 @@ xfs_acl_setmode( | |||
776 | * mode. The m:: bits take precedence over the g:: bits. | 774 | * mode. The m:: bits take precedence over the g:: bits. |
777 | */ | 775 | */ |
778 | va.va_mask = XFS_AT_MODE; | 776 | va.va_mask = XFS_AT_MODE; |
779 | VOP_GETATTR(vp, &va, 0, sys_cred, error); | 777 | error = bhv_vop_getattr(vp, &va, 0, sys_cred); |
780 | if (error) | 778 | if (error) |
781 | return error; | 779 | return error; |
782 | 780 | ||
@@ -810,8 +808,7 @@ xfs_acl_setmode( | |||
810 | if (gap && nomask) | 808 | if (gap && nomask) |
811 | va.va_mode |= gap->ae_perm << 3; | 809 | va.va_mode |= gap->ae_perm << 3; |
812 | 810 | ||
813 | VOP_SETATTR(vp, &va, 0, sys_cred, error); | 811 | return bhv_vop_setattr(vp, &va, 0, sys_cred); |
814 | return error; | ||
815 | } | 812 | } |
816 | 813 | ||
817 | /* | 814 | /* |
diff --git a/fs/xfs/xfs_acl.h b/fs/xfs/xfs_acl.h index 538d0d65b04c..f853cf1a6270 100644 --- a/fs/xfs/xfs_acl.h +++ b/fs/xfs/xfs_acl.h | |||
@@ -50,7 +50,7 @@ typedef struct xfs_acl { | |||
50 | #ifdef CONFIG_XFS_POSIX_ACL | 50 | #ifdef CONFIG_XFS_POSIX_ACL |
51 | 51 | ||
52 | struct vattr; | 52 | struct vattr; |
53 | struct vnode; | 53 | struct bhv_vnode; |
54 | struct xfs_inode; | 54 | struct xfs_inode; |
55 | 55 | ||
56 | extern struct kmem_zone *xfs_acl_zone; | 56 | extern struct kmem_zone *xfs_acl_zone; |
@@ -58,14 +58,14 @@ extern struct kmem_zone *xfs_acl_zone; | |||
58 | (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) | 58 | (zone) = kmem_zone_init(sizeof(xfs_acl_t), (name)) |
59 | #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) | 59 | #define xfs_acl_zone_destroy(zone) kmem_zone_destroy(zone) |
60 | 60 | ||
61 | extern int xfs_acl_inherit(struct vnode *, struct vattr *, xfs_acl_t *); | 61 | extern int xfs_acl_inherit(struct bhv_vnode *, struct bhv_vattr *, xfs_acl_t *); |
62 | extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); | 62 | extern int xfs_acl_iaccess(struct xfs_inode *, mode_t, cred_t *); |
63 | extern int xfs_acl_vtoacl(struct vnode *, xfs_acl_t *, xfs_acl_t *); | 63 | extern int xfs_acl_vtoacl(struct bhv_vnode *, xfs_acl_t *, xfs_acl_t *); |
64 | extern int xfs_acl_vhasacl_access(struct vnode *); | 64 | extern int xfs_acl_vhasacl_access(struct bhv_vnode *); |
65 | extern int xfs_acl_vhasacl_default(struct vnode *); | 65 | extern int xfs_acl_vhasacl_default(struct bhv_vnode *); |
66 | extern int xfs_acl_vset(struct vnode *, void *, size_t, int); | 66 | extern int xfs_acl_vset(struct bhv_vnode *, void *, size_t, int); |
67 | extern int xfs_acl_vget(struct vnode *, void *, size_t, int); | 67 | extern int xfs_acl_vget(struct bhv_vnode *, void *, size_t, int); |
68 | extern int xfs_acl_vremove(struct vnode *vp, int); | 68 | extern int xfs_acl_vremove(struct bhv_vnode *, int); |
69 | 69 | ||
70 | #define _ACL_TYPE_ACCESS 1 | 70 | #define _ACL_TYPE_ACCESS 1 |
71 | #define _ACL_TYPE_DEFAULT 2 | 71 | #define _ACL_TYPE_DEFAULT 2 |
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 8558226281c4..eef6763f3a67 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -1862,7 +1860,7 @@ xfs_alloc_fix_freelist( | |||
1862 | (pag->pagf_longest - delta) : | 1860 | (pag->pagf_longest - delta) : |
1863 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); | 1861 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); |
1864 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || | 1862 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || |
1865 | (args->minleft && | 1863 | (!(flags & XFS_ALLOC_FLAG_FREEING) && |
1866 | (int)(pag->pagf_freeblks + pag->pagf_flcount - | 1864 | (int)(pag->pagf_freeblks + pag->pagf_flcount - |
1867 | need - args->total) < | 1865 | need - args->total) < |
1868 | (int)args->minleft)) { | 1866 | (int)args->minleft)) { |
@@ -1898,7 +1896,7 @@ xfs_alloc_fix_freelist( | |||
1898 | longest = (longest > delta) ? (longest - delta) : | 1896 | longest = (longest > delta) ? (longest - delta) : |
1899 | (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); | 1897 | (be32_to_cpu(agf->agf_flcount) > 0 || longest > 0); |
1900 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || | 1898 | if (args->minlen + args->alignment + args->minalignslop - 1 > longest || |
1901 | (args->minleft && | 1899 | (!(flags & XFS_ALLOC_FLAG_FREEING) && |
1902 | (int)(be32_to_cpu(agf->agf_freeblks) + | 1900 | (int)(be32_to_cpu(agf->agf_freeblks) + |
1903 | be32_to_cpu(agf->agf_flcount) - need - args->total) < | 1901 | be32_to_cpu(agf->agf_flcount) - need - args->total) < |
1904 | (int)args->minleft)) { | 1902 | (int)args->minleft)) { |
@@ -1951,8 +1949,14 @@ xfs_alloc_fix_freelist( | |||
1951 | * the restrictions correctly. Can happen for free calls | 1949 | * the restrictions correctly. Can happen for free calls |
1952 | * on a completely full ag. | 1950 | * on a completely full ag. |
1953 | */ | 1951 | */ |
1954 | if (targs.agbno == NULLAGBLOCK) | 1952 | if (targs.agbno == NULLAGBLOCK) { |
1953 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { | ||
1954 | xfs_trans_brelse(tp, agflbp); | ||
1955 | args->agbp = NULL; | ||
1956 | return 0; | ||
1957 | } | ||
1955 | break; | 1958 | break; |
1959 | } | ||
1956 | /* | 1960 | /* |
1957 | * Put each allocated block on the list. | 1961 | * Put each allocated block on the list. |
1958 | */ | 1962 | */ |
@@ -2360,8 +2364,19 @@ xfs_alloc_vextent( | |||
2360 | if (args->agno == sagno && | 2364 | if (args->agno == sagno && |
2361 | type == XFS_ALLOCTYPE_START_BNO) | 2365 | type == XFS_ALLOCTYPE_START_BNO) |
2362 | args->type = XFS_ALLOCTYPE_THIS_AG; | 2366 | args->type = XFS_ALLOCTYPE_THIS_AG; |
2363 | if (++(args->agno) == mp->m_sb.sb_agcount) | 2367 | /* |
2364 | args->agno = 0; | 2368 | * For the first allocation, we can try any AG to get |
2369 | * space. However, if we already have allocated a | ||
2370 | * block, we don't want to try AGs whose number is below | ||
2371 | * sagno. Otherwise, we may end up with out-of-order | ||
2372 | * locking of AGF, which might cause deadlock. | ||
2373 | */ | ||
2374 | if (++(args->agno) == mp->m_sb.sb_agcount) { | ||
2375 | if (args->firstblock != NULLFSBLOCK) | ||
2376 | args->agno = sagno; | ||
2377 | else | ||
2378 | args->agno = 0; | ||
2379 | } | ||
2365 | /* | 2380 | /* |
2366 | * Reached the starting a.g., must either be done | 2381 | * Reached the starting a.g., must either be done |
2367 | * or switch to non-trylock mode. | 2382 | * or switch to non-trylock mode. |
@@ -2443,7 +2458,7 @@ xfs_free_extent( | |||
2443 | args.minlen = args.minleft = args.minalignslop = 0; | 2458 | args.minlen = args.minleft = args.minalignslop = 0; |
2444 | down_read(&args.mp->m_peraglock); | 2459 | down_read(&args.mp->m_peraglock); |
2445 | args.pag = &args.mp->m_perag[args.agno]; | 2460 | args.pag = &args.mp->m_perag[args.agno]; |
2446 | if ((error = xfs_alloc_fix_freelist(&args, 0))) | 2461 | if ((error = xfs_alloc_fix_freelist(&args, XFS_ALLOC_FLAG_FREEING))) |
2447 | goto error0; | 2462 | goto error0; |
2448 | #ifdef DEBUG | 2463 | #ifdef DEBUG |
2449 | ASSERT(args.agbp != NULL); | 2464 | ASSERT(args.agbp != NULL); |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 2d1f8928b267..650591f999ae 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -41,6 +41,7 @@ typedef enum xfs_alloctype | |||
41 | * Flags for xfs_alloc_fix_freelist. | 41 | * Flags for xfs_alloc_fix_freelist. |
42 | */ | 42 | */ |
43 | #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ | 43 | #define XFS_ALLOC_FLAG_TRYLOCK 0x00000001 /* use trylock for buffer locking */ |
44 | #define XFS_ALLOC_FLAG_FREEING 0x00000002 /* indicate caller is freeing extents*/ | ||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * Argument structure for xfs_alloc routines. | 47 | * Argument structure for xfs_alloc routines. |
@@ -70,6 +71,7 @@ typedef struct xfs_alloc_arg { | |||
70 | char wasfromfl; /* set if allocation is from freelist */ | 71 | char wasfromfl; /* set if allocation is from freelist */ |
71 | char isfl; /* set if is freelist blocks - !acctg */ | 72 | char isfl; /* set if is freelist blocks - !acctg */ |
72 | char userdata; /* set if this is user data */ | 73 | char userdata; /* set if this is user data */ |
74 | xfs_fsblock_t firstblock; /* io first block allocated */ | ||
73 | } xfs_alloc_arg_t; | 75 | } xfs_alloc_arg_t; |
74 | 76 | ||
75 | /* | 77 | /* |
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index a1d92da86ccd..7446556e8021 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_attr.c b/fs/xfs/xfs_attr.c index b6e1e02bbb28..1a2101043275 100644 --- a/fs/xfs/xfs_attr.c +++ b/fs/xfs/xfs_attr.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #include "xfs_trans.h" | 27 | #include "xfs_trans.h" |
28 | #include "xfs_sb.h" | 28 | #include "xfs_sb.h" |
29 | #include "xfs_ag.h" | 29 | #include "xfs_ag.h" |
30 | #include "xfs_dir.h" | ||
31 | #include "xfs_dir2.h" | 30 | #include "xfs_dir2.h" |
32 | #include "xfs_dmapi.h" | 31 | #include "xfs_dmapi.h" |
33 | #include "xfs_mount.h" | 32 | #include "xfs_mount.h" |
@@ -35,7 +34,6 @@ | |||
35 | #include "xfs_bmap_btree.h" | 34 | #include "xfs_bmap_btree.h" |
36 | #include "xfs_alloc_btree.h" | 35 | #include "xfs_alloc_btree.h" |
37 | #include "xfs_ialloc_btree.h" | 36 | #include "xfs_ialloc_btree.h" |
38 | #include "xfs_dir_sf.h" | ||
39 | #include "xfs_dir2_sf.h" | 37 | #include "xfs_dir2_sf.h" |
40 | #include "xfs_attr_sf.h" | 38 | #include "xfs_attr_sf.h" |
41 | #include "xfs_dinode.h" | 39 | #include "xfs_dinode.h" |
@@ -1910,7 +1908,7 @@ xfs_attr_rmtval_get(xfs_da_args_t *args) | |||
1910 | error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, | 1908 | error = xfs_bmapi(args->trans, args->dp, (xfs_fileoff_t)lblkno, |
1911 | args->rmtblkcnt, | 1909 | args->rmtblkcnt, |
1912 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 1910 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
1913 | NULL, 0, map, &nmap, NULL); | 1911 | NULL, 0, map, &nmap, NULL, NULL); |
1914 | if (error) | 1912 | if (error) |
1915 | return(error); | 1913 | return(error); |
1916 | ASSERT(nmap >= 1); | 1914 | ASSERT(nmap >= 1); |
@@ -1988,7 +1986,7 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
1988 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | | 1986 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA | |
1989 | XFS_BMAPI_WRITE, | 1987 | XFS_BMAPI_WRITE, |
1990 | args->firstblock, args->total, &map, &nmap, | 1988 | args->firstblock, args->total, &map, &nmap, |
1991 | args->flist); | 1989 | args->flist, NULL); |
1992 | if (!error) { | 1990 | if (!error) { |
1993 | error = xfs_bmap_finish(&args->trans, args->flist, | 1991 | error = xfs_bmap_finish(&args->trans, args->flist, |
1994 | *args->firstblock, &committed); | 1992 | *args->firstblock, &committed); |
@@ -2039,7 +2037,8 @@ xfs_attr_rmtval_set(xfs_da_args_t *args) | |||
2039 | error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, | 2037 | error = xfs_bmapi(NULL, dp, (xfs_fileoff_t)lblkno, |
2040 | args->rmtblkcnt, | 2038 | args->rmtblkcnt, |
2041 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2039 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2042 | args->firstblock, 0, &map, &nmap, NULL); | 2040 | args->firstblock, 0, &map, &nmap, |
2041 | NULL, NULL); | ||
2043 | if (error) { | 2042 | if (error) { |
2044 | return(error); | 2043 | return(error); |
2045 | } | 2044 | } |
@@ -2104,7 +2103,7 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2104 | args->rmtblkcnt, | 2103 | args->rmtblkcnt, |
2105 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2104 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2106 | args->firstblock, 0, &map, &nmap, | 2105 | args->firstblock, 0, &map, &nmap, |
2107 | args->flist); | 2106 | args->flist, NULL); |
2108 | if (error) { | 2107 | if (error) { |
2109 | return(error); | 2108 | return(error); |
2110 | } | 2109 | } |
@@ -2142,7 +2141,8 @@ xfs_attr_rmtval_remove(xfs_da_args_t *args) | |||
2142 | XFS_BMAP_INIT(args->flist, args->firstblock); | 2141 | XFS_BMAP_INIT(args->flist, args->firstblock); |
2143 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, | 2142 | error = xfs_bunmapi(args->trans, args->dp, lblkno, blkcnt, |
2144 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2143 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2145 | 1, args->firstblock, args->flist, &done); | 2144 | 1, args->firstblock, args->flist, |
2145 | NULL, &done); | ||
2146 | if (!error) { | 2146 | if (!error) { |
2147 | error = xfs_bmap_finish(&args->trans, args->flist, | 2147 | error = xfs_bmap_finish(&args->trans, args->flist, |
2148 | *args->firstblock, &committed); | 2148 | *args->firstblock, &committed); |
@@ -2322,56 +2322,56 @@ xfs_attr_trace_enter(int type, char *where, | |||
2322 | 2322 | ||
2323 | STATIC int | 2323 | STATIC int |
2324 | posix_acl_access_set( | 2324 | posix_acl_access_set( |
2325 | vnode_t *vp, char *name, void *data, size_t size, int xflags) | 2325 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2326 | { | 2326 | { |
2327 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); | 2327 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_ACCESS); |
2328 | } | 2328 | } |
2329 | 2329 | ||
2330 | STATIC int | 2330 | STATIC int |
2331 | posix_acl_access_remove( | 2331 | posix_acl_access_remove( |
2332 | struct vnode *vp, char *name, int xflags) | 2332 | bhv_vnode_t *vp, char *name, int xflags) |
2333 | { | 2333 | { |
2334 | return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); | 2334 | return xfs_acl_vremove(vp, _ACL_TYPE_ACCESS); |
2335 | } | 2335 | } |
2336 | 2336 | ||
2337 | STATIC int | 2337 | STATIC int |
2338 | posix_acl_access_get( | 2338 | posix_acl_access_get( |
2339 | vnode_t *vp, char *name, void *data, size_t size, int xflags) | 2339 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2340 | { | 2340 | { |
2341 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); | 2341 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_ACCESS); |
2342 | } | 2342 | } |
2343 | 2343 | ||
2344 | STATIC int | 2344 | STATIC int |
2345 | posix_acl_access_exists( | 2345 | posix_acl_access_exists( |
2346 | vnode_t *vp) | 2346 | bhv_vnode_t *vp) |
2347 | { | 2347 | { |
2348 | return xfs_acl_vhasacl_access(vp); | 2348 | return xfs_acl_vhasacl_access(vp); |
2349 | } | 2349 | } |
2350 | 2350 | ||
2351 | STATIC int | 2351 | STATIC int |
2352 | posix_acl_default_set( | 2352 | posix_acl_default_set( |
2353 | vnode_t *vp, char *name, void *data, size_t size, int xflags) | 2353 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2354 | { | 2354 | { |
2355 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); | 2355 | return xfs_acl_vset(vp, data, size, _ACL_TYPE_DEFAULT); |
2356 | } | 2356 | } |
2357 | 2357 | ||
2358 | STATIC int | 2358 | STATIC int |
2359 | posix_acl_default_get( | 2359 | posix_acl_default_get( |
2360 | vnode_t *vp, char *name, void *data, size_t size, int xflags) | 2360 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2361 | { | 2361 | { |
2362 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); | 2362 | return xfs_acl_vget(vp, data, size, _ACL_TYPE_DEFAULT); |
2363 | } | 2363 | } |
2364 | 2364 | ||
2365 | STATIC int | 2365 | STATIC int |
2366 | posix_acl_default_remove( | 2366 | posix_acl_default_remove( |
2367 | struct vnode *vp, char *name, int xflags) | 2367 | bhv_vnode_t *vp, char *name, int xflags) |
2368 | { | 2368 | { |
2369 | return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); | 2369 | return xfs_acl_vremove(vp, _ACL_TYPE_DEFAULT); |
2370 | } | 2370 | } |
2371 | 2371 | ||
2372 | STATIC int | 2372 | STATIC int |
2373 | posix_acl_default_exists( | 2373 | posix_acl_default_exists( |
2374 | vnode_t *vp) | 2374 | bhv_vnode_t *vp) |
2375 | { | 2375 | { |
2376 | return xfs_acl_vhasacl_default(vp); | 2376 | return xfs_acl_vhasacl_default(vp); |
2377 | } | 2377 | } |
@@ -2404,21 +2404,18 @@ STATIC struct attrnames *attr_system_names[] = | |||
2404 | 2404 | ||
2405 | STATIC int | 2405 | STATIC int |
2406 | attr_generic_set( | 2406 | attr_generic_set( |
2407 | struct vnode *vp, char *name, void *data, size_t size, int xflags) | 2407 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2408 | { | 2408 | { |
2409 | int error; | 2409 | return -bhv_vop_attr_set(vp, name, data, size, xflags, NULL); |
2410 | |||
2411 | VOP_ATTR_SET(vp, name, data, size, xflags, NULL, error); | ||
2412 | return -error; | ||
2413 | } | 2410 | } |
2414 | 2411 | ||
2415 | STATIC int | 2412 | STATIC int |
2416 | attr_generic_get( | 2413 | attr_generic_get( |
2417 | struct vnode *vp, char *name, void *data, size_t size, int xflags) | 2414 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2418 | { | 2415 | { |
2419 | int error, asize = size; | 2416 | int error, asize = size; |
2420 | 2417 | ||
2421 | VOP_ATTR_GET(vp, name, data, &asize, xflags, NULL, error); | 2418 | error = bhv_vop_attr_get(vp, name, data, &asize, xflags, NULL); |
2422 | if (!error) | 2419 | if (!error) |
2423 | return asize; | 2420 | return asize; |
2424 | return -error; | 2421 | return -error; |
@@ -2426,12 +2423,9 @@ attr_generic_get( | |||
2426 | 2423 | ||
2427 | STATIC int | 2424 | STATIC int |
2428 | attr_generic_remove( | 2425 | attr_generic_remove( |
2429 | struct vnode *vp, char *name, int xflags) | 2426 | bhv_vnode_t *vp, char *name, int xflags) |
2430 | { | 2427 | { |
2431 | int error; | 2428 | return -bhv_vop_attr_remove(vp, name, xflags, NULL); |
2432 | |||
2433 | VOP_ATTR_REMOVE(vp, name, xflags, NULL, error); | ||
2434 | return -error; | ||
2435 | } | 2429 | } |
2436 | 2430 | ||
2437 | STATIC int | 2431 | STATIC int |
@@ -2459,7 +2453,7 @@ attr_generic_listadd( | |||
2459 | 2453 | ||
2460 | STATIC int | 2454 | STATIC int |
2461 | attr_system_list( | 2455 | attr_system_list( |
2462 | struct vnode *vp, | 2456 | bhv_vnode_t *vp, |
2463 | void *data, | 2457 | void *data, |
2464 | size_t size, | 2458 | size_t size, |
2465 | ssize_t *result) | 2459 | ssize_t *result) |
@@ -2481,12 +2475,12 @@ attr_system_list( | |||
2481 | 2475 | ||
2482 | int | 2476 | int |
2483 | attr_generic_list( | 2477 | attr_generic_list( |
2484 | struct vnode *vp, void *data, size_t size, int xflags, ssize_t *result) | 2478 | bhv_vnode_t *vp, void *data, size_t size, int xflags, ssize_t *result) |
2485 | { | 2479 | { |
2486 | attrlist_cursor_kern_t cursor = { 0 }; | 2480 | attrlist_cursor_kern_t cursor = { 0 }; |
2487 | int error; | 2481 | int error; |
2488 | 2482 | ||
2489 | VOP_ATTR_LIST(vp, data, size, xflags, &cursor, NULL, error); | 2483 | error = bhv_vop_attr_list(vp, data, size, xflags, &cursor, NULL); |
2490 | if (error > 0) | 2484 | if (error > 0) |
2491 | return -error; | 2485 | return -error; |
2492 | *result = -error; | 2486 | *result = -error; |
@@ -2514,7 +2508,7 @@ attr_lookup_namespace( | |||
2514 | */ | 2508 | */ |
2515 | STATIC int | 2509 | STATIC int |
2516 | attr_user_capable( | 2510 | attr_user_capable( |
2517 | struct vnode *vp, | 2511 | bhv_vnode_t *vp, |
2518 | cred_t *cred) | 2512 | cred_t *cred) |
2519 | { | 2513 | { |
2520 | struct inode *inode = vn_to_inode(vp); | 2514 | struct inode *inode = vn_to_inode(vp); |
@@ -2532,7 +2526,7 @@ attr_user_capable( | |||
2532 | 2526 | ||
2533 | STATIC int | 2527 | STATIC int |
2534 | attr_trusted_capable( | 2528 | attr_trusted_capable( |
2535 | struct vnode *vp, | 2529 | bhv_vnode_t *vp, |
2536 | cred_t *cred) | 2530 | cred_t *cred) |
2537 | { | 2531 | { |
2538 | struct inode *inode = vn_to_inode(vp); | 2532 | struct inode *inode = vn_to_inode(vp); |
@@ -2546,7 +2540,7 @@ attr_trusted_capable( | |||
2546 | 2540 | ||
2547 | STATIC int | 2541 | STATIC int |
2548 | attr_secure_capable( | 2542 | attr_secure_capable( |
2549 | struct vnode *vp, | 2543 | bhv_vnode_t *vp, |
2550 | cred_t *cred) | 2544 | cred_t *cred) |
2551 | { | 2545 | { |
2552 | return -ENOSECURITY; | 2546 | return -ENOSECURITY; |
@@ -2554,7 +2548,7 @@ attr_secure_capable( | |||
2554 | 2548 | ||
2555 | STATIC int | 2549 | STATIC int |
2556 | attr_system_set( | 2550 | attr_system_set( |
2557 | struct vnode *vp, char *name, void *data, size_t size, int xflags) | 2551 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2558 | { | 2552 | { |
2559 | attrnames_t *namesp; | 2553 | attrnames_t *namesp; |
2560 | int error; | 2554 | int error; |
@@ -2573,7 +2567,7 @@ attr_system_set( | |||
2573 | 2567 | ||
2574 | STATIC int | 2568 | STATIC int |
2575 | attr_system_get( | 2569 | attr_system_get( |
2576 | struct vnode *vp, char *name, void *data, size_t size, int xflags) | 2570 | bhv_vnode_t *vp, char *name, void *data, size_t size, int xflags) |
2577 | { | 2571 | { |
2578 | attrnames_t *namesp; | 2572 | attrnames_t *namesp; |
2579 | 2573 | ||
@@ -2585,7 +2579,7 @@ attr_system_get( | |||
2585 | 2579 | ||
2586 | STATIC int | 2580 | STATIC int |
2587 | attr_system_remove( | 2581 | attr_system_remove( |
2588 | struct vnode *vp, char *name, int xflags) | 2582 | bhv_vnode_t *vp, char *name, int xflags) |
2589 | { | 2583 | { |
2590 | attrnames_t *namesp; | 2584 | attrnames_t *namesp; |
2591 | 2585 | ||
diff --git a/fs/xfs/xfs_attr.h b/fs/xfs/xfs_attr.h index b2c7b9fcded3..981633f6c077 100644 --- a/fs/xfs/xfs_attr.h +++ b/fs/xfs/xfs_attr.h | |||
@@ -36,13 +36,13 @@ | |||
36 | *========================================================================*/ | 36 | *========================================================================*/ |
37 | 37 | ||
38 | struct cred; | 38 | struct cred; |
39 | struct vnode; | 39 | struct bhv_vnode; |
40 | 40 | ||
41 | typedef int (*attrset_t)(struct vnode *, char *, void *, size_t, int); | 41 | typedef int (*attrset_t)(struct bhv_vnode *, char *, void *, size_t, int); |
42 | typedef int (*attrget_t)(struct vnode *, char *, void *, size_t, int); | 42 | typedef int (*attrget_t)(struct bhv_vnode *, char *, void *, size_t, int); |
43 | typedef int (*attrremove_t)(struct vnode *, char *, int); | 43 | typedef int (*attrremove_t)(struct bhv_vnode *, char *, int); |
44 | typedef int (*attrexists_t)(struct vnode *); | 44 | typedef int (*attrexists_t)(struct bhv_vnode *); |
45 | typedef int (*attrcapable_t)(struct vnode *, struct cred *); | 45 | typedef int (*attrcapable_t)(struct bhv_vnode *, struct cred *); |
46 | 46 | ||
47 | typedef struct attrnames { | 47 | typedef struct attrnames { |
48 | char * attr_name; | 48 | char * attr_name; |
@@ -63,7 +63,7 @@ extern struct attrnames attr_trusted; | |||
63 | extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; | 63 | extern struct attrnames *attr_namespaces[ATTR_NAMECOUNT]; |
64 | 64 | ||
65 | extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int); | 65 | extern attrnames_t *attr_lookup_namespace(char *, attrnames_t **, int); |
66 | extern int attr_generic_list(struct vnode *, void *, size_t, int, ssize_t *); | 66 | extern int attr_generic_list(struct bhv_vnode *, void *, size_t, int, ssize_t *); |
67 | 67 | ||
68 | #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ | 68 | #define ATTR_DONTFOLLOW 0x0001 /* -- unused, from IRIX -- */ |
69 | #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ | 69 | #define ATTR_ROOT 0x0002 /* use attrs in root (trusted) namespace */ |
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 9462be86aa14..9455051f0120 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -34,7 +33,6 @@ | |||
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_alloc.h" | 34 | #include "xfs_alloc.h" |
36 | #include "xfs_btree.h" | 35 | #include "xfs_btree.h" |
37 | #include "xfs_dir_sf.h" | ||
38 | #include "xfs_dir2_sf.h" | 36 | #include "xfs_dir2_sf.h" |
39 | #include "xfs_attr_sf.h" | 37 | #include "xfs_attr_sf.h" |
40 | #include "xfs_dinode.h" | 38 | #include "xfs_dinode.h" |
@@ -2990,7 +2988,7 @@ xfs_attr_leaf_freextent(xfs_trans_t **trans, xfs_inode_t *dp, | |||
2990 | nmap = 1; | 2988 | nmap = 1; |
2991 | error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, | 2989 | error = xfs_bmapi(*trans, dp, (xfs_fileoff_t)tblkno, tblkcnt, |
2992 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, | 2990 | XFS_BMAPI_ATTRFORK | XFS_BMAPI_METADATA, |
2993 | NULL, 0, &map, &nmap, NULL); | 2991 | NULL, 0, &map, &nmap, NULL, NULL); |
2994 | if (error) { | 2992 | if (error) { |
2995 | return(error); | 2993 | return(error); |
2996 | } | 2994 | } |
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index 26939d364bc4..3a6137539064 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,13 +24,11 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_alloc_btree.h" | 30 | #include "xfs_alloc_btree.h" |
32 | #include "xfs_ialloc_btree.h" | 31 | #include "xfs_ialloc_btree.h" |
33 | #include "xfs_dir_sf.h" | ||
34 | #include "xfs_dir2_sf.h" | 32 | #include "xfs_dir2_sf.h" |
35 | #include "xfs_attr_sf.h" | 33 | #include "xfs_attr_sf.h" |
36 | #include "xfs_dinode.h" | 34 | #include "xfs_dinode.h" |
@@ -40,13 +38,15 @@ | |||
40 | #include "xfs_mount.h" | 38 | #include "xfs_mount.h" |
41 | #include "xfs_ialloc.h" | 39 | #include "xfs_ialloc.h" |
42 | #include "xfs_itable.h" | 40 | #include "xfs_itable.h" |
41 | #include "xfs_dir2_data.h" | ||
42 | #include "xfs_dir2_leaf.h" | ||
43 | #include "xfs_dir2_block.h" | ||
43 | #include "xfs_inode_item.h" | 44 | #include "xfs_inode_item.h" |
44 | #include "xfs_extfree_item.h" | 45 | #include "xfs_extfree_item.h" |
45 | #include "xfs_alloc.h" | 46 | #include "xfs_alloc.h" |
46 | #include "xfs_bmap.h" | 47 | #include "xfs_bmap.h" |
47 | #include "xfs_rtalloc.h" | 48 | #include "xfs_rtalloc.h" |
48 | #include "xfs_error.h" | 49 | #include "xfs_error.h" |
49 | #include "xfs_dir_leaf.h" | ||
50 | #include "xfs_attr_leaf.h" | 50 | #include "xfs_attr_leaf.h" |
51 | #include "xfs_rw.h" | 51 | #include "xfs_rw.h" |
52 | #include "xfs_quota.h" | 52 | #include "xfs_quota.h" |
@@ -101,6 +101,7 @@ xfs_bmap_add_extent( | |||
101 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 101 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
102 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 102 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
103 | int *logflagsp, /* inode logging flags */ | 103 | int *logflagsp, /* inode logging flags */ |
104 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
104 | int whichfork, /* data or attr fork */ | 105 | int whichfork, /* data or attr fork */ |
105 | int rsvd); /* OK to allocate reserved blocks */ | 106 | int rsvd); /* OK to allocate reserved blocks */ |
106 | 107 | ||
@@ -118,6 +119,7 @@ xfs_bmap_add_extent_delay_real( | |||
118 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 119 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
119 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 120 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
120 | int *logflagsp, /* inode logging flags */ | 121 | int *logflagsp, /* inode logging flags */ |
122 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
121 | int rsvd); /* OK to allocate reserved blocks */ | 123 | int rsvd); /* OK to allocate reserved blocks */ |
122 | 124 | ||
123 | /* | 125 | /* |
@@ -131,6 +133,7 @@ xfs_bmap_add_extent_hole_delay( | |||
131 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 133 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
132 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 134 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
133 | int *logflagsp,/* inode logging flags */ | 135 | int *logflagsp,/* inode logging flags */ |
136 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
134 | int rsvd); /* OK to allocate reserved blocks */ | 137 | int rsvd); /* OK to allocate reserved blocks */ |
135 | 138 | ||
136 | /* | 139 | /* |
@@ -144,6 +147,7 @@ xfs_bmap_add_extent_hole_real( | |||
144 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 147 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
145 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 148 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
146 | int *logflagsp, /* inode logging flags */ | 149 | int *logflagsp, /* inode logging flags */ |
150 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
147 | int whichfork); /* data or attr fork */ | 151 | int whichfork); /* data or attr fork */ |
148 | 152 | ||
149 | /* | 153 | /* |
@@ -156,7 +160,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
156 | xfs_extnum_t idx, /* extent number to update/insert */ | 160 | xfs_extnum_t idx, /* extent number to update/insert */ |
157 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 161 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
158 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 162 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
159 | int *logflagsp); /* inode logging flags */ | 163 | int *logflagsp, /* inode logging flags */ |
164 | xfs_extdelta_t *delta); /* Change made to incore extents */ | ||
160 | 165 | ||
161 | /* | 166 | /* |
162 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. | 167 | * xfs_bmap_alloc is called by xfs_bmapi to allocate an extent for a file. |
@@ -203,6 +208,7 @@ xfs_bmap_del_extent( | |||
203 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 208 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
204 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 209 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
205 | int *logflagsp,/* inode logging flags */ | 210 | int *logflagsp,/* inode logging flags */ |
211 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
206 | int whichfork, /* data or attr fork */ | 212 | int whichfork, /* data or attr fork */ |
207 | int rsvd); /* OK to allocate reserved blocks */ | 213 | int rsvd); /* OK to allocate reserved blocks */ |
208 | 214 | ||
@@ -510,7 +516,7 @@ xfs_bmap_add_attrfork_local( | |||
510 | dargs.total = mp->m_dirblkfsbs; | 516 | dargs.total = mp->m_dirblkfsbs; |
511 | dargs.whichfork = XFS_DATA_FORK; | 517 | dargs.whichfork = XFS_DATA_FORK; |
512 | dargs.trans = tp; | 518 | dargs.trans = tp; |
513 | error = XFS_DIR_SHORTFORM_TO_SINGLE(mp, &dargs); | 519 | error = xfs_dir2_sf_to_block(&dargs); |
514 | } else | 520 | } else |
515 | error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, | 521 | error = xfs_bmap_local_to_extents(tp, ip, firstblock, 1, flags, |
516 | XFS_DATA_FORK); | 522 | XFS_DATA_FORK); |
@@ -530,6 +536,7 @@ xfs_bmap_add_extent( | |||
530 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 536 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
531 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 537 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
532 | int *logflagsp, /* inode logging flags */ | 538 | int *logflagsp, /* inode logging flags */ |
539 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
533 | int whichfork, /* data or attr fork */ | 540 | int whichfork, /* data or attr fork */ |
534 | int rsvd) /* OK to use reserved data blocks */ | 541 | int rsvd) /* OK to use reserved data blocks */ |
535 | { | 542 | { |
@@ -567,6 +574,15 @@ xfs_bmap_add_extent( | |||
567 | logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); | 574 | logflags = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); |
568 | } else | 575 | } else |
569 | logflags = 0; | 576 | logflags = 0; |
577 | /* DELTA: single new extent */ | ||
578 | if (delta) { | ||
579 | if (delta->xed_startoff > new->br_startoff) | ||
580 | delta->xed_startoff = new->br_startoff; | ||
581 | if (delta->xed_blockcount < | ||
582 | new->br_startoff + new->br_blockcount) | ||
583 | delta->xed_blockcount = new->br_startoff + | ||
584 | new->br_blockcount; | ||
585 | } | ||
570 | } | 586 | } |
571 | /* | 587 | /* |
572 | * Any kind of new delayed allocation goes here. | 588 | * Any kind of new delayed allocation goes here. |
@@ -576,7 +592,7 @@ xfs_bmap_add_extent( | |||
576 | ASSERT((cur->bc_private.b.flags & | 592 | ASSERT((cur->bc_private.b.flags & |
577 | XFS_BTCUR_BPRV_WASDEL) == 0); | 593 | XFS_BTCUR_BPRV_WASDEL) == 0); |
578 | if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new, | 594 | if ((error = xfs_bmap_add_extent_hole_delay(ip, idx, cur, new, |
579 | &logflags, rsvd))) | 595 | &logflags, delta, rsvd))) |
580 | goto done; | 596 | goto done; |
581 | } | 597 | } |
582 | /* | 598 | /* |
@@ -587,7 +603,7 @@ xfs_bmap_add_extent( | |||
587 | ASSERT((cur->bc_private.b.flags & | 603 | ASSERT((cur->bc_private.b.flags & |
588 | XFS_BTCUR_BPRV_WASDEL) == 0); | 604 | XFS_BTCUR_BPRV_WASDEL) == 0); |
589 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, | 605 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, new, |
590 | &logflags, whichfork))) | 606 | &logflags, delta, whichfork))) |
591 | goto done; | 607 | goto done; |
592 | } else { | 608 | } else { |
593 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ | 609 | xfs_bmbt_irec_t prev; /* old extent at offset idx */ |
@@ -612,17 +628,17 @@ xfs_bmap_add_extent( | |||
612 | XFS_BTCUR_BPRV_WASDEL); | 628 | XFS_BTCUR_BPRV_WASDEL); |
613 | if ((error = xfs_bmap_add_extent_delay_real(ip, | 629 | if ((error = xfs_bmap_add_extent_delay_real(ip, |
614 | idx, &cur, new, &da_new, first, flist, | 630 | idx, &cur, new, &da_new, first, flist, |
615 | &logflags, rsvd))) | 631 | &logflags, delta, rsvd))) |
616 | goto done; | 632 | goto done; |
617 | } else if (new->br_state == XFS_EXT_NORM) { | 633 | } else if (new->br_state == XFS_EXT_NORM) { |
618 | ASSERT(new->br_state == XFS_EXT_NORM); | 634 | ASSERT(new->br_state == XFS_EXT_NORM); |
619 | if ((error = xfs_bmap_add_extent_unwritten_real( | 635 | if ((error = xfs_bmap_add_extent_unwritten_real( |
620 | ip, idx, &cur, new, &logflags))) | 636 | ip, idx, &cur, new, &logflags, delta))) |
621 | goto done; | 637 | goto done; |
622 | } else { | 638 | } else { |
623 | ASSERT(new->br_state == XFS_EXT_UNWRITTEN); | 639 | ASSERT(new->br_state == XFS_EXT_UNWRITTEN); |
624 | if ((error = xfs_bmap_add_extent_unwritten_real( | 640 | if ((error = xfs_bmap_add_extent_unwritten_real( |
625 | ip, idx, &cur, new, &logflags))) | 641 | ip, idx, &cur, new, &logflags, delta))) |
626 | goto done; | 642 | goto done; |
627 | } | 643 | } |
628 | ASSERT(*curp == cur || *curp == NULL); | 644 | ASSERT(*curp == cur || *curp == NULL); |
@@ -635,7 +651,7 @@ xfs_bmap_add_extent( | |||
635 | ASSERT((cur->bc_private.b.flags & | 651 | ASSERT((cur->bc_private.b.flags & |
636 | XFS_BTCUR_BPRV_WASDEL) == 0); | 652 | XFS_BTCUR_BPRV_WASDEL) == 0); |
637 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, | 653 | if ((error = xfs_bmap_add_extent_hole_real(ip, idx, cur, |
638 | new, &logflags, whichfork))) | 654 | new, &logflags, delta, whichfork))) |
639 | goto done; | 655 | goto done; |
640 | } | 656 | } |
641 | } | 657 | } |
@@ -700,6 +716,7 @@ xfs_bmap_add_extent_delay_real( | |||
700 | xfs_fsblock_t *first, /* pointer to firstblock variable */ | 716 | xfs_fsblock_t *first, /* pointer to firstblock variable */ |
701 | xfs_bmap_free_t *flist, /* list of extents to be freed */ | 717 | xfs_bmap_free_t *flist, /* list of extents to be freed */ |
702 | int *logflagsp, /* inode logging flags */ | 718 | int *logflagsp, /* inode logging flags */ |
719 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
703 | int rsvd) /* OK to use reserved data block allocation */ | 720 | int rsvd) /* OK to use reserved data block allocation */ |
704 | { | 721 | { |
705 | xfs_btree_cur_t *cur; /* btree cursor */ | 722 | xfs_btree_cur_t *cur; /* btree cursor */ |
@@ -716,8 +733,8 @@ xfs_bmap_add_extent_delay_real( | |||
716 | /* left is 0, right is 1, prev is 2 */ | 733 | /* left is 0, right is 1, prev is 2 */ |
717 | int rval=0; /* return value (logging flags) */ | 734 | int rval=0; /* return value (logging flags) */ |
718 | int state = 0;/* state bits, accessed thru macros */ | 735 | int state = 0;/* state bits, accessed thru macros */ |
719 | xfs_filblks_t temp; /* value for dnew calculations */ | 736 | xfs_filblks_t temp=0; /* value for dnew calculations */ |
720 | xfs_filblks_t temp2; /* value for dnew calculations */ | 737 | xfs_filblks_t temp2=0;/* value for dnew calculations */ |
721 | int tmp_rval; /* partial logging flags */ | 738 | int tmp_rval; /* partial logging flags */ |
722 | enum { /* bit number definitions for state */ | 739 | enum { /* bit number definitions for state */ |
723 | LEFT_CONTIG, RIGHT_CONTIG, | 740 | LEFT_CONTIG, RIGHT_CONTIG, |
@@ -839,6 +856,11 @@ xfs_bmap_add_extent_delay_real( | |||
839 | goto done; | 856 | goto done; |
840 | } | 857 | } |
841 | *dnew = 0; | 858 | *dnew = 0; |
859 | /* DELTA: Three in-core extents are replaced by one. */ | ||
860 | temp = LEFT.br_startoff; | ||
861 | temp2 = LEFT.br_blockcount + | ||
862 | PREV.br_blockcount + | ||
863 | RIGHT.br_blockcount; | ||
842 | break; | 864 | break; |
843 | 865 | ||
844 | case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): | 866 | case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): |
@@ -872,6 +894,10 @@ xfs_bmap_add_extent_delay_real( | |||
872 | goto done; | 894 | goto done; |
873 | } | 895 | } |
874 | *dnew = 0; | 896 | *dnew = 0; |
897 | /* DELTA: Two in-core extents are replaced by one. */ | ||
898 | temp = LEFT.br_startoff; | ||
899 | temp2 = LEFT.br_blockcount + | ||
900 | PREV.br_blockcount; | ||
875 | break; | 901 | break; |
876 | 902 | ||
877 | case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): | 903 | case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): |
@@ -906,6 +932,10 @@ xfs_bmap_add_extent_delay_real( | |||
906 | goto done; | 932 | goto done; |
907 | } | 933 | } |
908 | *dnew = 0; | 934 | *dnew = 0; |
935 | /* DELTA: Two in-core extents are replaced by one. */ | ||
936 | temp = PREV.br_startoff; | ||
937 | temp2 = PREV.br_blockcount + | ||
938 | RIGHT.br_blockcount; | ||
909 | break; | 939 | break; |
910 | 940 | ||
911 | case MASK2(LEFT_FILLING, RIGHT_FILLING): | 941 | case MASK2(LEFT_FILLING, RIGHT_FILLING): |
@@ -936,6 +966,9 @@ xfs_bmap_add_extent_delay_real( | |||
936 | ASSERT(i == 1); | 966 | ASSERT(i == 1); |
937 | } | 967 | } |
938 | *dnew = 0; | 968 | *dnew = 0; |
969 | /* DELTA: The in-core extent described by new changed type. */ | ||
970 | temp = new->br_startoff; | ||
971 | temp2 = new->br_blockcount; | ||
939 | break; | 972 | break; |
940 | 973 | ||
941 | case MASK2(LEFT_FILLING, LEFT_CONTIG): | 974 | case MASK2(LEFT_FILLING, LEFT_CONTIG): |
@@ -978,6 +1011,10 @@ xfs_bmap_add_extent_delay_real( | |||
978 | xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx, | 1011 | xfs_bmap_trace_post_update(fname, "LF|LC", ip, idx, |
979 | XFS_DATA_FORK); | 1012 | XFS_DATA_FORK); |
980 | *dnew = temp; | 1013 | *dnew = temp; |
1014 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1015 | temp = LEFT.br_startoff; | ||
1016 | temp2 = LEFT.br_blockcount + | ||
1017 | PREV.br_blockcount; | ||
981 | break; | 1018 | break; |
982 | 1019 | ||
983 | case MASK(LEFT_FILLING): | 1020 | case MASK(LEFT_FILLING): |
@@ -1025,6 +1062,9 @@ xfs_bmap_add_extent_delay_real( | |||
1025 | xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1, | 1062 | xfs_bmap_trace_post_update(fname, "LF", ip, idx + 1, |
1026 | XFS_DATA_FORK); | 1063 | XFS_DATA_FORK); |
1027 | *dnew = temp; | 1064 | *dnew = temp; |
1065 | /* DELTA: One in-core extent is split in two. */ | ||
1066 | temp = PREV.br_startoff; | ||
1067 | temp2 = PREV.br_blockcount; | ||
1028 | break; | 1068 | break; |
1029 | 1069 | ||
1030 | case MASK2(RIGHT_FILLING, RIGHT_CONTIG): | 1070 | case MASK2(RIGHT_FILLING, RIGHT_CONTIG): |
@@ -1067,6 +1107,10 @@ xfs_bmap_add_extent_delay_real( | |||
1067 | xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx, | 1107 | xfs_bmap_trace_post_update(fname, "RF|RC", ip, idx, |
1068 | XFS_DATA_FORK); | 1108 | XFS_DATA_FORK); |
1069 | *dnew = temp; | 1109 | *dnew = temp; |
1110 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1111 | temp = PREV.br_startoff; | ||
1112 | temp2 = PREV.br_blockcount + | ||
1113 | RIGHT.br_blockcount; | ||
1070 | break; | 1114 | break; |
1071 | 1115 | ||
1072 | case MASK(RIGHT_FILLING): | 1116 | case MASK(RIGHT_FILLING): |
@@ -1112,6 +1156,9 @@ xfs_bmap_add_extent_delay_real( | |||
1112 | xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); | 1156 | xfs_bmbt_set_startblock(ep, NULLSTARTBLOCK((int)temp)); |
1113 | xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); | 1157 | xfs_bmap_trace_post_update(fname, "RF", ip, idx, XFS_DATA_FORK); |
1114 | *dnew = temp; | 1158 | *dnew = temp; |
1159 | /* DELTA: One in-core extent is split in two. */ | ||
1160 | temp = PREV.br_startoff; | ||
1161 | temp2 = PREV.br_blockcount; | ||
1115 | break; | 1162 | break; |
1116 | 1163 | ||
1117 | case 0: | 1164 | case 0: |
@@ -1194,6 +1241,9 @@ xfs_bmap_add_extent_delay_real( | |||
1194 | xfs_bmap_trace_post_update(fname, "0", ip, idx + 2, | 1241 | xfs_bmap_trace_post_update(fname, "0", ip, idx + 2, |
1195 | XFS_DATA_FORK); | 1242 | XFS_DATA_FORK); |
1196 | *dnew = temp + temp2; | 1243 | *dnew = temp + temp2; |
1244 | /* DELTA: One in-core extent is split in three. */ | ||
1245 | temp = PREV.br_startoff; | ||
1246 | temp2 = PREV.br_blockcount; | ||
1197 | break; | 1247 | break; |
1198 | 1248 | ||
1199 | case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): | 1249 | case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): |
@@ -1209,6 +1259,13 @@ xfs_bmap_add_extent_delay_real( | |||
1209 | ASSERT(0); | 1259 | ASSERT(0); |
1210 | } | 1260 | } |
1211 | *curp = cur; | 1261 | *curp = cur; |
1262 | if (delta) { | ||
1263 | temp2 += temp; | ||
1264 | if (delta->xed_startoff > temp) | ||
1265 | delta->xed_startoff = temp; | ||
1266 | if (delta->xed_blockcount < temp2) | ||
1267 | delta->xed_blockcount = temp2; | ||
1268 | } | ||
1212 | done: | 1269 | done: |
1213 | *logflagsp = rval; | 1270 | *logflagsp = rval; |
1214 | return error; | 1271 | return error; |
@@ -1235,7 +1292,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
1235 | xfs_extnum_t idx, /* extent number to update/insert */ | 1292 | xfs_extnum_t idx, /* extent number to update/insert */ |
1236 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ | 1293 | xfs_btree_cur_t **curp, /* if *curp is null, not a btree */ |
1237 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1294 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1238 | int *logflagsp) /* inode logging flags */ | 1295 | int *logflagsp, /* inode logging flags */ |
1296 | xfs_extdelta_t *delta) /* Change made to incore extents */ | ||
1239 | { | 1297 | { |
1240 | xfs_btree_cur_t *cur; /* btree cursor */ | 1298 | xfs_btree_cur_t *cur; /* btree cursor */ |
1241 | xfs_bmbt_rec_t *ep; /* extent entry for idx */ | 1299 | xfs_bmbt_rec_t *ep; /* extent entry for idx */ |
@@ -1252,6 +1310,8 @@ xfs_bmap_add_extent_unwritten_real( | |||
1252 | /* left is 0, right is 1, prev is 2 */ | 1310 | /* left is 0, right is 1, prev is 2 */ |
1253 | int rval=0; /* return value (logging flags) */ | 1311 | int rval=0; /* return value (logging flags) */ |
1254 | int state = 0;/* state bits, accessed thru macros */ | 1312 | int state = 0;/* state bits, accessed thru macros */ |
1313 | xfs_filblks_t temp=0; | ||
1314 | xfs_filblks_t temp2=0; | ||
1255 | enum { /* bit number definitions for state */ | 1315 | enum { /* bit number definitions for state */ |
1256 | LEFT_CONTIG, RIGHT_CONTIG, | 1316 | LEFT_CONTIG, RIGHT_CONTIG, |
1257 | LEFT_FILLING, RIGHT_FILLING, | 1317 | LEFT_FILLING, RIGHT_FILLING, |
@@ -1380,6 +1440,11 @@ xfs_bmap_add_extent_unwritten_real( | |||
1380 | RIGHT.br_blockcount, LEFT.br_state))) | 1440 | RIGHT.br_blockcount, LEFT.br_state))) |
1381 | goto done; | 1441 | goto done; |
1382 | } | 1442 | } |
1443 | /* DELTA: Three in-core extents are replaced by one. */ | ||
1444 | temp = LEFT.br_startoff; | ||
1445 | temp2 = LEFT.br_blockcount + | ||
1446 | PREV.br_blockcount + | ||
1447 | RIGHT.br_blockcount; | ||
1383 | break; | 1448 | break; |
1384 | 1449 | ||
1385 | case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): | 1450 | case MASK3(LEFT_FILLING, RIGHT_FILLING, LEFT_CONTIG): |
@@ -1419,6 +1484,10 @@ xfs_bmap_add_extent_unwritten_real( | |||
1419 | LEFT.br_state))) | 1484 | LEFT.br_state))) |
1420 | goto done; | 1485 | goto done; |
1421 | } | 1486 | } |
1487 | /* DELTA: Two in-core extents are replaced by one. */ | ||
1488 | temp = LEFT.br_startoff; | ||
1489 | temp2 = LEFT.br_blockcount + | ||
1490 | PREV.br_blockcount; | ||
1422 | break; | 1491 | break; |
1423 | 1492 | ||
1424 | case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): | 1493 | case MASK3(LEFT_FILLING, RIGHT_FILLING, RIGHT_CONTIG): |
@@ -1459,6 +1528,10 @@ xfs_bmap_add_extent_unwritten_real( | |||
1459 | newext))) | 1528 | newext))) |
1460 | goto done; | 1529 | goto done; |
1461 | } | 1530 | } |
1531 | /* DELTA: Two in-core extents are replaced by one. */ | ||
1532 | temp = PREV.br_startoff; | ||
1533 | temp2 = PREV.br_blockcount + | ||
1534 | RIGHT.br_blockcount; | ||
1462 | break; | 1535 | break; |
1463 | 1536 | ||
1464 | case MASK2(LEFT_FILLING, RIGHT_FILLING): | 1537 | case MASK2(LEFT_FILLING, RIGHT_FILLING): |
@@ -1487,6 +1560,9 @@ xfs_bmap_add_extent_unwritten_real( | |||
1487 | newext))) | 1560 | newext))) |
1488 | goto done; | 1561 | goto done; |
1489 | } | 1562 | } |
1563 | /* DELTA: The in-core extent described by new changed type. */ | ||
1564 | temp = new->br_startoff; | ||
1565 | temp2 = new->br_blockcount; | ||
1490 | break; | 1566 | break; |
1491 | 1567 | ||
1492 | case MASK2(LEFT_FILLING, LEFT_CONTIG): | 1568 | case MASK2(LEFT_FILLING, LEFT_CONTIG): |
@@ -1534,6 +1610,10 @@ xfs_bmap_add_extent_unwritten_real( | |||
1534 | LEFT.br_state)) | 1610 | LEFT.br_state)) |
1535 | goto done; | 1611 | goto done; |
1536 | } | 1612 | } |
1613 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1614 | temp = LEFT.br_startoff; | ||
1615 | temp2 = LEFT.br_blockcount + | ||
1616 | PREV.br_blockcount; | ||
1537 | break; | 1617 | break; |
1538 | 1618 | ||
1539 | case MASK(LEFT_FILLING): | 1619 | case MASK(LEFT_FILLING): |
@@ -1574,6 +1654,9 @@ xfs_bmap_add_extent_unwritten_real( | |||
1574 | goto done; | 1654 | goto done; |
1575 | ASSERT(i == 1); | 1655 | ASSERT(i == 1); |
1576 | } | 1656 | } |
1657 | /* DELTA: One in-core extent is split in two. */ | ||
1658 | temp = PREV.br_startoff; | ||
1659 | temp2 = PREV.br_blockcount; | ||
1577 | break; | 1660 | break; |
1578 | 1661 | ||
1579 | case MASK2(RIGHT_FILLING, RIGHT_CONTIG): | 1662 | case MASK2(RIGHT_FILLING, RIGHT_CONTIG): |
@@ -1617,6 +1700,10 @@ xfs_bmap_add_extent_unwritten_real( | |||
1617 | newext))) | 1700 | newext))) |
1618 | goto done; | 1701 | goto done; |
1619 | } | 1702 | } |
1703 | /* DELTA: The boundary between two in-core extents moved. */ | ||
1704 | temp = PREV.br_startoff; | ||
1705 | temp2 = PREV.br_blockcount + | ||
1706 | RIGHT.br_blockcount; | ||
1620 | break; | 1707 | break; |
1621 | 1708 | ||
1622 | case MASK(RIGHT_FILLING): | 1709 | case MASK(RIGHT_FILLING): |
@@ -1657,6 +1744,9 @@ xfs_bmap_add_extent_unwritten_real( | |||
1657 | goto done; | 1744 | goto done; |
1658 | ASSERT(i == 1); | 1745 | ASSERT(i == 1); |
1659 | } | 1746 | } |
1747 | /* DELTA: One in-core extent is split in two. */ | ||
1748 | temp = PREV.br_startoff; | ||
1749 | temp2 = PREV.br_blockcount; | ||
1660 | break; | 1750 | break; |
1661 | 1751 | ||
1662 | case 0: | 1752 | case 0: |
@@ -1710,6 +1800,9 @@ xfs_bmap_add_extent_unwritten_real( | |||
1710 | goto done; | 1800 | goto done; |
1711 | ASSERT(i == 1); | 1801 | ASSERT(i == 1); |
1712 | } | 1802 | } |
1803 | /* DELTA: One in-core extent is split in three. */ | ||
1804 | temp = PREV.br_startoff; | ||
1805 | temp2 = PREV.br_blockcount; | ||
1713 | break; | 1806 | break; |
1714 | 1807 | ||
1715 | case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): | 1808 | case MASK3(LEFT_FILLING, LEFT_CONTIG, RIGHT_CONTIG): |
@@ -1725,6 +1818,13 @@ xfs_bmap_add_extent_unwritten_real( | |||
1725 | ASSERT(0); | 1818 | ASSERT(0); |
1726 | } | 1819 | } |
1727 | *curp = cur; | 1820 | *curp = cur; |
1821 | if (delta) { | ||
1822 | temp2 += temp; | ||
1823 | if (delta->xed_startoff > temp) | ||
1824 | delta->xed_startoff = temp; | ||
1825 | if (delta->xed_blockcount < temp2) | ||
1826 | delta->xed_blockcount = temp2; | ||
1827 | } | ||
1728 | done: | 1828 | done: |
1729 | *logflagsp = rval; | 1829 | *logflagsp = rval; |
1730 | return error; | 1830 | return error; |
@@ -1753,6 +1853,7 @@ xfs_bmap_add_extent_hole_delay( | |||
1753 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 1853 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
1754 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 1854 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1755 | int *logflagsp, /* inode logging flags */ | 1855 | int *logflagsp, /* inode logging flags */ |
1856 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
1756 | int rsvd) /* OK to allocate reserved blocks */ | 1857 | int rsvd) /* OK to allocate reserved blocks */ |
1757 | { | 1858 | { |
1758 | xfs_bmbt_rec_t *ep; /* extent record for idx */ | 1859 | xfs_bmbt_rec_t *ep; /* extent record for idx */ |
@@ -1765,7 +1866,8 @@ xfs_bmap_add_extent_hole_delay( | |||
1765 | xfs_filblks_t oldlen=0; /* old indirect size */ | 1866 | xfs_filblks_t oldlen=0; /* old indirect size */ |
1766 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ | 1867 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ |
1767 | int state; /* state bits, accessed thru macros */ | 1868 | int state; /* state bits, accessed thru macros */ |
1768 | xfs_filblks_t temp; /* temp for indirect calculations */ | 1869 | xfs_filblks_t temp=0; /* temp for indirect calculations */ |
1870 | xfs_filblks_t temp2=0; | ||
1769 | enum { /* bit number definitions for state */ | 1871 | enum { /* bit number definitions for state */ |
1770 | LEFT_CONTIG, RIGHT_CONTIG, | 1872 | LEFT_CONTIG, RIGHT_CONTIG, |
1771 | LEFT_DELAY, RIGHT_DELAY, | 1873 | LEFT_DELAY, RIGHT_DELAY, |
@@ -1844,6 +1946,9 @@ xfs_bmap_add_extent_hole_delay( | |||
1844 | XFS_DATA_FORK); | 1946 | XFS_DATA_FORK); |
1845 | xfs_iext_remove(ifp, idx, 1); | 1947 | xfs_iext_remove(ifp, idx, 1); |
1846 | ip->i_df.if_lastex = idx - 1; | 1948 | ip->i_df.if_lastex = idx - 1; |
1949 | /* DELTA: Two in-core extents were replaced by one. */ | ||
1950 | temp2 = temp; | ||
1951 | temp = left.br_startoff; | ||
1847 | break; | 1952 | break; |
1848 | 1953 | ||
1849 | case MASK(LEFT_CONTIG): | 1954 | case MASK(LEFT_CONTIG): |
@@ -1864,6 +1969,9 @@ xfs_bmap_add_extent_hole_delay( | |||
1864 | xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, | 1969 | xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, |
1865 | XFS_DATA_FORK); | 1970 | XFS_DATA_FORK); |
1866 | ip->i_df.if_lastex = idx - 1; | 1971 | ip->i_df.if_lastex = idx - 1; |
1972 | /* DELTA: One in-core extent grew into a hole. */ | ||
1973 | temp2 = temp; | ||
1974 | temp = left.br_startoff; | ||
1867 | break; | 1975 | break; |
1868 | 1976 | ||
1869 | case MASK(RIGHT_CONTIG): | 1977 | case MASK(RIGHT_CONTIG): |
@@ -1881,6 +1989,9 @@ xfs_bmap_add_extent_hole_delay( | |||
1881 | NULLSTARTBLOCK((int)newlen), temp, right.br_state); | 1989 | NULLSTARTBLOCK((int)newlen), temp, right.br_state); |
1882 | xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK); | 1990 | xfs_bmap_trace_post_update(fname, "RC", ip, idx, XFS_DATA_FORK); |
1883 | ip->i_df.if_lastex = idx; | 1991 | ip->i_df.if_lastex = idx; |
1992 | /* DELTA: One in-core extent grew into a hole. */ | ||
1993 | temp2 = temp; | ||
1994 | temp = new->br_startoff; | ||
1884 | break; | 1995 | break; |
1885 | 1996 | ||
1886 | case 0: | 1997 | case 0: |
@@ -1894,6 +2005,9 @@ xfs_bmap_add_extent_hole_delay( | |||
1894 | XFS_DATA_FORK); | 2005 | XFS_DATA_FORK); |
1895 | xfs_iext_insert(ifp, idx, 1, new); | 2006 | xfs_iext_insert(ifp, idx, 1, new); |
1896 | ip->i_df.if_lastex = idx; | 2007 | ip->i_df.if_lastex = idx; |
2008 | /* DELTA: A new in-core extent was added in a hole. */ | ||
2009 | temp2 = new->br_blockcount; | ||
2010 | temp = new->br_startoff; | ||
1897 | break; | 2011 | break; |
1898 | } | 2012 | } |
1899 | if (oldlen != newlen) { | 2013 | if (oldlen != newlen) { |
@@ -1904,6 +2018,13 @@ xfs_bmap_add_extent_hole_delay( | |||
1904 | * Nothing to do for disk quota accounting here. | 2018 | * Nothing to do for disk quota accounting here. |
1905 | */ | 2019 | */ |
1906 | } | 2020 | } |
2021 | if (delta) { | ||
2022 | temp2 += temp; | ||
2023 | if (delta->xed_startoff > temp) | ||
2024 | delta->xed_startoff = temp; | ||
2025 | if (delta->xed_blockcount < temp2) | ||
2026 | delta->xed_blockcount = temp2; | ||
2027 | } | ||
1907 | *logflagsp = 0; | 2028 | *logflagsp = 0; |
1908 | return 0; | 2029 | return 0; |
1909 | #undef MASK | 2030 | #undef MASK |
@@ -1925,6 +2046,7 @@ xfs_bmap_add_extent_hole_real( | |||
1925 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 2046 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
1926 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ | 2047 | xfs_bmbt_irec_t *new, /* new data to add to file extents */ |
1927 | int *logflagsp, /* inode logging flags */ | 2048 | int *logflagsp, /* inode logging flags */ |
2049 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
1928 | int whichfork) /* data or attr fork */ | 2050 | int whichfork) /* data or attr fork */ |
1929 | { | 2051 | { |
1930 | xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */ | 2052 | xfs_bmbt_rec_t *ep; /* pointer to extent entry ins. point */ |
@@ -1936,7 +2058,10 @@ xfs_bmap_add_extent_hole_real( | |||
1936 | xfs_ifork_t *ifp; /* inode fork pointer */ | 2058 | xfs_ifork_t *ifp; /* inode fork pointer */ |
1937 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ | 2059 | xfs_bmbt_irec_t left; /* left neighbor extent entry */ |
1938 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ | 2060 | xfs_bmbt_irec_t right; /* right neighbor extent entry */ |
2061 | int rval=0; /* return value (logging flags) */ | ||
1939 | int state; /* state bits, accessed thru macros */ | 2062 | int state; /* state bits, accessed thru macros */ |
2063 | xfs_filblks_t temp=0; | ||
2064 | xfs_filblks_t temp2=0; | ||
1940 | enum { /* bit number definitions for state */ | 2065 | enum { /* bit number definitions for state */ |
1941 | LEFT_CONTIG, RIGHT_CONTIG, | 2066 | LEFT_CONTIG, RIGHT_CONTIG, |
1942 | LEFT_DELAY, RIGHT_DELAY, | 2067 | LEFT_DELAY, RIGHT_DELAY, |
@@ -1993,6 +2118,7 @@ xfs_bmap_add_extent_hole_real( | |||
1993 | left.br_blockcount + new->br_blockcount + | 2118 | left.br_blockcount + new->br_blockcount + |
1994 | right.br_blockcount <= MAXEXTLEN)); | 2119 | right.br_blockcount <= MAXEXTLEN)); |
1995 | 2120 | ||
2121 | error = 0; | ||
1996 | /* | 2122 | /* |
1997 | * Select which case we're in here, and implement it. | 2123 | * Select which case we're in here, and implement it. |
1998 | */ | 2124 | */ |
@@ -2018,25 +2144,35 @@ xfs_bmap_add_extent_hole_real( | |||
2018 | XFS_IFORK_NEXT_SET(ip, whichfork, | 2144 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2019 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); | 2145 | XFS_IFORK_NEXTENTS(ip, whichfork) - 1); |
2020 | if (cur == NULL) { | 2146 | if (cur == NULL) { |
2021 | *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); | 2147 | rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); |
2022 | return 0; | 2148 | } else { |
2149 | rval = XFS_ILOG_CORE; | ||
2150 | if ((error = xfs_bmbt_lookup_eq(cur, | ||
2151 | right.br_startoff, | ||
2152 | right.br_startblock, | ||
2153 | right.br_blockcount, &i))) | ||
2154 | goto done; | ||
2155 | ASSERT(i == 1); | ||
2156 | if ((error = xfs_bmbt_delete(cur, &i))) | ||
2157 | goto done; | ||
2158 | ASSERT(i == 1); | ||
2159 | if ((error = xfs_bmbt_decrement(cur, 0, &i))) | ||
2160 | goto done; | ||
2161 | ASSERT(i == 1); | ||
2162 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | ||
2163 | left.br_startblock, | ||
2164 | left.br_blockcount + | ||
2165 | new->br_blockcount + | ||
2166 | right.br_blockcount, | ||
2167 | left.br_state))) | ||
2168 | goto done; | ||
2023 | } | 2169 | } |
2024 | *logflagsp = XFS_ILOG_CORE; | 2170 | /* DELTA: Two in-core extents were replaced by one. */ |
2025 | if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, | 2171 | temp = left.br_startoff; |
2026 | right.br_startblock, right.br_blockcount, &i))) | 2172 | temp2 = left.br_blockcount + |
2027 | return error; | 2173 | new->br_blockcount + |
2028 | ASSERT(i == 1); | 2174 | right.br_blockcount; |
2029 | if ((error = xfs_bmbt_delete(cur, &i))) | 2175 | break; |
2030 | return error; | ||
2031 | ASSERT(i == 1); | ||
2032 | if ((error = xfs_bmbt_decrement(cur, 0, &i))) | ||
2033 | return error; | ||
2034 | ASSERT(i == 1); | ||
2035 | error = xfs_bmbt_update(cur, left.br_startoff, | ||
2036 | left.br_startblock, | ||
2037 | left.br_blockcount + new->br_blockcount + | ||
2038 | right.br_blockcount, left.br_state); | ||
2039 | return error; | ||
2040 | 2176 | ||
2041 | case MASK(LEFT_CONTIG): | 2177 | case MASK(LEFT_CONTIG): |
2042 | /* | 2178 | /* |
@@ -2050,19 +2186,27 @@ xfs_bmap_add_extent_hole_real( | |||
2050 | xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork); | 2186 | xfs_bmap_trace_post_update(fname, "LC", ip, idx - 1, whichfork); |
2051 | ifp->if_lastex = idx - 1; | 2187 | ifp->if_lastex = idx - 1; |
2052 | if (cur == NULL) { | 2188 | if (cur == NULL) { |
2053 | *logflagsp = XFS_ILOG_FEXT(whichfork); | 2189 | rval = XFS_ILOG_FEXT(whichfork); |
2054 | return 0; | 2190 | } else { |
2191 | rval = 0; | ||
2192 | if ((error = xfs_bmbt_lookup_eq(cur, | ||
2193 | left.br_startoff, | ||
2194 | left.br_startblock, | ||
2195 | left.br_blockcount, &i))) | ||
2196 | goto done; | ||
2197 | ASSERT(i == 1); | ||
2198 | if ((error = xfs_bmbt_update(cur, left.br_startoff, | ||
2199 | left.br_startblock, | ||
2200 | left.br_blockcount + | ||
2201 | new->br_blockcount, | ||
2202 | left.br_state))) | ||
2203 | goto done; | ||
2055 | } | 2204 | } |
2056 | *logflagsp = 0; | 2205 | /* DELTA: One in-core extent grew. */ |
2057 | if ((error = xfs_bmbt_lookup_eq(cur, left.br_startoff, | 2206 | temp = left.br_startoff; |
2058 | left.br_startblock, left.br_blockcount, &i))) | 2207 | temp2 = left.br_blockcount + |
2059 | return error; | 2208 | new->br_blockcount; |
2060 | ASSERT(i == 1); | 2209 | break; |
2061 | error = xfs_bmbt_update(cur, left.br_startoff, | ||
2062 | left.br_startblock, | ||
2063 | left.br_blockcount + new->br_blockcount, | ||
2064 | left.br_state); | ||
2065 | return error; | ||
2066 | 2210 | ||
2067 | case MASK(RIGHT_CONTIG): | 2211 | case MASK(RIGHT_CONTIG): |
2068 | /* | 2212 | /* |
@@ -2077,19 +2221,27 @@ xfs_bmap_add_extent_hole_real( | |||
2077 | xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork); | 2221 | xfs_bmap_trace_post_update(fname, "RC", ip, idx, whichfork); |
2078 | ifp->if_lastex = idx; | 2222 | ifp->if_lastex = idx; |
2079 | if (cur == NULL) { | 2223 | if (cur == NULL) { |
2080 | *logflagsp = XFS_ILOG_FEXT(whichfork); | 2224 | rval = XFS_ILOG_FEXT(whichfork); |
2081 | return 0; | 2225 | } else { |
2226 | rval = 0; | ||
2227 | if ((error = xfs_bmbt_lookup_eq(cur, | ||
2228 | right.br_startoff, | ||
2229 | right.br_startblock, | ||
2230 | right.br_blockcount, &i))) | ||
2231 | goto done; | ||
2232 | ASSERT(i == 1); | ||
2233 | if ((error = xfs_bmbt_update(cur, new->br_startoff, | ||
2234 | new->br_startblock, | ||
2235 | new->br_blockcount + | ||
2236 | right.br_blockcount, | ||
2237 | right.br_state))) | ||
2238 | goto done; | ||
2082 | } | 2239 | } |
2083 | *logflagsp = 0; | 2240 | /* DELTA: One in-core extent grew. */ |
2084 | if ((error = xfs_bmbt_lookup_eq(cur, right.br_startoff, | 2241 | temp = new->br_startoff; |
2085 | right.br_startblock, right.br_blockcount, &i))) | 2242 | temp2 = new->br_blockcount + |
2086 | return error; | 2243 | right.br_blockcount; |
2087 | ASSERT(i == 1); | 2244 | break; |
2088 | error = xfs_bmbt_update(cur, new->br_startoff, | ||
2089 | new->br_startblock, | ||
2090 | new->br_blockcount + right.br_blockcount, | ||
2091 | right.br_state); | ||
2092 | return error; | ||
2093 | 2245 | ||
2094 | case 0: | 2246 | case 0: |
2095 | /* | 2247 | /* |
@@ -2104,29 +2256,41 @@ xfs_bmap_add_extent_hole_real( | |||
2104 | XFS_IFORK_NEXT_SET(ip, whichfork, | 2256 | XFS_IFORK_NEXT_SET(ip, whichfork, |
2105 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); | 2257 | XFS_IFORK_NEXTENTS(ip, whichfork) + 1); |
2106 | if (cur == NULL) { | 2258 | if (cur == NULL) { |
2107 | *logflagsp = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); | 2259 | rval = XFS_ILOG_CORE | XFS_ILOG_FEXT(whichfork); |
2108 | return 0; | 2260 | } else { |
2261 | rval = XFS_ILOG_CORE; | ||
2262 | if ((error = xfs_bmbt_lookup_eq(cur, | ||
2263 | new->br_startoff, | ||
2264 | new->br_startblock, | ||
2265 | new->br_blockcount, &i))) | ||
2266 | goto done; | ||
2267 | ASSERT(i == 0); | ||
2268 | cur->bc_rec.b.br_state = new->br_state; | ||
2269 | if ((error = xfs_bmbt_insert(cur, &i))) | ||
2270 | goto done; | ||
2271 | ASSERT(i == 1); | ||
2109 | } | 2272 | } |
2110 | *logflagsp = XFS_ILOG_CORE; | 2273 | /* DELTA: A new extent was added in a hole. */ |
2111 | if ((error = xfs_bmbt_lookup_eq(cur, new->br_startoff, | 2274 | temp = new->br_startoff; |
2112 | new->br_startblock, new->br_blockcount, &i))) | 2275 | temp2 = new->br_blockcount; |
2113 | return error; | 2276 | break; |
2114 | ASSERT(i == 0); | 2277 | } |
2115 | cur->bc_rec.b.br_state = new->br_state; | 2278 | if (delta) { |
2116 | if ((error = xfs_bmbt_insert(cur, &i))) | 2279 | temp2 += temp; |
2117 | return error; | 2280 | if (delta->xed_startoff > temp) |
2118 | ASSERT(i == 1); | 2281 | delta->xed_startoff = temp; |
2119 | return 0; | 2282 | if (delta->xed_blockcount < temp2) |
2283 | delta->xed_blockcount = temp2; | ||
2120 | } | 2284 | } |
2285 | done: | ||
2286 | *logflagsp = rval; | ||
2287 | return error; | ||
2121 | #undef MASK | 2288 | #undef MASK |
2122 | #undef MASK2 | 2289 | #undef MASK2 |
2123 | #undef STATE_SET | 2290 | #undef STATE_SET |
2124 | #undef STATE_TEST | 2291 | #undef STATE_TEST |
2125 | #undef STATE_SET_TEST | 2292 | #undef STATE_SET_TEST |
2126 | #undef SWITCH_STATE | 2293 | #undef SWITCH_STATE |
2127 | /* NOTREACHED */ | ||
2128 | ASSERT(0); | ||
2129 | return 0; /* keep gcc quite */ | ||
2130 | } | 2294 | } |
2131 | 2295 | ||
2132 | /* | 2296 | /* |
@@ -2598,6 +2762,7 @@ xfs_bmap_btalloc( | |||
2598 | args.mp = mp; | 2762 | args.mp = mp; |
2599 | args.fsbno = ap->rval; | 2763 | args.fsbno = ap->rval; |
2600 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); | 2764 | args.maxlen = MIN(ap->alen, mp->m_sb.sb_agblocks); |
2765 | args.firstblock = ap->firstblock; | ||
2601 | blen = 0; | 2766 | blen = 0; |
2602 | if (nullfb) { | 2767 | if (nullfb) { |
2603 | args.type = XFS_ALLOCTYPE_START_BNO; | 2768 | args.type = XFS_ALLOCTYPE_START_BNO; |
@@ -2657,7 +2822,7 @@ xfs_bmap_btalloc( | |||
2657 | else | 2822 | else |
2658 | args.minlen = ap->alen; | 2823 | args.minlen = ap->alen; |
2659 | } else if (ap->low) { | 2824 | } else if (ap->low) { |
2660 | args.type = XFS_ALLOCTYPE_FIRST_AG; | 2825 | args.type = XFS_ALLOCTYPE_START_BNO; |
2661 | args.total = args.minlen = ap->minlen; | 2826 | args.total = args.minlen = ap->minlen; |
2662 | } else { | 2827 | } else { |
2663 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 2828 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
@@ -2669,7 +2834,7 @@ xfs_bmap_btalloc( | |||
2669 | args.prod = ap->ip->i_d.di_extsize; | 2834 | args.prod = ap->ip->i_d.di_extsize; |
2670 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) | 2835 | if ((args.mod = (xfs_extlen_t)do_mod(ap->off, args.prod))) |
2671 | args.mod = (xfs_extlen_t)(args.prod - args.mod); | 2836 | args.mod = (xfs_extlen_t)(args.prod - args.mod); |
2672 | } else if (unlikely(mp->m_sb.sb_blocksize >= NBPP)) { | 2837 | } else if (mp->m_sb.sb_blocksize >= NBPP) { |
2673 | args.prod = 1; | 2838 | args.prod = 1; |
2674 | args.mod = 0; | 2839 | args.mod = 0; |
2675 | } else { | 2840 | } else { |
@@ -2885,6 +3050,7 @@ xfs_bmap_del_extent( | |||
2885 | xfs_btree_cur_t *cur, /* if null, not a btree */ | 3050 | xfs_btree_cur_t *cur, /* if null, not a btree */ |
2886 | xfs_bmbt_irec_t *del, /* data to remove from extents */ | 3051 | xfs_bmbt_irec_t *del, /* data to remove from extents */ |
2887 | int *logflagsp, /* inode logging flags */ | 3052 | int *logflagsp, /* inode logging flags */ |
3053 | xfs_extdelta_t *delta, /* Change made to incore extents */ | ||
2888 | int whichfork, /* data or attr fork */ | 3054 | int whichfork, /* data or attr fork */ |
2889 | int rsvd) /* OK to allocate reserved blocks */ | 3055 | int rsvd) /* OK to allocate reserved blocks */ |
2890 | { | 3056 | { |
@@ -3193,6 +3359,14 @@ xfs_bmap_del_extent( | |||
3193 | if (da_old > da_new) | 3359 | if (da_old > da_new) |
3194 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new), | 3360 | xfs_mod_incore_sb(mp, XFS_SBS_FDBLOCKS, (int)(da_old - da_new), |
3195 | rsvd); | 3361 | rsvd); |
3362 | if (delta) { | ||
3363 | /* DELTA: report the original extent. */ | ||
3364 | if (delta->xed_startoff > got.br_startoff) | ||
3365 | delta->xed_startoff = got.br_startoff; | ||
3366 | if (delta->xed_blockcount < got.br_startoff+got.br_blockcount) | ||
3367 | delta->xed_blockcount = got.br_startoff + | ||
3368 | got.br_blockcount; | ||
3369 | } | ||
3196 | done: | 3370 | done: |
3197 | *logflagsp = flags; | 3371 | *logflagsp = flags; |
3198 | return error; | 3372 | return error; |
@@ -3279,6 +3453,7 @@ xfs_bmap_extents_to_btree( | |||
3279 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); | 3453 | XFS_IFORK_FMT_SET(ip, whichfork, XFS_DINODE_FMT_BTREE); |
3280 | args.tp = tp; | 3454 | args.tp = tp; |
3281 | args.mp = mp; | 3455 | args.mp = mp; |
3456 | args.firstblock = *firstblock; | ||
3282 | if (*firstblock == NULLFSBLOCK) { | 3457 | if (*firstblock == NULLFSBLOCK) { |
3283 | args.type = XFS_ALLOCTYPE_START_BNO; | 3458 | args.type = XFS_ALLOCTYPE_START_BNO; |
3284 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); | 3459 | args.fsbno = XFS_INO_TO_FSB(mp, ip->i_ino); |
@@ -3414,6 +3589,7 @@ xfs_bmap_local_to_extents( | |||
3414 | 3589 | ||
3415 | args.tp = tp; | 3590 | args.tp = tp; |
3416 | args.mp = ip->i_mount; | 3591 | args.mp = ip->i_mount; |
3592 | args.firstblock = *firstblock; | ||
3417 | ASSERT((ifp->if_flags & | 3593 | ASSERT((ifp->if_flags & |
3418 | (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); | 3594 | (XFS_IFINLINE|XFS_IFEXTENTS|XFS_IFEXTIREC)) == XFS_IFINLINE); |
3419 | /* | 3595 | /* |
@@ -3753,7 +3929,7 @@ xfs_bunmap_trace( | |||
3753 | if (ip->i_rwtrace == NULL) | 3929 | if (ip->i_rwtrace == NULL) |
3754 | return; | 3930 | return; |
3755 | ktrace_enter(ip->i_rwtrace, | 3931 | ktrace_enter(ip->i_rwtrace, |
3756 | (void *)(__psint_t)XFS_BUNMAPI, | 3932 | (void *)(__psint_t)XFS_BUNMAP, |
3757 | (void *)ip, | 3933 | (void *)ip, |
3758 | (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff), | 3934 | (void *)(__psint_t)((ip->i_d.di_size >> 32) & 0xffffffff), |
3759 | (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff), | 3935 | (void *)(__psint_t)(ip->i_d.di_size & 0xffffffff), |
@@ -4087,8 +4263,8 @@ xfs_bmap_finish( | |||
4087 | if (!XFS_FORCED_SHUTDOWN(mp)) | 4263 | if (!XFS_FORCED_SHUTDOWN(mp)) |
4088 | xfs_force_shutdown(mp, | 4264 | xfs_force_shutdown(mp, |
4089 | (error == EFSCORRUPTED) ? | 4265 | (error == EFSCORRUPTED) ? |
4090 | XFS_CORRUPT_INCORE : | 4266 | SHUTDOWN_CORRUPT_INCORE : |
4091 | XFS_METADATA_IO_ERROR); | 4267 | SHUTDOWN_META_IO_ERROR); |
4092 | return error; | 4268 | return error; |
4093 | } | 4269 | } |
4094 | xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock, | 4270 | xfs_trans_log_efd_extent(ntp, efd, free->xbfi_startblock, |
@@ -4538,7 +4714,8 @@ xfs_bmapi( | |||
4538 | xfs_extlen_t total, /* total blocks needed */ | 4714 | xfs_extlen_t total, /* total blocks needed */ |
4539 | xfs_bmbt_irec_t *mval, /* output: map values */ | 4715 | xfs_bmbt_irec_t *mval, /* output: map values */ |
4540 | int *nmap, /* i/o: mval size/count */ | 4716 | int *nmap, /* i/o: mval size/count */ |
4541 | xfs_bmap_free_t *flist) /* i/o: list extents to free */ | 4717 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
4718 | xfs_extdelta_t *delta) /* o: change made to incore extents */ | ||
4542 | { | 4719 | { |
4543 | xfs_fsblock_t abno; /* allocated block number */ | 4720 | xfs_fsblock_t abno; /* allocated block number */ |
4544 | xfs_extlen_t alen; /* allocated extent length */ | 4721 | xfs_extlen_t alen; /* allocated extent length */ |
@@ -4650,6 +4827,10 @@ xfs_bmapi( | |||
4650 | end = bno + len; | 4827 | end = bno + len; |
4651 | obno = bno; | 4828 | obno = bno; |
4652 | bma.ip = NULL; | 4829 | bma.ip = NULL; |
4830 | if (delta) { | ||
4831 | delta->xed_startoff = NULLFILEOFF; | ||
4832 | delta->xed_blockcount = 0; | ||
4833 | } | ||
4653 | while (bno < end && n < *nmap) { | 4834 | while (bno < end && n < *nmap) { |
4654 | /* | 4835 | /* |
4655 | * Reading past eof, act as though there's a hole | 4836 | * Reading past eof, act as though there's a hole |
@@ -4886,8 +5067,8 @@ xfs_bmapi( | |||
4886 | got.br_state = XFS_EXT_UNWRITTEN; | 5067 | got.br_state = XFS_EXT_UNWRITTEN; |
4887 | } | 5068 | } |
4888 | error = xfs_bmap_add_extent(ip, lastx, &cur, &got, | 5069 | error = xfs_bmap_add_extent(ip, lastx, &cur, &got, |
4889 | firstblock, flist, &tmp_logflags, whichfork, | 5070 | firstblock, flist, &tmp_logflags, delta, |
4890 | (flags & XFS_BMAPI_RSVBLOCKS)); | 5071 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); |
4891 | logflags |= tmp_logflags; | 5072 | logflags |= tmp_logflags; |
4892 | if (error) | 5073 | if (error) |
4893 | goto error0; | 5074 | goto error0; |
@@ -4983,8 +5164,8 @@ xfs_bmapi( | |||
4983 | } | 5164 | } |
4984 | mval->br_state = XFS_EXT_NORM; | 5165 | mval->br_state = XFS_EXT_NORM; |
4985 | error = xfs_bmap_add_extent(ip, lastx, &cur, mval, | 5166 | error = xfs_bmap_add_extent(ip, lastx, &cur, mval, |
4986 | firstblock, flist, &tmp_logflags, whichfork, | 5167 | firstblock, flist, &tmp_logflags, delta, |
4987 | (flags & XFS_BMAPI_RSVBLOCKS)); | 5168 | whichfork, (flags & XFS_BMAPI_RSVBLOCKS)); |
4988 | logflags |= tmp_logflags; | 5169 | logflags |= tmp_logflags; |
4989 | if (error) | 5170 | if (error) |
4990 | goto error0; | 5171 | goto error0; |
@@ -5073,7 +5254,14 @@ xfs_bmapi( | |||
5073 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || | 5254 | ASSERT(XFS_IFORK_FORMAT(ip, whichfork) != XFS_DINODE_FMT_BTREE || |
5074 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); | 5255 | XFS_IFORK_NEXTENTS(ip, whichfork) > ifp->if_ext_max); |
5075 | error = 0; | 5256 | error = 0; |
5076 | 5257 | if (delta && delta->xed_startoff != NULLFILEOFF) { | |
5258 | /* A change was actually made. | ||
5259 | * Note that delta->xed_blockount is an offset at this | ||
5260 | * point and needs to be converted to a block count. | ||
5261 | */ | ||
5262 | ASSERT(delta->xed_blockcount > delta->xed_startoff); | ||
5263 | delta->xed_blockcount -= delta->xed_startoff; | ||
5264 | } | ||
5077 | error0: | 5265 | error0: |
5078 | /* | 5266 | /* |
5079 | * Log everything. Do this after conversion, there's no point in | 5267 | * Log everything. Do this after conversion, there's no point in |
@@ -5185,6 +5373,8 @@ xfs_bunmapi( | |||
5185 | xfs_fsblock_t *firstblock, /* first allocated block | 5373 | xfs_fsblock_t *firstblock, /* first allocated block |
5186 | controls a.g. for allocs */ | 5374 | controls a.g. for allocs */ |
5187 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 5375 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
5376 | xfs_extdelta_t *delta, /* o: change made to incore | ||
5377 | extents */ | ||
5188 | int *done) /* set if not done yet */ | 5378 | int *done) /* set if not done yet */ |
5189 | { | 5379 | { |
5190 | xfs_btree_cur_t *cur; /* bmap btree cursor */ | 5380 | xfs_btree_cur_t *cur; /* bmap btree cursor */ |
@@ -5242,6 +5432,10 @@ xfs_bunmapi( | |||
5242 | bno = start + len - 1; | 5432 | bno = start + len - 1; |
5243 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, | 5433 | ep = xfs_bmap_search_extents(ip, bno, whichfork, &eof, &lastx, &got, |
5244 | &prev); | 5434 | &prev); |
5435 | if (delta) { | ||
5436 | delta->xed_startoff = NULLFILEOFF; | ||
5437 | delta->xed_blockcount = 0; | ||
5438 | } | ||
5245 | /* | 5439 | /* |
5246 | * Check to see if the given block number is past the end of the | 5440 | * Check to see if the given block number is past the end of the |
5247 | * file, back up to the last block if so... | 5441 | * file, back up to the last block if so... |
@@ -5340,7 +5534,8 @@ xfs_bunmapi( | |||
5340 | } | 5534 | } |
5341 | del.br_state = XFS_EXT_UNWRITTEN; | 5535 | del.br_state = XFS_EXT_UNWRITTEN; |
5342 | error = xfs_bmap_add_extent(ip, lastx, &cur, &del, | 5536 | error = xfs_bmap_add_extent(ip, lastx, &cur, &del, |
5343 | firstblock, flist, &logflags, XFS_DATA_FORK, 0); | 5537 | firstblock, flist, &logflags, delta, |
5538 | XFS_DATA_FORK, 0); | ||
5344 | if (error) | 5539 | if (error) |
5345 | goto error0; | 5540 | goto error0; |
5346 | goto nodelete; | 5541 | goto nodelete; |
@@ -5394,7 +5589,7 @@ xfs_bunmapi( | |||
5394 | prev.br_state = XFS_EXT_UNWRITTEN; | 5589 | prev.br_state = XFS_EXT_UNWRITTEN; |
5395 | error = xfs_bmap_add_extent(ip, lastx - 1, &cur, | 5590 | error = xfs_bmap_add_extent(ip, lastx - 1, &cur, |
5396 | &prev, firstblock, flist, &logflags, | 5591 | &prev, firstblock, flist, &logflags, |
5397 | XFS_DATA_FORK, 0); | 5592 | delta, XFS_DATA_FORK, 0); |
5398 | if (error) | 5593 | if (error) |
5399 | goto error0; | 5594 | goto error0; |
5400 | goto nodelete; | 5595 | goto nodelete; |
@@ -5403,7 +5598,7 @@ xfs_bunmapi( | |||
5403 | del.br_state = XFS_EXT_UNWRITTEN; | 5598 | del.br_state = XFS_EXT_UNWRITTEN; |
5404 | error = xfs_bmap_add_extent(ip, lastx, &cur, | 5599 | error = xfs_bmap_add_extent(ip, lastx, &cur, |
5405 | &del, firstblock, flist, &logflags, | 5600 | &del, firstblock, flist, &logflags, |
5406 | XFS_DATA_FORK, 0); | 5601 | delta, XFS_DATA_FORK, 0); |
5407 | if (error) | 5602 | if (error) |
5408 | goto error0; | 5603 | goto error0; |
5409 | goto nodelete; | 5604 | goto nodelete; |
@@ -5456,7 +5651,7 @@ xfs_bunmapi( | |||
5456 | goto error0; | 5651 | goto error0; |
5457 | } | 5652 | } |
5458 | error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, | 5653 | error = xfs_bmap_del_extent(ip, tp, lastx, flist, cur, &del, |
5459 | &tmp_logflags, whichfork, rsvd); | 5654 | &tmp_logflags, delta, whichfork, rsvd); |
5460 | logflags |= tmp_logflags; | 5655 | logflags |= tmp_logflags; |
5461 | if (error) | 5656 | if (error) |
5462 | goto error0; | 5657 | goto error0; |
@@ -5513,6 +5708,14 @@ nodelete: | |||
5513 | ASSERT(ifp->if_ext_max == | 5708 | ASSERT(ifp->if_ext_max == |
5514 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); | 5709 | XFS_IFORK_SIZE(ip, whichfork) / (uint)sizeof(xfs_bmbt_rec_t)); |
5515 | error = 0; | 5710 | error = 0; |
5711 | if (delta && delta->xed_startoff != NULLFILEOFF) { | ||
5712 | /* A change was actually made. | ||
5713 | * Note that delta->xed_blockount is an offset at this | ||
5714 | * point and needs to be converted to a block count. | ||
5715 | */ | ||
5716 | ASSERT(delta->xed_blockcount > delta->xed_startoff); | ||
5717 | delta->xed_blockcount -= delta->xed_startoff; | ||
5718 | } | ||
5516 | error0: | 5719 | error0: |
5517 | /* | 5720 | /* |
5518 | * Log everything. Do this after conversion, there's no point in | 5721 | * Log everything. Do this after conversion, there's no point in |
@@ -5556,7 +5759,7 @@ xfs_getbmap( | |||
5556 | __int64_t fixlen; /* length for -1 case */ | 5759 | __int64_t fixlen; /* length for -1 case */ |
5557 | int i; /* extent number */ | 5760 | int i; /* extent number */ |
5558 | xfs_inode_t *ip; /* xfs incore inode pointer */ | 5761 | xfs_inode_t *ip; /* xfs incore inode pointer */ |
5559 | vnode_t *vp; /* corresponding vnode */ | 5762 | bhv_vnode_t *vp; /* corresponding vnode */ |
5560 | int lock; /* lock state */ | 5763 | int lock; /* lock state */ |
5561 | xfs_bmbt_irec_t *map; /* buffer for user's data */ | 5764 | xfs_bmbt_irec_t *map; /* buffer for user's data */ |
5562 | xfs_mount_t *mp; /* file system mount point */ | 5765 | xfs_mount_t *mp; /* file system mount point */ |
@@ -5653,7 +5856,7 @@ xfs_getbmap( | |||
5653 | 5856 | ||
5654 | if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) { | 5857 | if (whichfork == XFS_DATA_FORK && ip->i_delayed_blks) { |
5655 | /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */ | 5858 | /* xfs_fsize_t last_byte = xfs_file_last_byte(ip); */ |
5656 | VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, 0, FI_REMAPF, error); | 5859 | error = bhv_vop_flush_pages(vp, (xfs_off_t)0, -1, 0, FI_REMAPF); |
5657 | } | 5860 | } |
5658 | 5861 | ||
5659 | ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0); | 5862 | ASSERT(whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0); |
@@ -5689,7 +5892,8 @@ xfs_getbmap( | |||
5689 | nmap = (nexleft > subnex) ? subnex : nexleft; | 5892 | nmap = (nexleft > subnex) ? subnex : nexleft; |
5690 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), | 5893 | error = xfs_bmapi(NULL, ip, XFS_BB_TO_FSBT(mp, bmv->bmv_offset), |
5691 | XFS_BB_TO_FSB(mp, bmv->bmv_length), | 5894 | XFS_BB_TO_FSB(mp, bmv->bmv_length), |
5692 | bmapi_flags, NULL, 0, map, &nmap, NULL); | 5895 | bmapi_flags, NULL, 0, map, &nmap, |
5896 | NULL, NULL); | ||
5693 | if (error) | 5897 | if (error) |
5694 | goto unlock_and_return; | 5898 | goto unlock_and_return; |
5695 | ASSERT(nmap <= subnex); | 5899 | ASSERT(nmap <= subnex); |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index 8e0d73d9ccc4..80e93409b78d 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -26,6 +26,20 @@ struct xfs_mount; | |||
26 | struct xfs_trans; | 26 | struct xfs_trans; |
27 | 27 | ||
28 | /* | 28 | /* |
29 | * DELTA: describe a change to the in-core extent list. | ||
30 | * | ||
31 | * Internally the use of xed_blockount is somewhat funky. | ||
32 | * xed_blockcount contains an offset much of the time because this | ||
33 | * makes merging changes easier. (xfs_fileoff_t and xfs_filblks_t are | ||
34 | * the same underlying type). | ||
35 | */ | ||
36 | typedef struct xfs_extdelta | ||
37 | { | ||
38 | xfs_fileoff_t xed_startoff; /* offset of range */ | ||
39 | xfs_filblks_t xed_blockcount; /* blocks in range */ | ||
40 | } xfs_extdelta_t; | ||
41 | |||
42 | /* | ||
29 | * List of extents to be free "later". | 43 | * List of extents to be free "later". |
30 | * The list is kept sorted on xbf_startblock. | 44 | * The list is kept sorted on xbf_startblock. |
31 | */ | 45 | */ |
@@ -275,7 +289,9 @@ xfs_bmapi( | |||
275 | xfs_extlen_t total, /* total blocks needed */ | 289 | xfs_extlen_t total, /* total blocks needed */ |
276 | struct xfs_bmbt_irec *mval, /* output: map values */ | 290 | struct xfs_bmbt_irec *mval, /* output: map values */ |
277 | int *nmap, /* i/o: mval size/count */ | 291 | int *nmap, /* i/o: mval size/count */ |
278 | xfs_bmap_free_t *flist); /* i/o: list extents to free */ | 292 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
293 | xfs_extdelta_t *delta); /* o: change made to incore | ||
294 | extents */ | ||
279 | 295 | ||
280 | /* | 296 | /* |
281 | * Map file blocks to filesystem blocks, simple version. | 297 | * Map file blocks to filesystem blocks, simple version. |
@@ -309,6 +325,8 @@ xfs_bunmapi( | |||
309 | xfs_fsblock_t *firstblock, /* first allocated block | 325 | xfs_fsblock_t *firstblock, /* first allocated block |
310 | controls a.g. for allocs */ | 326 | controls a.g. for allocs */ |
311 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ | 327 | xfs_bmap_free_t *flist, /* i/o: list extents to free */ |
328 | xfs_extdelta_t *delta, /* o: change made to incore | ||
329 | extents */ | ||
312 | int *done); /* set if not done yet */ | 330 | int *done); /* set if not done yet */ |
313 | 331 | ||
314 | /* | 332 | /* |
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c index bea44709afbe..18fb7385d719 100644 --- a/fs/xfs/xfs_bmap_btree.c +++ b/fs/xfs/xfs_bmap_btree.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -1569,12 +1567,11 @@ xfs_bmbt_split( | |||
1569 | lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); | 1567 | lbno = XFS_DADDR_TO_FSB(args.mp, XFS_BUF_ADDR(lbp)); |
1570 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); | 1568 | left = XFS_BUF_TO_BMBT_BLOCK(lbp); |
1571 | args.fsbno = cur->bc_private.b.firstblock; | 1569 | args.fsbno = cur->bc_private.b.firstblock; |
1570 | args.firstblock = args.fsbno; | ||
1572 | if (args.fsbno == NULLFSBLOCK) { | 1571 | if (args.fsbno == NULLFSBLOCK) { |
1573 | args.fsbno = lbno; | 1572 | args.fsbno = lbno; |
1574 | args.type = XFS_ALLOCTYPE_START_BNO; | 1573 | args.type = XFS_ALLOCTYPE_START_BNO; |
1575 | } else if (cur->bc_private.b.flist->xbf_low) | 1574 | } else |
1576 | args.type = XFS_ALLOCTYPE_FIRST_AG; | ||
1577 | else | ||
1578 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 1575 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
1579 | args.mod = args.minleft = args.alignment = args.total = args.isfl = | 1576 | args.mod = args.minleft = args.alignment = args.total = args.isfl = |
1580 | args.userdata = args.minalignslop = 0; | 1577 | args.userdata = args.minalignslop = 0; |
@@ -2356,6 +2353,7 @@ xfs_bmbt_newroot( | |||
2356 | args.userdata = args.minalignslop = 0; | 2353 | args.userdata = args.minalignslop = 0; |
2357 | args.minlen = args.maxlen = args.prod = 1; | 2354 | args.minlen = args.maxlen = args.prod = 1; |
2358 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; | 2355 | args.wasdel = cur->bc_private.b.flags & XFS_BTCUR_BPRV_WASDEL; |
2356 | args.firstblock = args.fsbno; | ||
2359 | if (args.fsbno == NULLFSBLOCK) { | 2357 | if (args.fsbno == NULLFSBLOCK) { |
2360 | #ifdef DEBUG | 2358 | #ifdef DEBUG |
2361 | if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { | 2359 | if ((error = xfs_btree_check_lptr(cur, INT_GET(*pp, ARCH_CONVERT), level))) { |
@@ -2365,9 +2363,7 @@ xfs_bmbt_newroot( | |||
2365 | #endif | 2363 | #endif |
2366 | args.fsbno = INT_GET(*pp, ARCH_CONVERT); | 2364 | args.fsbno = INT_GET(*pp, ARCH_CONVERT); |
2367 | args.type = XFS_ALLOCTYPE_START_BNO; | 2365 | args.type = XFS_ALLOCTYPE_START_BNO; |
2368 | } else if (args.wasdel) | 2366 | } else |
2369 | args.type = XFS_ALLOCTYPE_FIRST_AG; | ||
2370 | else | ||
2371 | args.type = XFS_ALLOCTYPE_NEAR_BNO; | 2367 | args.type = XFS_ALLOCTYPE_NEAR_BNO; |
2372 | if ((error = xfs_alloc_vextent(&args))) { | 2368 | if ((error = xfs_alloc_vextent(&args))) { |
2373 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); | 2369 | XFS_BMBT_TRACE_CURSOR(cur, ERROR); |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index 52d5d095fc35..ee2255bd6562 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c index 5fed15682dda..a4aa53974f76 100644 --- a/fs/xfs/xfs_buf_item.c +++ b/fs/xfs/xfs_buf_item.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_inum.h" | 23 | #include "xfs_inum.h" |
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_buf_item.h" | 28 | #include "xfs_buf_item.h" |
@@ -1030,9 +1029,9 @@ xfs_buf_iodone_callbacks( | |||
1030 | if ((XFS_BUF_TARGET(bp) != lasttarg) || | 1029 | if ((XFS_BUF_TARGET(bp) != lasttarg) || |
1031 | (time_after(jiffies, (lasttime + 5*HZ)))) { | 1030 | (time_after(jiffies, (lasttime + 5*HZ)))) { |
1032 | lasttime = jiffies; | 1031 | lasttime = jiffies; |
1033 | prdev("XFS write error in file system meta-data " | 1032 | cmn_err(CE_ALERT, "Device %s, XFS metadata write error" |
1034 | "block 0x%llx in %s", | 1033 | " block 0x%llx in %s", |
1035 | XFS_BUF_TARGET(bp), | 1034 | XFS_BUFTARG_NAME(XFS_BUF_TARGET(bp)), |
1036 | (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); | 1035 | (__uint64_t)XFS_BUF_ADDR(bp), mp->m_fsname); |
1037 | } | 1036 | } |
1038 | lasttarg = XFS_BUF_TARGET(bp); | 1037 | lasttarg = XFS_BUF_TARGET(bp); |
@@ -1108,7 +1107,7 @@ xfs_buf_error_relse( | |||
1108 | XFS_BUF_ERROR(bp,0); | 1107 | XFS_BUF_ERROR(bp,0); |
1109 | xfs_buftrace("BUF_ERROR_RELSE", bp); | 1108 | xfs_buftrace("BUF_ERROR_RELSE", bp); |
1110 | if (! XFS_FORCED_SHUTDOWN(mp)) | 1109 | if (! XFS_FORCED_SHUTDOWN(mp)) |
1111 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 1110 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
1112 | /* | 1111 | /* |
1113 | * We have to unpin the pinned buffers so do the | 1112 | * We have to unpin the pinned buffers so do the |
1114 | * callbacks. | 1113 | * callbacks. |
diff --git a/fs/xfs/xfs_cap.h b/fs/xfs/xfs_cap.h index d0035c6e9514..7a0e482dd436 100644 --- a/fs/xfs/xfs_cap.h +++ b/fs/xfs/xfs_cap.h | |||
@@ -49,12 +49,12 @@ typedef struct xfs_cap_set { | |||
49 | 49 | ||
50 | #include <linux/posix_cap_xattr.h> | 50 | #include <linux/posix_cap_xattr.h> |
51 | 51 | ||
52 | struct vnode; | 52 | struct bhv_vnode; |
53 | 53 | ||
54 | extern int xfs_cap_vhascap(struct vnode *); | 54 | extern int xfs_cap_vhascap(struct bhv_vnode *); |
55 | extern int xfs_cap_vset(struct vnode *, void *, size_t); | 55 | extern int xfs_cap_vset(struct bhv_vnode *, void *, size_t); |
56 | extern int xfs_cap_vget(struct vnode *, void *, size_t); | 56 | extern int xfs_cap_vget(struct bhv_vnode *, void *, size_t); |
57 | extern int xfs_cap_vremove(struct vnode *vp); | 57 | extern int xfs_cap_vremove(struct bhv_vnode *); |
58 | 58 | ||
59 | #define _CAP_EXISTS xfs_cap_vhascap | 59 | #define _CAP_EXISTS xfs_cap_vhascap |
60 | 60 | ||
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index 8988b9051175..32ab61d17ace 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -43,7 +41,6 @@ | |||
43 | #include "xfs_bmap.h" | 41 | #include "xfs_bmap.h" |
44 | #include "xfs_attr.h" | 42 | #include "xfs_attr.h" |
45 | #include "xfs_attr_leaf.h" | 43 | #include "xfs_attr_leaf.h" |
46 | #include "xfs_dir_leaf.h" | ||
47 | #include "xfs_dir2_data.h" | 44 | #include "xfs_dir2_data.h" |
48 | #include "xfs_dir2_leaf.h" | 45 | #include "xfs_dir2_leaf.h" |
49 | #include "xfs_dir2_block.h" | 46 | #include "xfs_dir2_block.h" |
@@ -159,7 +156,7 @@ xfs_da_split(xfs_da_state_t *state) | |||
159 | max = state->path.active - 1; | 156 | max = state->path.active - 1; |
160 | ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); | 157 | ASSERT((max >= 0) && (max < XFS_DA_NODE_MAXDEPTH)); |
161 | ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || | 158 | ASSERT(state->path.blk[max].magic == XFS_ATTR_LEAF_MAGIC || |
162 | state->path.blk[max].magic == XFS_DIRX_LEAF_MAGIC(state->mp)); | 159 | state->path.blk[max].magic == XFS_DIR2_LEAFN_MAGIC); |
163 | 160 | ||
164 | addblk = &state->path.blk[max]; /* initial dummy value */ | 161 | addblk = &state->path.blk[max]; /* initial dummy value */ |
165 | for (i = max; (i >= 0) && addblk; state->path.active--, i--) { | 162 | for (i = max; (i >= 0) && addblk; state->path.active--, i--) { |
@@ -199,38 +196,7 @@ xfs_da_split(xfs_da_state_t *state) | |||
199 | return(error); /* GROT: attr inconsistent */ | 196 | return(error); /* GROT: attr inconsistent */ |
200 | addblk = newblk; | 197 | addblk = newblk; |
201 | break; | 198 | break; |
202 | case XFS_DIR_LEAF_MAGIC: | ||
203 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
204 | error = xfs_dir_leaf_split(state, oldblk, newblk); | ||
205 | if ((error != 0) && (error != ENOSPC)) { | ||
206 | return(error); /* GROT: dir is inconsistent */ | ||
207 | } | ||
208 | if (!error) { | ||
209 | addblk = newblk; | ||
210 | break; | ||
211 | } | ||
212 | /* | ||
213 | * Entry wouldn't fit, split the leaf again. | ||
214 | */ | ||
215 | state->extravalid = 1; | ||
216 | if (state->inleaf) { | ||
217 | state->extraafter = 0; /* before newblk */ | ||
218 | error = xfs_dir_leaf_split(state, oldblk, | ||
219 | &state->extrablk); | ||
220 | if (error) | ||
221 | return(error); /* GROT: dir incon. */ | ||
222 | addblk = newblk; | ||
223 | } else { | ||
224 | state->extraafter = 1; /* after newblk */ | ||
225 | error = xfs_dir_leaf_split(state, newblk, | ||
226 | &state->extrablk); | ||
227 | if (error) | ||
228 | return(error); /* GROT: dir incon. */ | ||
229 | addblk = newblk; | ||
230 | } | ||
231 | break; | ||
232 | case XFS_DIR2_LEAFN_MAGIC: | 199 | case XFS_DIR2_LEAFN_MAGIC: |
233 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
234 | error = xfs_dir2_leafn_split(state, oldblk, newblk); | 200 | error = xfs_dir2_leafn_split(state, oldblk, newblk); |
235 | if (error) | 201 | if (error) |
236 | return error; | 202 | return error; |
@@ -363,7 +329,6 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
363 | size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - | 329 | size = (int)((char *)&oldroot->btree[be16_to_cpu(oldroot->hdr.count)] - |
364 | (char *)oldroot); | 330 | (char *)oldroot); |
365 | } else { | 331 | } else { |
366 | ASSERT(XFS_DIR_IS_V2(mp)); | ||
367 | ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); | 332 | ASSERT(be16_to_cpu(oldroot->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC); |
368 | leaf = (xfs_dir2_leaf_t *)oldroot; | 333 | leaf = (xfs_dir2_leaf_t *)oldroot; |
369 | size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - | 334 | size = (int)((char *)&leaf->ents[be16_to_cpu(leaf->hdr.count)] - |
@@ -379,8 +344,7 @@ xfs_da_root_split(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | |||
379 | * Set up the new root node. | 344 | * Set up the new root node. |
380 | */ | 345 | */ |
381 | error = xfs_da_node_create(args, | 346 | error = xfs_da_node_create(args, |
382 | args->whichfork == XFS_DATA_FORK && | 347 | (args->whichfork == XFS_DATA_FORK) ? mp->m_dirleafblk : 0, |
383 | XFS_DIR_IS_V2(mp) ? mp->m_dirleafblk : 0, | ||
384 | be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); | 348 | be16_to_cpu(node->hdr.level) + 1, &bp, args->whichfork); |
385 | if (error) | 349 | if (error) |
386 | return(error); | 350 | return(error); |
@@ -427,10 +391,9 @@ xfs_da_node_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
427 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); | 391 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); |
428 | 392 | ||
429 | /* | 393 | /* |
430 | * With V2 the extra block is data or freespace. | 394 | * With V2 dirs the extra block is data or freespace. |
431 | */ | 395 | */ |
432 | useextra = state->extravalid && (XFS_DIR_IS_V1(state->mp) || | 396 | useextra = state->extravalid && state->args->whichfork == XFS_ATTR_FORK; |
433 | state->args->whichfork == XFS_ATTR_FORK); | ||
434 | newcount = 1 + useextra; | 397 | newcount = 1 + useextra; |
435 | /* | 398 | /* |
436 | * Do we have to split the node? | 399 | * Do we have to split the node? |
@@ -624,7 +587,7 @@ xfs_da_node_add(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | |||
624 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); | 587 | ASSERT(be16_to_cpu(node->hdr.info.magic) == XFS_DA_NODE_MAGIC); |
625 | ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); | 588 | ASSERT((oldblk->index >= 0) && (oldblk->index <= be16_to_cpu(node->hdr.count))); |
626 | ASSERT(newblk->blkno != 0); | 589 | ASSERT(newblk->blkno != 0); |
627 | if (state->args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) | 590 | if (state->args->whichfork == XFS_DATA_FORK) |
628 | ASSERT(newblk->blkno >= mp->m_dirleafblk && | 591 | ASSERT(newblk->blkno >= mp->m_dirleafblk && |
629 | newblk->blkno < mp->m_dirfreeblk); | 592 | newblk->blkno < mp->m_dirfreeblk); |
630 | 593 | ||
@@ -670,7 +633,7 @@ xfs_da_join(xfs_da_state_t *state) | |||
670 | save_blk = &state->altpath.blk[ state->path.active-1 ]; | 633 | save_blk = &state->altpath.blk[ state->path.active-1 ]; |
671 | ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); | 634 | ASSERT(state->path.blk[0].magic == XFS_DA_NODE_MAGIC); |
672 | ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || | 635 | ASSERT(drop_blk->magic == XFS_ATTR_LEAF_MAGIC || |
673 | drop_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp)); | 636 | drop_blk->magic == XFS_DIR2_LEAFN_MAGIC); |
674 | 637 | ||
675 | /* | 638 | /* |
676 | * Walk back up the tree joining/deallocating as necessary. | 639 | * Walk back up the tree joining/deallocating as necessary. |
@@ -693,17 +656,7 @@ xfs_da_join(xfs_da_state_t *state) | |||
693 | return(0); | 656 | return(0); |
694 | xfs_attr_leaf_unbalance(state, drop_blk, save_blk); | 657 | xfs_attr_leaf_unbalance(state, drop_blk, save_blk); |
695 | break; | 658 | break; |
696 | case XFS_DIR_LEAF_MAGIC: | ||
697 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
698 | error = xfs_dir_leaf_toosmall(state, &action); | ||
699 | if (error) | ||
700 | return(error); | ||
701 | if (action == 0) | ||
702 | return(0); | ||
703 | xfs_dir_leaf_unbalance(state, drop_blk, save_blk); | ||
704 | break; | ||
705 | case XFS_DIR2_LEAFN_MAGIC: | 659 | case XFS_DIR2_LEAFN_MAGIC: |
706 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
707 | error = xfs_dir2_leafn_toosmall(state, &action); | 660 | error = xfs_dir2_leafn_toosmall(state, &action); |
708 | if (error) | 661 | if (error) |
709 | return error; | 662 | return error; |
@@ -790,7 +743,7 @@ xfs_da_root_join(xfs_da_state_t *state, xfs_da_state_blk_t *root_blk) | |||
790 | ASSERT(bp != NULL); | 743 | ASSERT(bp != NULL); |
791 | blkinfo = bp->data; | 744 | blkinfo = bp->data; |
792 | if (be16_to_cpu(oldroot->hdr.level) == 1) { | 745 | if (be16_to_cpu(oldroot->hdr.level) == 1) { |
793 | ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || | 746 | ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DIR2_LEAFN_MAGIC || |
794 | be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); | 747 | be16_to_cpu(blkinfo->magic) == XFS_ATTR_LEAF_MAGIC); |
795 | } else { | 748 | } else { |
796 | ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); | 749 | ASSERT(be16_to_cpu(blkinfo->magic) == XFS_DA_NODE_MAGIC); |
@@ -951,14 +904,7 @@ xfs_da_fixhashpath(xfs_da_state_t *state, xfs_da_state_path_t *path) | |||
951 | if (count == 0) | 904 | if (count == 0) |
952 | return; | 905 | return; |
953 | break; | 906 | break; |
954 | case XFS_DIR_LEAF_MAGIC: | ||
955 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
956 | lasthash = xfs_dir_leaf_lasthash(blk->bp, &count); | ||
957 | if (count == 0) | ||
958 | return; | ||
959 | break; | ||
960 | case XFS_DIR2_LEAFN_MAGIC: | 907 | case XFS_DIR2_LEAFN_MAGIC: |
961 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
962 | lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); | 908 | lasthash = xfs_dir2_leafn_lasthash(blk->bp, &count); |
963 | if (count == 0) | 909 | if (count == 0) |
964 | return; | 910 | return; |
@@ -1117,10 +1063,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) | |||
1117 | * Descend thru the B-tree searching each level for the right | 1063 | * Descend thru the B-tree searching each level for the right |
1118 | * node to use, until the right hashval is found. | 1064 | * node to use, until the right hashval is found. |
1119 | */ | 1065 | */ |
1120 | if (args->whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(state->mp)) | 1066 | blkno = (args->whichfork == XFS_DATA_FORK)? state->mp->m_dirleafblk : 0; |
1121 | blkno = state->mp->m_dirleafblk; | ||
1122 | else | ||
1123 | blkno = 0; | ||
1124 | for (blk = &state->path.blk[0], state->path.active = 1; | 1067 | for (blk = &state->path.blk[0], state->path.active = 1; |
1125 | state->path.active <= XFS_DA_NODE_MAXDEPTH; | 1068 | state->path.active <= XFS_DA_NODE_MAXDEPTH; |
1126 | blk++, state->path.active++) { | 1069 | blk++, state->path.active++) { |
@@ -1137,7 +1080,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) | |||
1137 | } | 1080 | } |
1138 | curr = blk->bp->data; | 1081 | curr = blk->bp->data; |
1139 | ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || | 1082 | ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || |
1140 | be16_to_cpu(curr->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || | 1083 | be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC || |
1141 | be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); | 1084 | be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); |
1142 | 1085 | ||
1143 | /* | 1086 | /* |
@@ -1190,16 +1133,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) | |||
1190 | blk->index = probe; | 1133 | blk->index = probe; |
1191 | blkno = be32_to_cpu(btree->before); | 1134 | blkno = be32_to_cpu(btree->before); |
1192 | } | 1135 | } |
1193 | } | 1136 | } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { |
1194 | else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { | ||
1195 | blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); | 1137 | blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); |
1196 | break; | 1138 | break; |
1197 | } | 1139 | } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { |
1198 | else if (be16_to_cpu(curr->magic) == XFS_DIR_LEAF_MAGIC) { | ||
1199 | blk->hashval = xfs_dir_leaf_lasthash(blk->bp, NULL); | ||
1200 | break; | ||
1201 | } | ||
1202 | else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { | ||
1203 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); | 1140 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); |
1204 | break; | 1141 | break; |
1205 | } | 1142 | } |
@@ -1212,12 +1149,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result) | |||
1212 | * next leaf and keep searching. | 1149 | * next leaf and keep searching. |
1213 | */ | 1150 | */ |
1214 | for (;;) { | 1151 | for (;;) { |
1215 | if (blk->magic == XFS_DIR_LEAF_MAGIC) { | 1152 | if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { |
1216 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
1217 | retval = xfs_dir_leaf_lookup_int(blk->bp, args, | ||
1218 | &blk->index); | ||
1219 | } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { | ||
1220 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
1221 | retval = xfs_dir2_leafn_lookup_int(blk->bp, args, | 1153 | retval = xfs_dir2_leafn_lookup_int(blk->bp, args, |
1222 | &blk->index, state); | 1154 | &blk->index, state); |
1223 | } | 1155 | } |
@@ -1270,7 +1202,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, | |||
1270 | old_info = old_blk->bp->data; | 1202 | old_info = old_blk->bp->data; |
1271 | new_info = new_blk->bp->data; | 1203 | new_info = new_blk->bp->data; |
1272 | ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || | 1204 | ASSERT(old_blk->magic == XFS_DA_NODE_MAGIC || |
1273 | old_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || | 1205 | old_blk->magic == XFS_DIR2_LEAFN_MAGIC || |
1274 | old_blk->magic == XFS_ATTR_LEAF_MAGIC); | 1206 | old_blk->magic == XFS_ATTR_LEAF_MAGIC); |
1275 | ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); | 1207 | ASSERT(old_blk->magic == be16_to_cpu(old_info->magic)); |
1276 | ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); | 1208 | ASSERT(new_blk->magic == be16_to_cpu(new_info->magic)); |
@@ -1280,12 +1212,7 @@ xfs_da_blk_link(xfs_da_state_t *state, xfs_da_state_blk_t *old_blk, | |||
1280 | case XFS_ATTR_LEAF_MAGIC: | 1212 | case XFS_ATTR_LEAF_MAGIC: |
1281 | before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); | 1213 | before = xfs_attr_leaf_order(old_blk->bp, new_blk->bp); |
1282 | break; | 1214 | break; |
1283 | case XFS_DIR_LEAF_MAGIC: | ||
1284 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
1285 | before = xfs_dir_leaf_order(old_blk->bp, new_blk->bp); | ||
1286 | break; | ||
1287 | case XFS_DIR2_LEAFN_MAGIC: | 1215 | case XFS_DIR2_LEAFN_MAGIC: |
1288 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
1289 | before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); | 1216 | before = xfs_dir2_leafn_order(old_blk->bp, new_blk->bp); |
1290 | break; | 1217 | break; |
1291 | case XFS_DA_NODE_MAGIC: | 1218 | case XFS_DA_NODE_MAGIC: |
@@ -1404,7 +1331,7 @@ xfs_da_blk_unlink(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, | |||
1404 | save_info = save_blk->bp->data; | 1331 | save_info = save_blk->bp->data; |
1405 | drop_info = drop_blk->bp->data; | 1332 | drop_info = drop_blk->bp->data; |
1406 | ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || | 1333 | ASSERT(save_blk->magic == XFS_DA_NODE_MAGIC || |
1407 | save_blk->magic == XFS_DIRX_LEAF_MAGIC(state->mp) || | 1334 | save_blk->magic == XFS_DIR2_LEAFN_MAGIC || |
1408 | save_blk->magic == XFS_ATTR_LEAF_MAGIC); | 1335 | save_blk->magic == XFS_ATTR_LEAF_MAGIC); |
1409 | ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); | 1336 | ASSERT(save_blk->magic == be16_to_cpu(save_info->magic)); |
1410 | ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); | 1337 | ASSERT(drop_blk->magic == be16_to_cpu(drop_info->magic)); |
@@ -1529,7 +1456,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | |||
1529 | ASSERT(blk->bp != NULL); | 1456 | ASSERT(blk->bp != NULL); |
1530 | info = blk->bp->data; | 1457 | info = blk->bp->data; |
1531 | ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || | 1458 | ASSERT(be16_to_cpu(info->magic) == XFS_DA_NODE_MAGIC || |
1532 | be16_to_cpu(info->magic) == XFS_DIRX_LEAF_MAGIC(state->mp) || | 1459 | be16_to_cpu(info->magic) == XFS_DIR2_LEAFN_MAGIC || |
1533 | be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); | 1460 | be16_to_cpu(info->magic) == XFS_ATTR_LEAF_MAGIC); |
1534 | blk->magic = be16_to_cpu(info->magic); | 1461 | blk->magic = be16_to_cpu(info->magic); |
1535 | if (blk->magic == XFS_DA_NODE_MAGIC) { | 1462 | if (blk->magic == XFS_DA_NODE_MAGIC) { |
@@ -1548,20 +1475,13 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | |||
1548 | blk->hashval = xfs_attr_leaf_lasthash(blk->bp, | 1475 | blk->hashval = xfs_attr_leaf_lasthash(blk->bp, |
1549 | NULL); | 1476 | NULL); |
1550 | break; | 1477 | break; |
1551 | case XFS_DIR_LEAF_MAGIC: | ||
1552 | ASSERT(XFS_DIR_IS_V1(state->mp)); | ||
1553 | blk->hashval = xfs_dir_leaf_lasthash(blk->bp, | ||
1554 | NULL); | ||
1555 | break; | ||
1556 | case XFS_DIR2_LEAFN_MAGIC: | 1478 | case XFS_DIR2_LEAFN_MAGIC: |
1557 | ASSERT(XFS_DIR_IS_V2(state->mp)); | ||
1558 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, | 1479 | blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, |
1559 | NULL); | 1480 | NULL); |
1560 | break; | 1481 | break; |
1561 | default: | 1482 | default: |
1562 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || | 1483 | ASSERT(blk->magic == XFS_ATTR_LEAF_MAGIC || |
1563 | blk->magic == | 1484 | blk->magic == XFS_DIR2_LEAFN_MAGIC); |
1564 | XFS_DIRX_LEAF_MAGIC(state->mp)); | ||
1565 | break; | 1485 | break; |
1566 | } | 1486 | } |
1567 | } | 1487 | } |
@@ -1620,7 +1540,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1620 | xfs_bmbt_irec_t *mapp; | 1540 | xfs_bmbt_irec_t *mapp; |
1621 | xfs_inode_t *dp; | 1541 | xfs_inode_t *dp; |
1622 | int nmap, error, w, count, c, got, i, mapi; | 1542 | int nmap, error, w, count, c, got, i, mapi; |
1623 | xfs_fsize_t size; | ||
1624 | xfs_trans_t *tp; | 1543 | xfs_trans_t *tp; |
1625 | xfs_mount_t *mp; | 1544 | xfs_mount_t *mp; |
1626 | 1545 | ||
@@ -1631,7 +1550,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1631 | /* | 1550 | /* |
1632 | * For new directories adjust the file offset and block count. | 1551 | * For new directories adjust the file offset and block count. |
1633 | */ | 1552 | */ |
1634 | if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) { | 1553 | if (w == XFS_DATA_FORK) { |
1635 | bno = mp->m_dirleafblk; | 1554 | bno = mp->m_dirleafblk; |
1636 | count = mp->m_dirblkfsbs; | 1555 | count = mp->m_dirblkfsbs; |
1637 | } else { | 1556 | } else { |
@@ -1641,10 +1560,9 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1641 | /* | 1560 | /* |
1642 | * Find a spot in the file space to put the new block. | 1561 | * Find a spot in the file space to put the new block. |
1643 | */ | 1562 | */ |
1644 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) { | 1563 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, w))) |
1645 | return error; | 1564 | return error; |
1646 | } | 1565 | if (w == XFS_DATA_FORK) |
1647 | if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) | ||
1648 | ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); | 1566 | ASSERT(bno >= mp->m_dirleafblk && bno < mp->m_dirfreeblk); |
1649 | /* | 1567 | /* |
1650 | * Try mapping it in one filesystem block. | 1568 | * Try mapping it in one filesystem block. |
@@ -1655,7 +1573,7 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1655 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| | 1573 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE|XFS_BMAPI_METADATA| |
1656 | XFS_BMAPI_CONTIG, | 1574 | XFS_BMAPI_CONTIG, |
1657 | args->firstblock, args->total, &map, &nmap, | 1575 | args->firstblock, args->total, &map, &nmap, |
1658 | args->flist))) { | 1576 | args->flist, NULL))) { |
1659 | return error; | 1577 | return error; |
1660 | } | 1578 | } |
1661 | ASSERT(nmap <= 1); | 1579 | ASSERT(nmap <= 1); |
@@ -1676,7 +1594,8 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1676 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE| | 1594 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_WRITE| |
1677 | XFS_BMAPI_METADATA, | 1595 | XFS_BMAPI_METADATA, |
1678 | args->firstblock, args->total, | 1596 | args->firstblock, args->total, |
1679 | &mapp[mapi], &nmap, args->flist))) { | 1597 | &mapp[mapi], &nmap, args->flist, |
1598 | NULL))) { | ||
1680 | kmem_free(mapp, sizeof(*mapp) * count); | 1599 | kmem_free(mapp, sizeof(*mapp) * count); |
1681 | return error; | 1600 | return error; |
1682 | } | 1601 | } |
@@ -1705,19 +1624,6 @@ xfs_da_grow_inode(xfs_da_args_t *args, xfs_dablk_t *new_blkno) | |||
1705 | if (mapp != &map) | 1624 | if (mapp != &map) |
1706 | kmem_free(mapp, sizeof(*mapp) * count); | 1625 | kmem_free(mapp, sizeof(*mapp) * count); |
1707 | *new_blkno = (xfs_dablk_t)bno; | 1626 | *new_blkno = (xfs_dablk_t)bno; |
1708 | /* | ||
1709 | * For version 1 directories, adjust the file size if it changed. | ||
1710 | */ | ||
1711 | if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) { | ||
1712 | ASSERT(mapi == 1); | ||
1713 | if ((error = xfs_bmap_last_offset(tp, dp, &bno, w))) | ||
1714 | return error; | ||
1715 | size = XFS_FSB_TO_B(mp, bno); | ||
1716 | if (size != dp->i_d.di_size) { | ||
1717 | dp->i_d.di_size = size; | ||
1718 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | ||
1719 | } | ||
1720 | } | ||
1721 | return 0; | 1627 | return 0; |
1722 | } | 1628 | } |
1723 | 1629 | ||
@@ -1742,7 +1648,6 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, | |||
1742 | int error, w, entno, level, dead_level; | 1648 | int error, w, entno, level, dead_level; |
1743 | xfs_da_blkinfo_t *dead_info, *sib_info; | 1649 | xfs_da_blkinfo_t *dead_info, *sib_info; |
1744 | xfs_da_intnode_t *par_node, *dead_node; | 1650 | xfs_da_intnode_t *par_node, *dead_node; |
1745 | xfs_dir_leafblock_t *dead_leaf; | ||
1746 | xfs_dir2_leaf_t *dead_leaf2; | 1651 | xfs_dir2_leaf_t *dead_leaf2; |
1747 | xfs_dahash_t dead_hash; | 1652 | xfs_dahash_t dead_hash; |
1748 | 1653 | ||
@@ -1753,11 +1658,8 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, | |||
1753 | w = args->whichfork; | 1658 | w = args->whichfork; |
1754 | ASSERT(w == XFS_DATA_FORK); | 1659 | ASSERT(w == XFS_DATA_FORK); |
1755 | mp = ip->i_mount; | 1660 | mp = ip->i_mount; |
1756 | if (XFS_DIR_IS_V2(mp)) { | 1661 | lastoff = mp->m_dirfreeblk; |
1757 | lastoff = mp->m_dirfreeblk; | 1662 | error = xfs_bmap_last_before(tp, ip, &lastoff, w); |
1758 | error = xfs_bmap_last_before(tp, ip, &lastoff, w); | ||
1759 | } else | ||
1760 | error = xfs_bmap_last_offset(tp, ip, &lastoff, w); | ||
1761 | if (error) | 1663 | if (error) |
1762 | return error; | 1664 | return error; |
1763 | if (unlikely(lastoff == 0)) { | 1665 | if (unlikely(lastoff == 0)) { |
@@ -1780,14 +1682,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, | |||
1780 | /* | 1682 | /* |
1781 | * Get values from the moved block. | 1683 | * Get values from the moved block. |
1782 | */ | 1684 | */ |
1783 | if (be16_to_cpu(dead_info->magic) == XFS_DIR_LEAF_MAGIC) { | 1685 | if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { |
1784 | ASSERT(XFS_DIR_IS_V1(mp)); | ||
1785 | dead_leaf = (xfs_dir_leafblock_t *)dead_info; | ||
1786 | dead_level = 0; | ||
1787 | dead_hash = | ||
1788 | INT_GET(dead_leaf->entries[INT_GET(dead_leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT); | ||
1789 | } else if (be16_to_cpu(dead_info->magic) == XFS_DIR2_LEAFN_MAGIC) { | ||
1790 | ASSERT(XFS_DIR_IS_V2(mp)); | ||
1791 | dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; | 1686 | dead_leaf2 = (xfs_dir2_leaf_t *)dead_info; |
1792 | dead_level = 0; | 1687 | dead_level = 0; |
1793 | dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); | 1688 | dead_hash = be32_to_cpu(dead_leaf2->ents[be16_to_cpu(dead_leaf2->hdr.count) - 1].hashval); |
@@ -1842,7 +1737,7 @@ xfs_da_swap_lastblock(xfs_da_args_t *args, xfs_dablk_t *dead_blknop, | |||
1842 | xfs_da_buf_done(sib_buf); | 1737 | xfs_da_buf_done(sib_buf); |
1843 | sib_buf = NULL; | 1738 | sib_buf = NULL; |
1844 | } | 1739 | } |
1845 | par_blkno = XFS_DIR_IS_V1(mp) ? 0 : mp->m_dirleafblk; | 1740 | par_blkno = mp->m_dirleafblk; |
1846 | level = -1; | 1741 | level = -1; |
1847 | /* | 1742 | /* |
1848 | * Walk down the tree looking for the parent of the moved block. | 1743 | * Walk down the tree looking for the parent of the moved block. |
@@ -1941,8 +1836,6 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | |||
1941 | { | 1836 | { |
1942 | xfs_inode_t *dp; | 1837 | xfs_inode_t *dp; |
1943 | int done, error, w, count; | 1838 | int done, error, w, count; |
1944 | xfs_fileoff_t bno; | ||
1945 | xfs_fsize_t size; | ||
1946 | xfs_trans_t *tp; | 1839 | xfs_trans_t *tp; |
1947 | xfs_mount_t *mp; | 1840 | xfs_mount_t *mp; |
1948 | 1841 | ||
@@ -1950,7 +1843,7 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | |||
1950 | w = args->whichfork; | 1843 | w = args->whichfork; |
1951 | tp = args->trans; | 1844 | tp = args->trans; |
1952 | mp = dp->i_mount; | 1845 | mp = dp->i_mount; |
1953 | if (w == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) | 1846 | if (w == XFS_DATA_FORK) |
1954 | count = mp->m_dirblkfsbs; | 1847 | count = mp->m_dirblkfsbs; |
1955 | else | 1848 | else |
1956 | count = 1; | 1849 | count = 1; |
@@ -1961,34 +1854,17 @@ xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | |||
1961 | */ | 1854 | */ |
1962 | if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, | 1855 | if ((error = xfs_bunmapi(tp, dp, dead_blkno, count, |
1963 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA, | 1856 | XFS_BMAPI_AFLAG(w)|XFS_BMAPI_METADATA, |
1964 | 0, args->firstblock, args->flist, | 1857 | 0, args->firstblock, args->flist, NULL, |
1965 | &done)) == ENOSPC) { | 1858 | &done)) == ENOSPC) { |
1966 | if (w != XFS_DATA_FORK) | 1859 | if (w != XFS_DATA_FORK) |
1967 | goto done; | 1860 | break; |
1968 | if ((error = xfs_da_swap_lastblock(args, &dead_blkno, | 1861 | if ((error = xfs_da_swap_lastblock(args, &dead_blkno, |
1969 | &dead_buf))) | 1862 | &dead_buf))) |
1970 | goto done; | 1863 | break; |
1971 | } else if (error) | 1864 | } else { |
1972 | goto done; | ||
1973 | else | ||
1974 | break; | 1865 | break; |
1975 | } | ||
1976 | ASSERT(done); | ||
1977 | xfs_da_binval(tp, dead_buf); | ||
1978 | /* | ||
1979 | * Adjust the directory size for version 1. | ||
1980 | */ | ||
1981 | if (w == XFS_DATA_FORK && XFS_DIR_IS_V1(mp)) { | ||
1982 | if ((error = xfs_bmap_last_offset(tp, dp, &bno, w))) | ||
1983 | return error; | ||
1984 | size = XFS_FSB_TO_B(dp->i_mount, bno); | ||
1985 | if (size != dp->i_d.di_size) { | ||
1986 | dp->i_d.di_size = size; | ||
1987 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | ||
1988 | } | 1866 | } |
1989 | } | 1867 | } |
1990 | return 0; | ||
1991 | done: | ||
1992 | xfs_da_binval(tp, dead_buf); | 1868 | xfs_da_binval(tp, dead_buf); |
1993 | return error; | 1869 | return error; |
1994 | } | 1870 | } |
@@ -2049,10 +1925,7 @@ xfs_da_do_buf( | |||
2049 | xfs_dabuf_t *rbp; | 1925 | xfs_dabuf_t *rbp; |
2050 | 1926 | ||
2051 | mp = dp->i_mount; | 1927 | mp = dp->i_mount; |
2052 | if (whichfork == XFS_DATA_FORK && XFS_DIR_IS_V2(mp)) | 1928 | nfsb = (whichfork == XFS_DATA_FORK) ? mp->m_dirblkfsbs : 1; |
2053 | nfsb = mp->m_dirblkfsbs; | ||
2054 | else | ||
2055 | nfsb = 1; | ||
2056 | mappedbno = *mappedbnop; | 1929 | mappedbno = *mappedbnop; |
2057 | /* | 1930 | /* |
2058 | * Caller doesn't have a mapping. -2 means don't complain | 1931 | * Caller doesn't have a mapping. -2 means don't complain |
@@ -2086,7 +1959,7 @@ xfs_da_do_buf( | |||
2086 | nfsb, | 1959 | nfsb, |
2087 | XFS_BMAPI_METADATA | | 1960 | XFS_BMAPI_METADATA | |
2088 | XFS_BMAPI_AFLAG(whichfork), | 1961 | XFS_BMAPI_AFLAG(whichfork), |
2089 | NULL, 0, mapp, &nmap, NULL))) | 1962 | NULL, 0, mapp, &nmap, NULL, NULL))) |
2090 | goto exit0; | 1963 | goto exit0; |
2091 | } | 1964 | } |
2092 | } else { | 1965 | } else { |
@@ -2198,7 +2071,6 @@ xfs_da_do_buf( | |||
2198 | magic1 = be32_to_cpu(data->hdr.magic); | 2071 | magic1 = be32_to_cpu(data->hdr.magic); |
2199 | if (unlikely( | 2072 | if (unlikely( |
2200 | XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && | 2073 | XFS_TEST_ERROR((magic != XFS_DA_NODE_MAGIC) && |
2201 | (magic != XFS_DIR_LEAF_MAGIC) && | ||
2202 | (magic != XFS_ATTR_LEAF_MAGIC) && | 2074 | (magic != XFS_ATTR_LEAF_MAGIC) && |
2203 | (magic != XFS_DIR2_LEAF1_MAGIC) && | 2075 | (magic != XFS_DIR2_LEAF1_MAGIC) && |
2204 | (magic != XFS_DIR2_LEAFN_MAGIC) && | 2076 | (magic != XFS_DIR2_LEAFN_MAGIC) && |
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 243a730d5ec8..4ab865ec8b82 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -36,14 +36,10 @@ struct zone; | |||
36 | * level in the Btree, and to identify which type of block this is. | 36 | * level in the Btree, and to identify which type of block this is. |
37 | */ | 37 | */ |
38 | #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ | 38 | #define XFS_DA_NODE_MAGIC 0xfebe /* magic number: non-leaf blocks */ |
39 | #define XFS_DIR_LEAF_MAGIC 0xfeeb /* magic number: directory leaf blks */ | ||
40 | #define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ | 39 | #define XFS_ATTR_LEAF_MAGIC 0xfbee /* magic number: attribute leaf blks */ |
41 | #define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ | 40 | #define XFS_DIR2_LEAF1_MAGIC 0xd2f1 /* magic number: v2 dirlf single blks */ |
42 | #define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ | 41 | #define XFS_DIR2_LEAFN_MAGIC 0xd2ff /* magic number: v2 dirlf multi blks */ |
43 | 42 | ||
44 | #define XFS_DIRX_LEAF_MAGIC(mp) \ | ||
45 | (XFS_DIR_IS_V1(mp) ? XFS_DIR_LEAF_MAGIC : XFS_DIR2_LEAFN_MAGIC) | ||
46 | |||
47 | typedef struct xfs_da_blkinfo { | 43 | typedef struct xfs_da_blkinfo { |
48 | __be32 forw; /* previous block in list */ | 44 | __be32 forw; /* previous block in list */ |
49 | __be32 back; /* following block in list */ | 45 | __be32 back; /* following block in list */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index 4968a6358e61..80562b60fb95 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2002,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -54,24 +52,14 @@ xfs_swapext( | |||
54 | xfs_swapext_t __user *sxu) | 52 | xfs_swapext_t __user *sxu) |
55 | { | 53 | { |
56 | xfs_swapext_t *sxp; | 54 | xfs_swapext_t *sxp; |
57 | xfs_inode_t *ip=NULL, *tip=NULL, *ips[2]; | 55 | xfs_inode_t *ip=NULL, *tip=NULL; |
58 | xfs_trans_t *tp; | ||
59 | xfs_mount_t *mp; | 56 | xfs_mount_t *mp; |
60 | xfs_bstat_t *sbp; | ||
61 | struct file *fp = NULL, *tfp = NULL; | 57 | struct file *fp = NULL, *tfp = NULL; |
62 | vnode_t *vp, *tvp; | 58 | bhv_vnode_t *vp, *tvp; |
63 | static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; | ||
64 | int ilf_fields, tilf_fields; | ||
65 | int error = 0; | 59 | int error = 0; |
66 | xfs_ifork_t *tempifp, *ifp, *tifp; | ||
67 | __uint64_t tmp; | ||
68 | int aforkblks = 0; | ||
69 | int taforkblks = 0; | ||
70 | char locked = 0; | ||
71 | 60 | ||
72 | sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); | 61 | sxp = kmem_alloc(sizeof(xfs_swapext_t), KM_MAYFAIL); |
73 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); | 62 | if (!sxp) { |
74 | if (!sxp || !tempifp) { | ||
75 | error = XFS_ERROR(ENOMEM); | 63 | error = XFS_ERROR(ENOMEM); |
76 | goto error0; | 64 | goto error0; |
77 | } | 65 | } |
@@ -118,14 +106,56 @@ xfs_swapext( | |||
118 | 106 | ||
119 | mp = ip->i_mount; | 107 | mp = ip->i_mount; |
120 | 108 | ||
121 | sbp = &sxp->sx_stat; | ||
122 | |||
123 | if (XFS_FORCED_SHUTDOWN(mp)) { | 109 | if (XFS_FORCED_SHUTDOWN(mp)) { |
124 | error = XFS_ERROR(EIO); | 110 | error = XFS_ERROR(EIO); |
125 | goto error0; | 111 | goto error0; |
126 | } | 112 | } |
127 | 113 | ||
128 | locked = 1; | 114 | error = XFS_SWAP_EXTENTS(mp, &ip->i_iocore, &tip->i_iocore, sxp); |
115 | |||
116 | error0: | ||
117 | if (fp != NULL) | ||
118 | fput(fp); | ||
119 | if (tfp != NULL) | ||
120 | fput(tfp); | ||
121 | |||
122 | if (sxp != NULL) | ||
123 | kmem_free(sxp, sizeof(xfs_swapext_t)); | ||
124 | |||
125 | return error; | ||
126 | } | ||
127 | |||
128 | int | ||
129 | xfs_swap_extents( | ||
130 | xfs_inode_t *ip, | ||
131 | xfs_inode_t *tip, | ||
132 | xfs_swapext_t *sxp) | ||
133 | { | ||
134 | xfs_mount_t *mp; | ||
135 | xfs_inode_t *ips[2]; | ||
136 | xfs_trans_t *tp; | ||
137 | xfs_bstat_t *sbp = &sxp->sx_stat; | ||
138 | bhv_vnode_t *vp, *tvp; | ||
139 | xfs_ifork_t *tempifp, *ifp, *tifp; | ||
140 | int ilf_fields, tilf_fields; | ||
141 | static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; | ||
142 | int error = 0; | ||
143 | int aforkblks = 0; | ||
144 | int taforkblks = 0; | ||
145 | __uint64_t tmp; | ||
146 | char locked = 0; | ||
147 | |||
148 | mp = ip->i_mount; | ||
149 | |||
150 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); | ||
151 | if (!tempifp) { | ||
152 | error = XFS_ERROR(ENOMEM); | ||
153 | goto error0; | ||
154 | } | ||
155 | |||
156 | sbp = &sxp->sx_stat; | ||
157 | vp = XFS_ITOV(ip); | ||
158 | tvp = XFS_ITOV(tip); | ||
129 | 159 | ||
130 | /* Lock in i_ino order */ | 160 | /* Lock in i_ino order */ |
131 | if (ip->i_ino < tip->i_ino) { | 161 | if (ip->i_ino < tip->i_ino) { |
@@ -137,6 +167,7 @@ xfs_swapext( | |||
137 | } | 167 | } |
138 | 168 | ||
139 | xfs_lock_inodes(ips, 2, 0, lock_flags); | 169 | xfs_lock_inodes(ips, 2, 0, lock_flags); |
170 | locked = 1; | ||
140 | 171 | ||
141 | /* Check permissions */ | 172 | /* Check permissions */ |
142 | error = xfs_iaccess(ip, S_IWUSR, NULL); | 173 | error = xfs_iaccess(ip, S_IWUSR, NULL); |
@@ -169,7 +200,7 @@ xfs_swapext( | |||
169 | 200 | ||
170 | if (VN_CACHED(tvp) != 0) { | 201 | if (VN_CACHED(tvp) != 0) { |
171 | xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1); | 202 | xfs_inval_cached_trace(&tip->i_iocore, 0, -1, 0, -1); |
172 | VOP_FLUSHINVAL_PAGES(tvp, 0, -1, FI_REMAPF_LOCKED); | 203 | bhv_vop_flushinval_pages(tvp, 0, -1, FI_REMAPF_LOCKED); |
173 | } | 204 | } |
174 | 205 | ||
175 | /* Verify O_DIRECT for ftmp */ | 206 | /* Verify O_DIRECT for ftmp */ |
@@ -214,7 +245,7 @@ xfs_swapext( | |||
214 | /* We need to fail if the file is memory mapped. Once we have tossed | 245 | /* We need to fail if the file is memory mapped. Once we have tossed |
215 | * all existing pages, the page fault will have no option | 246 | * all existing pages, the page fault will have no option |
216 | * but to go to the filesystem for pages. By making the page fault call | 247 | * but to go to the filesystem for pages. By making the page fault call |
217 | * VOP_READ (or write in the case of autogrow) they block on the iolock | 248 | * vop_read (or write in the case of autogrow) they block on the iolock |
218 | * until we have switched the extents. | 249 | * until we have switched the extents. |
219 | */ | 250 | */ |
220 | if (VN_MAPPED(vp)) { | 251 | if (VN_MAPPED(vp)) { |
@@ -233,7 +264,7 @@ xfs_swapext( | |||
233 | * fields change. | 264 | * fields change. |
234 | */ | 265 | */ |
235 | 266 | ||
236 | VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); | 267 | bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); |
237 | 268 | ||
238 | tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT); | 269 | tp = xfs_trans_alloc(mp, XFS_TRANS_SWAPEXT); |
239 | if ((error = xfs_trans_reserve(tp, 0, | 270 | if ((error = xfs_trans_reserve(tp, 0, |
@@ -360,16 +391,7 @@ xfs_swapext( | |||
360 | xfs_iunlock(ip, lock_flags); | 391 | xfs_iunlock(ip, lock_flags); |
361 | xfs_iunlock(tip, lock_flags); | 392 | xfs_iunlock(tip, lock_flags); |
362 | } | 393 | } |
363 | |||
364 | if (fp != NULL) | ||
365 | fput(fp); | ||
366 | if (tfp != NULL) | ||
367 | fput(tfp); | ||
368 | |||
369 | if (sxp != NULL) | ||
370 | kmem_free(sxp, sizeof(xfs_swapext_t)); | ||
371 | if (tempifp != NULL) | 394 | if (tempifp != NULL) |
372 | kmem_free(tempifp, sizeof(xfs_ifork_t)); | 395 | kmem_free(tempifp, sizeof(xfs_ifork_t)); |
373 | |||
374 | return error; | 396 | return error; |
375 | } | 397 | } |
diff --git a/fs/xfs/xfs_dfrag.h b/fs/xfs/xfs_dfrag.h index f678559abc45..da178205be68 100644 --- a/fs/xfs/xfs_dfrag.h +++ b/fs/xfs/xfs_dfrag.h | |||
@@ -48,6 +48,9 @@ typedef struct xfs_swapext | |||
48 | */ | 48 | */ |
49 | int xfs_swapext(struct xfs_swapext __user *sx); | 49 | int xfs_swapext(struct xfs_swapext __user *sx); |
50 | 50 | ||
51 | int xfs_swap_extents(struct xfs_inode *ip, struct xfs_inode *tip, | ||
52 | struct xfs_swapext *sxp); | ||
53 | |||
51 | #endif /* __KERNEL__ */ | 54 | #endif /* __KERNEL__ */ |
52 | 55 | ||
53 | #endif /* __XFS_DFRAG_H__ */ | 56 | #endif /* __XFS_DFRAG_H__ */ |
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index 79d0d9e1fbab..b33826961c45 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h | |||
@@ -85,7 +85,6 @@ typedef struct xfs_dinode | |||
85 | union { | 85 | union { |
86 | xfs_bmdr_block_t di_bmbt; /* btree root block */ | 86 | xfs_bmdr_block_t di_bmbt; /* btree root block */ |
87 | xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ | 87 | xfs_bmbt_rec_32_t di_bmx[1]; /* extent list */ |
88 | xfs_dir_shortform_t di_dirsf; /* shortform directory */ | ||
89 | xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ | 88 | xfs_dir2_sf_t di_dir2sf; /* shortform directory v2 */ |
90 | char di_c[1]; /* local contents */ | 89 | char di_c[1]; /* local contents */ |
91 | xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */ | 90 | xfs_dev_t di_dev; /* device for S_IFCHR/S_IFBLK */ |
@@ -257,6 +256,7 @@ typedef enum xfs_dinode_fmt | |||
257 | #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ | 256 | #define XFS_DIFLAG_NOSYMLINKS_BIT 10 /* disallow symlink creation */ |
258 | #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ | 257 | #define XFS_DIFLAG_EXTSIZE_BIT 11 /* inode extent size allocator hint */ |
259 | #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ | 258 | #define XFS_DIFLAG_EXTSZINHERIT_BIT 12 /* inherit inode extent size */ |
259 | #define XFS_DIFLAG_NODEFRAG_BIT 13 /* do not reorganize/defragment */ | ||
260 | #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) | 260 | #define XFS_DIFLAG_REALTIME (1 << XFS_DIFLAG_REALTIME_BIT) |
261 | #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) | 261 | #define XFS_DIFLAG_PREALLOC (1 << XFS_DIFLAG_PREALLOC_BIT) |
262 | #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) | 262 | #define XFS_DIFLAG_NEWRTBM (1 << XFS_DIFLAG_NEWRTBM_BIT) |
@@ -270,12 +270,13 @@ typedef enum xfs_dinode_fmt | |||
270 | #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) | 270 | #define XFS_DIFLAG_NOSYMLINKS (1 << XFS_DIFLAG_NOSYMLINKS_BIT) |
271 | #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) | 271 | #define XFS_DIFLAG_EXTSIZE (1 << XFS_DIFLAG_EXTSIZE_BIT) |
272 | #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) | 272 | #define XFS_DIFLAG_EXTSZINHERIT (1 << XFS_DIFLAG_EXTSZINHERIT_BIT) |
273 | #define XFS_DIFLAG_NODEFRAG (1 << XFS_DIFLAG_NODEFRAG_BIT) | ||
273 | 274 | ||
274 | #define XFS_DIFLAG_ANY \ | 275 | #define XFS_DIFLAG_ANY \ |
275 | (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ | 276 | (XFS_DIFLAG_REALTIME | XFS_DIFLAG_PREALLOC | XFS_DIFLAG_NEWRTBM | \ |
276 | XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ | 277 | XFS_DIFLAG_IMMUTABLE | XFS_DIFLAG_APPEND | XFS_DIFLAG_SYNC | \ |
277 | XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ | 278 | XFS_DIFLAG_NOATIME | XFS_DIFLAG_NODUMP | XFS_DIFLAG_RTINHERIT | \ |
278 | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ | 279 | XFS_DIFLAG_PROJINHERIT | XFS_DIFLAG_NOSYMLINKS | XFS_DIFLAG_EXTSIZE | \ |
279 | XFS_DIFLAG_EXTSZINHERIT) | 280 | XFS_DIFLAG_EXTSZINHERIT | XFS_DIFLAG_NODEFRAG) |
280 | 281 | ||
281 | #endif /* __XFS_DINODE_H__ */ | 282 | #endif /* __XFS_DINODE_H__ */ |
diff --git a/fs/xfs/xfs_dir.c b/fs/xfs/xfs_dir.c deleted file mode 100644 index 9cc702a839a3..000000000000 --- a/fs/xfs/xfs_dir.c +++ /dev/null | |||
@@ -1,1217 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_fs.h" | ||
20 | #include "xfs_types.h" | ||
21 | #include "xfs_log.h" | ||
22 | #include "xfs_inum.h" | ||
23 | #include "xfs_trans.h" | ||
24 | #include "xfs_sb.h" | ||
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | ||
29 | #include "xfs_da_btree.h" | ||
30 | #include "xfs_bmap_btree.h" | ||
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_alloc.h" | ||
34 | #include "xfs_btree.h" | ||
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | ||
37 | #include "xfs_attr_sf.h" | ||
38 | #include "xfs_dinode.h" | ||
39 | #include "xfs_inode.h" | ||
40 | #include "xfs_bmap.h" | ||
41 | #include "xfs_dir_leaf.h" | ||
42 | #include "xfs_error.h" | ||
43 | |||
44 | /* | ||
45 | * xfs_dir.c | ||
46 | * | ||
47 | * Provide the external interfaces to manage directories. | ||
48 | */ | ||
49 | |||
50 | /*======================================================================== | ||
51 | * Function prototypes for the kernel. | ||
52 | *========================================================================*/ | ||
53 | |||
54 | /* | ||
55 | * Functions for the dirops interfaces. | ||
56 | */ | ||
57 | static void xfs_dir_mount(struct xfs_mount *mp); | ||
58 | |||
59 | static int xfs_dir_isempty(struct xfs_inode *dp); | ||
60 | |||
61 | static int xfs_dir_init(struct xfs_trans *trans, | ||
62 | struct xfs_inode *dir, | ||
63 | struct xfs_inode *parent_dir); | ||
64 | |||
65 | static int xfs_dir_createname(struct xfs_trans *trans, | ||
66 | struct xfs_inode *dp, | ||
67 | char *name_string, | ||
68 | int name_len, | ||
69 | xfs_ino_t inode_number, | ||
70 | xfs_fsblock_t *firstblock, | ||
71 | xfs_bmap_free_t *flist, | ||
72 | xfs_extlen_t total); | ||
73 | |||
74 | static int xfs_dir_lookup(struct xfs_trans *tp, | ||
75 | struct xfs_inode *dp, | ||
76 | char *name_string, | ||
77 | int name_length, | ||
78 | xfs_ino_t *inode_number); | ||
79 | |||
80 | static int xfs_dir_removename(struct xfs_trans *trans, | ||
81 | struct xfs_inode *dp, | ||
82 | char *name_string, | ||
83 | int name_length, | ||
84 | xfs_ino_t ino, | ||
85 | xfs_fsblock_t *firstblock, | ||
86 | xfs_bmap_free_t *flist, | ||
87 | xfs_extlen_t total); | ||
88 | |||
89 | static int xfs_dir_getdents(struct xfs_trans *tp, | ||
90 | struct xfs_inode *dp, | ||
91 | struct uio *uiop, | ||
92 | int *eofp); | ||
93 | |||
94 | static int xfs_dir_replace(struct xfs_trans *tp, | ||
95 | struct xfs_inode *dp, | ||
96 | char *name_string, | ||
97 | int name_length, | ||
98 | xfs_ino_t inode_number, | ||
99 | xfs_fsblock_t *firstblock, | ||
100 | xfs_bmap_free_t *flist, | ||
101 | xfs_extlen_t total); | ||
102 | |||
103 | static int xfs_dir_canenter(struct xfs_trans *tp, | ||
104 | struct xfs_inode *dp, | ||
105 | char *name_string, | ||
106 | int name_length); | ||
107 | |||
108 | static int xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, | ||
109 | xfs_dinode_t *dip); | ||
110 | |||
111 | xfs_dirops_t xfsv1_dirops = { | ||
112 | .xd_mount = xfs_dir_mount, | ||
113 | .xd_isempty = xfs_dir_isempty, | ||
114 | .xd_init = xfs_dir_init, | ||
115 | .xd_createname = xfs_dir_createname, | ||
116 | .xd_lookup = xfs_dir_lookup, | ||
117 | .xd_removename = xfs_dir_removename, | ||
118 | .xd_getdents = xfs_dir_getdents, | ||
119 | .xd_replace = xfs_dir_replace, | ||
120 | .xd_canenter = xfs_dir_canenter, | ||
121 | .xd_shortform_validate_ondisk = xfs_dir_shortform_validate_ondisk, | ||
122 | .xd_shortform_to_single = xfs_dir_shortform_to_leaf, | ||
123 | }; | ||
124 | |||
125 | /* | ||
126 | * Internal routines when dirsize == XFS_LBSIZE(mp). | ||
127 | */ | ||
128 | STATIC int xfs_dir_leaf_lookup(xfs_da_args_t *args); | ||
129 | STATIC int xfs_dir_leaf_removename(xfs_da_args_t *args, int *number_entries, | ||
130 | int *total_namebytes); | ||
131 | STATIC int xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, | ||
132 | uio_t *uio, int *eofp, | ||
133 | xfs_dirent_t *dbp, | ||
134 | xfs_dir_put_t put); | ||
135 | STATIC int xfs_dir_leaf_replace(xfs_da_args_t *args); | ||
136 | |||
137 | /* | ||
138 | * Internal routines when dirsize > XFS_LBSIZE(mp). | ||
139 | */ | ||
140 | STATIC int xfs_dir_node_addname(xfs_da_args_t *args); | ||
141 | STATIC int xfs_dir_node_lookup(xfs_da_args_t *args); | ||
142 | STATIC int xfs_dir_node_removename(xfs_da_args_t *args); | ||
143 | STATIC int xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, | ||
144 | uio_t *uio, int *eofp, | ||
145 | xfs_dirent_t *dbp, | ||
146 | xfs_dir_put_t put); | ||
147 | STATIC int xfs_dir_node_replace(xfs_da_args_t *args); | ||
148 | |||
149 | #if defined(XFS_DIR_TRACE) | ||
150 | ktrace_t *xfs_dir_trace_buf; | ||
151 | #endif | ||
152 | |||
153 | |||
154 | /*======================================================================== | ||
155 | * Overall external interface routines. | ||
156 | *========================================================================*/ | ||
157 | |||
158 | xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; | ||
159 | |||
160 | /* | ||
161 | * One-time startup routine called from xfs_init(). | ||
162 | */ | ||
163 | void | ||
164 | xfs_dir_startup(void) | ||
165 | { | ||
166 | xfs_dir_hash_dot = xfs_da_hashname(".", 1); | ||
167 | xfs_dir_hash_dotdot = xfs_da_hashname("..", 2); | ||
168 | } | ||
169 | |||
170 | /* | ||
171 | * Initialize directory-related fields in the mount structure. | ||
172 | */ | ||
173 | static void | ||
174 | xfs_dir_mount(xfs_mount_t *mp) | ||
175 | { | ||
176 | uint shortcount, leafcount, count; | ||
177 | |||
178 | mp->m_dirversion = 1; | ||
179 | if (!(mp->m_flags & XFS_MOUNT_ATTR2)) { | ||
180 | shortcount = (mp->m_attroffset - | ||
181 | (uint)sizeof(xfs_dir_sf_hdr_t)) / | ||
182 | (uint)sizeof(xfs_dir_sf_entry_t); | ||
183 | leafcount = (XFS_LBSIZE(mp) - | ||
184 | (uint)sizeof(xfs_dir_leaf_hdr_t)) / | ||
185 | ((uint)sizeof(xfs_dir_leaf_entry_t) + | ||
186 | (uint)sizeof(xfs_dir_leaf_name_t)); | ||
187 | } else { | ||
188 | shortcount = (XFS_BMDR_SPACE_CALC(MINABTPTRS) - | ||
189 | (uint)sizeof(xfs_dir_sf_hdr_t)) / | ||
190 | (uint)sizeof(xfs_dir_sf_entry_t); | ||
191 | leafcount = (XFS_LBSIZE(mp) - | ||
192 | (uint)sizeof(xfs_dir_leaf_hdr_t)) / | ||
193 | ((uint)sizeof(xfs_dir_leaf_entry_t) + | ||
194 | (uint)sizeof(xfs_dir_leaf_name_t)); | ||
195 | } | ||
196 | count = shortcount > leafcount ? shortcount : leafcount; | ||
197 | mp->m_dircook_elog = xfs_da_log2_roundup(count + 1); | ||
198 | ASSERT(mp->m_dircook_elog <= mp->m_sb.sb_blocklog); | ||
199 | mp->m_dir_node_ents = mp->m_attr_node_ents = | ||
200 | (XFS_LBSIZE(mp) - (uint)sizeof(xfs_da_node_hdr_t)) / | ||
201 | (uint)sizeof(xfs_da_node_entry_t); | ||
202 | mp->m_dir_magicpct = (XFS_LBSIZE(mp) * 37) / 100; | ||
203 | mp->m_dirblksize = mp->m_sb.sb_blocksize; | ||
204 | mp->m_dirblkfsbs = 1; | ||
205 | } | ||
206 | |||
207 | /* | ||
208 | * Return 1 if directory contains only "." and "..". | ||
209 | */ | ||
210 | static int | ||
211 | xfs_dir_isempty(xfs_inode_t *dp) | ||
212 | { | ||
213 | xfs_dir_sf_hdr_t *hdr; | ||
214 | |||
215 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
216 | if (dp->i_d.di_size == 0) | ||
217 | return(1); | ||
218 | if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) | ||
219 | return(0); | ||
220 | hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data; | ||
221 | return(hdr->count == 0); | ||
222 | } | ||
223 | |||
224 | /* | ||
225 | * Initialize a directory with its "." and ".." entries. | ||
226 | */ | ||
227 | static int | ||
228 | xfs_dir_init(xfs_trans_t *trans, xfs_inode_t *dir, xfs_inode_t *parent_dir) | ||
229 | { | ||
230 | xfs_da_args_t args; | ||
231 | int error; | ||
232 | |||
233 | memset((char *)&args, 0, sizeof(args)); | ||
234 | args.dp = dir; | ||
235 | args.trans = trans; | ||
236 | |||
237 | ASSERT((dir->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
238 | if ((error = xfs_dir_ino_validate(trans->t_mountp, parent_dir->i_ino))) | ||
239 | return error; | ||
240 | |||
241 | return(xfs_dir_shortform_create(&args, parent_dir->i_ino)); | ||
242 | } | ||
243 | |||
244 | /* | ||
245 | * Generic handler routine to add a name to a directory. | ||
246 | * Transitions directory from shortform to Btree as necessary. | ||
247 | */ | ||
248 | static int /* error */ | ||
249 | xfs_dir_createname(xfs_trans_t *trans, xfs_inode_t *dp, char *name, | ||
250 | int namelen, xfs_ino_t inum, xfs_fsblock_t *firstblock, | ||
251 | xfs_bmap_free_t *flist, xfs_extlen_t total) | ||
252 | { | ||
253 | xfs_da_args_t args; | ||
254 | int retval, newsize, done; | ||
255 | |||
256 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
257 | |||
258 | if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum))) | ||
259 | return (retval); | ||
260 | |||
261 | XFS_STATS_INC(xs_dir_create); | ||
262 | /* | ||
263 | * Fill in the arg structure for this request. | ||
264 | */ | ||
265 | args.name = name; | ||
266 | args.namelen = namelen; | ||
267 | args.hashval = xfs_da_hashname(name, namelen); | ||
268 | args.inumber = inum; | ||
269 | args.dp = dp; | ||
270 | args.firstblock = firstblock; | ||
271 | args.flist = flist; | ||
272 | args.total = total; | ||
273 | args.whichfork = XFS_DATA_FORK; | ||
274 | args.trans = trans; | ||
275 | args.justcheck = 0; | ||
276 | args.addname = args.oknoent = 1; | ||
277 | |||
278 | /* | ||
279 | * Decide on what work routines to call based on the inode size. | ||
280 | */ | ||
281 | done = 0; | ||
282 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
283 | newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen); | ||
284 | if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) { | ||
285 | retval = xfs_dir_shortform_addname(&args); | ||
286 | done = 1; | ||
287 | } else { | ||
288 | if (total == 0) | ||
289 | return XFS_ERROR(ENOSPC); | ||
290 | retval = xfs_dir_shortform_to_leaf(&args); | ||
291 | done = retval != 0; | ||
292 | } | ||
293 | } | ||
294 | if (!done && xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
295 | retval = xfs_dir_leaf_addname(&args); | ||
296 | done = retval != ENOSPC; | ||
297 | if (!done) { | ||
298 | if (total == 0) | ||
299 | return XFS_ERROR(ENOSPC); | ||
300 | retval = xfs_dir_leaf_to_node(&args); | ||
301 | done = retval != 0; | ||
302 | } | ||
303 | } | ||
304 | if (!done) { | ||
305 | retval = xfs_dir_node_addname(&args); | ||
306 | } | ||
307 | return(retval); | ||
308 | } | ||
309 | |||
310 | /* | ||
311 | * Generic handler routine to check if a name can be added to a directory, | ||
312 | * without adding any blocks to the directory. | ||
313 | */ | ||
314 | static int /* error */ | ||
315 | xfs_dir_canenter(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen) | ||
316 | { | ||
317 | xfs_da_args_t args; | ||
318 | int retval, newsize; | ||
319 | |||
320 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
321 | /* | ||
322 | * Fill in the arg structure for this request. | ||
323 | */ | ||
324 | args.name = name; | ||
325 | args.namelen = namelen; | ||
326 | args.hashval = xfs_da_hashname(name, namelen); | ||
327 | args.inumber = 0; | ||
328 | args.dp = dp; | ||
329 | args.firstblock = NULL; | ||
330 | args.flist = NULL; | ||
331 | args.total = 0; | ||
332 | args.whichfork = XFS_DATA_FORK; | ||
333 | args.trans = trans; | ||
334 | args.justcheck = args.addname = args.oknoent = 1; | ||
335 | |||
336 | /* | ||
337 | * Decide on what work routines to call based on the inode size. | ||
338 | */ | ||
339 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
340 | newsize = XFS_DIR_SF_ENTSIZE_BYNAME(args.namelen); | ||
341 | if ((dp->i_d.di_size + newsize) <= XFS_IFORK_DSIZE(dp)) | ||
342 | retval = 0; | ||
343 | else | ||
344 | retval = XFS_ERROR(ENOSPC); | ||
345 | } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
346 | retval = xfs_dir_leaf_addname(&args); | ||
347 | } else { | ||
348 | retval = xfs_dir_node_addname(&args); | ||
349 | } | ||
350 | return(retval); | ||
351 | } | ||
352 | |||
353 | /* | ||
354 | * Generic handler routine to remove a name from a directory. | ||
355 | * Transitions directory from Btree to shortform as necessary. | ||
356 | */ | ||
357 | static int /* error */ | ||
358 | xfs_dir_removename(xfs_trans_t *trans, xfs_inode_t *dp, char *name, | ||
359 | int namelen, xfs_ino_t ino, xfs_fsblock_t *firstblock, | ||
360 | xfs_bmap_free_t *flist, xfs_extlen_t total) | ||
361 | { | ||
362 | xfs_da_args_t args; | ||
363 | int count, totallen, newsize, retval; | ||
364 | |||
365 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
366 | XFS_STATS_INC(xs_dir_remove); | ||
367 | /* | ||
368 | * Fill in the arg structure for this request. | ||
369 | */ | ||
370 | args.name = name; | ||
371 | args.namelen = namelen; | ||
372 | args.hashval = xfs_da_hashname(name, namelen); | ||
373 | args.inumber = ino; | ||
374 | args.dp = dp; | ||
375 | args.firstblock = firstblock; | ||
376 | args.flist = flist; | ||
377 | args.total = total; | ||
378 | args.whichfork = XFS_DATA_FORK; | ||
379 | args.trans = trans; | ||
380 | args.justcheck = args.addname = args.oknoent = 0; | ||
381 | |||
382 | /* | ||
383 | * Decide on what work routines to call based on the inode size. | ||
384 | */ | ||
385 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
386 | retval = xfs_dir_shortform_removename(&args); | ||
387 | } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
388 | retval = xfs_dir_leaf_removename(&args, &count, &totallen); | ||
389 | if (retval == 0) { | ||
390 | newsize = XFS_DIR_SF_ALLFIT(count, totallen); | ||
391 | if (newsize <= XFS_IFORK_DSIZE(dp)) { | ||
392 | retval = xfs_dir_leaf_to_shortform(&args); | ||
393 | } | ||
394 | } | ||
395 | } else { | ||
396 | retval = xfs_dir_node_removename(&args); | ||
397 | } | ||
398 | return(retval); | ||
399 | } | ||
400 | |||
401 | static int /* error */ | ||
402 | xfs_dir_lookup(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, | ||
403 | xfs_ino_t *inum) | ||
404 | { | ||
405 | xfs_da_args_t args; | ||
406 | int retval; | ||
407 | |||
408 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
409 | |||
410 | XFS_STATS_INC(xs_dir_lookup); | ||
411 | /* | ||
412 | * Fill in the arg structure for this request. | ||
413 | */ | ||
414 | args.name = name; | ||
415 | args.namelen = namelen; | ||
416 | args.hashval = xfs_da_hashname(name, namelen); | ||
417 | args.inumber = 0; | ||
418 | args.dp = dp; | ||
419 | args.firstblock = NULL; | ||
420 | args.flist = NULL; | ||
421 | args.total = 0; | ||
422 | args.whichfork = XFS_DATA_FORK; | ||
423 | args.trans = trans; | ||
424 | args.justcheck = args.addname = 0; | ||
425 | args.oknoent = 1; | ||
426 | |||
427 | /* | ||
428 | * Decide on what work routines to call based on the inode size. | ||
429 | */ | ||
430 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
431 | retval = xfs_dir_shortform_lookup(&args); | ||
432 | } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
433 | retval = xfs_dir_leaf_lookup(&args); | ||
434 | } else { | ||
435 | retval = xfs_dir_node_lookup(&args); | ||
436 | } | ||
437 | if (retval == EEXIST) | ||
438 | retval = 0; | ||
439 | *inum = args.inumber; | ||
440 | return(retval); | ||
441 | } | ||
442 | |||
443 | /* | ||
444 | * Implement readdir. | ||
445 | */ | ||
446 | static int /* error */ | ||
447 | xfs_dir_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, int *eofp) | ||
448 | { | ||
449 | xfs_dirent_t *dbp; | ||
450 | int alignment, retval; | ||
451 | xfs_dir_put_t put; | ||
452 | |||
453 | XFS_STATS_INC(xs_dir_getdents); | ||
454 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
455 | |||
456 | /* | ||
457 | * If our caller has given us a single contiguous memory buffer, | ||
458 | * just work directly within that buffer. If it's in user memory, | ||
459 | * lock it down first. | ||
460 | */ | ||
461 | alignment = sizeof(xfs_off_t) - 1; | ||
462 | if ((uio->uio_iovcnt == 1) && | ||
463 | (((__psint_t)uio->uio_iov[0].iov_base & alignment) == 0) && | ||
464 | ((uio->uio_iov[0].iov_len & alignment) == 0)) { | ||
465 | dbp = NULL; | ||
466 | put = xfs_dir_put_dirent64_direct; | ||
467 | } else { | ||
468 | dbp = kmem_alloc(sizeof(*dbp) + MAXNAMELEN, KM_SLEEP); | ||
469 | put = xfs_dir_put_dirent64_uio; | ||
470 | } | ||
471 | |||
472 | /* | ||
473 | * Decide on what work routines to call based on the inode size. | ||
474 | */ | ||
475 | *eofp = 0; | ||
476 | |||
477 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
478 | retval = xfs_dir_shortform_getdents(dp, uio, eofp, dbp, put); | ||
479 | } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
480 | retval = xfs_dir_leaf_getdents(trans, dp, uio, eofp, dbp, put); | ||
481 | } else { | ||
482 | retval = xfs_dir_node_getdents(trans, dp, uio, eofp, dbp, put); | ||
483 | } | ||
484 | if (dbp != NULL) | ||
485 | kmem_free(dbp, sizeof(*dbp) + MAXNAMELEN); | ||
486 | |||
487 | return(retval); | ||
488 | } | ||
489 | |||
490 | static int /* error */ | ||
491 | xfs_dir_replace(xfs_trans_t *trans, xfs_inode_t *dp, char *name, int namelen, | ||
492 | xfs_ino_t inum, xfs_fsblock_t *firstblock, | ||
493 | xfs_bmap_free_t *flist, xfs_extlen_t total) | ||
494 | { | ||
495 | xfs_da_args_t args; | ||
496 | int retval; | ||
497 | |||
498 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | ||
499 | |||
500 | if ((retval = xfs_dir_ino_validate(trans->t_mountp, inum))) | ||
501 | return retval; | ||
502 | |||
503 | /* | ||
504 | * Fill in the arg structure for this request. | ||
505 | */ | ||
506 | args.name = name; | ||
507 | args.namelen = namelen; | ||
508 | args.hashval = xfs_da_hashname(name, namelen); | ||
509 | args.inumber = inum; | ||
510 | args.dp = dp; | ||
511 | args.firstblock = firstblock; | ||
512 | args.flist = flist; | ||
513 | args.total = total; | ||
514 | args.whichfork = XFS_DATA_FORK; | ||
515 | args.trans = trans; | ||
516 | args.justcheck = args.addname = args.oknoent = 0; | ||
517 | |||
518 | /* | ||
519 | * Decide on what work routines to call based on the inode size. | ||
520 | */ | ||
521 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | ||
522 | retval = xfs_dir_shortform_replace(&args); | ||
523 | } else if (xfs_bmap_one_block(dp, XFS_DATA_FORK)) { | ||
524 | retval = xfs_dir_leaf_replace(&args); | ||
525 | } else { | ||
526 | retval = xfs_dir_node_replace(&args); | ||
527 | } | ||
528 | |||
529 | return(retval); | ||
530 | } | ||
531 | |||
532 | static int | ||
533 | xfs_dir_shortform_validate_ondisk(xfs_mount_t *mp, xfs_dinode_t *dp) | ||
534 | { | ||
535 | xfs_ino_t ino; | ||
536 | int namelen_sum; | ||
537 | int count; | ||
538 | xfs_dir_shortform_t *sf; | ||
539 | xfs_dir_sf_entry_t *sfe; | ||
540 | int i; | ||
541 | |||
542 | |||
543 | |||
544 | if ((INT_GET(dp->di_core.di_mode, ARCH_CONVERT) & S_IFMT) != S_IFDIR) { | ||
545 | return 0; | ||
546 | } | ||
547 | if (INT_GET(dp->di_core.di_format, ARCH_CONVERT) != XFS_DINODE_FMT_LOCAL) { | ||
548 | return 0; | ||
549 | } | ||
550 | if (INT_GET(dp->di_core.di_size, ARCH_CONVERT) < sizeof(sf->hdr)) { | ||
551 | xfs_fs_cmn_err(CE_WARN, mp, "Invalid shortform size: dp 0x%p", | ||
552 | dp); | ||
553 | return 1; | ||
554 | } | ||
555 | sf = (xfs_dir_shortform_t *)(&dp->di_u.di_dirsf); | ||
556 | ino = XFS_GET_DIR_INO8(sf->hdr.parent); | ||
557 | if (xfs_dir_ino_validate(mp, ino)) | ||
558 | return 1; | ||
559 | |||
560 | count = sf->hdr.count; | ||
561 | if ((count < 0) || ((count * 10) > XFS_LITINO(mp))) { | ||
562 | xfs_fs_cmn_err(CE_WARN, mp, | ||
563 | "Invalid shortform count: dp 0x%p", dp); | ||
564 | return(1); | ||
565 | } | ||
566 | |||
567 | if (count == 0) { | ||
568 | return 0; | ||
569 | } | ||
570 | |||
571 | namelen_sum = 0; | ||
572 | sfe = &sf->list[0]; | ||
573 | for (i = sf->hdr.count - 1; i >= 0; i--) { | ||
574 | ino = XFS_GET_DIR_INO8(sfe->inumber); | ||
575 | xfs_dir_ino_validate(mp, ino); | ||
576 | if (sfe->namelen >= XFS_LITINO(mp)) { | ||
577 | xfs_fs_cmn_err(CE_WARN, mp, | ||
578 | "Invalid shortform namelen: dp 0x%p", dp); | ||
579 | return 1; | ||
580 | } | ||
581 | namelen_sum += sfe->namelen; | ||
582 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
583 | } | ||
584 | if (namelen_sum >= XFS_LITINO(mp)) { | ||
585 | xfs_fs_cmn_err(CE_WARN, mp, | ||
586 | "Invalid shortform namelen: dp 0x%p", dp); | ||
587 | return 1; | ||
588 | } | ||
589 | |||
590 | return 0; | ||
591 | } | ||
592 | |||
593 | /*======================================================================== | ||
594 | * External routines when dirsize == XFS_LBSIZE(dp->i_mount). | ||
595 | *========================================================================*/ | ||
596 | |||
597 | /* | ||
598 | * Add a name to the leaf directory structure | ||
599 | * This is the external routine. | ||
600 | */ | ||
601 | int | ||
602 | xfs_dir_leaf_addname(xfs_da_args_t *args) | ||
603 | { | ||
604 | int index, retval; | ||
605 | xfs_dabuf_t *bp; | ||
606 | |||
607 | retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, | ||
608 | XFS_DATA_FORK); | ||
609 | if (retval) | ||
610 | return(retval); | ||
611 | ASSERT(bp != NULL); | ||
612 | |||
613 | retval = xfs_dir_leaf_lookup_int(bp, args, &index); | ||
614 | if (retval == ENOENT) | ||
615 | retval = xfs_dir_leaf_add(bp, args, index); | ||
616 | xfs_da_buf_done(bp); | ||
617 | return(retval); | ||
618 | } | ||
619 | |||
620 | /* | ||
621 | * Remove a name from the leaf directory structure | ||
622 | * This is the external routine. | ||
623 | */ | ||
624 | STATIC int | ||
625 | xfs_dir_leaf_removename(xfs_da_args_t *args, int *count, int *totallen) | ||
626 | { | ||
627 | xfs_dir_leafblock_t *leaf; | ||
628 | int index, retval; | ||
629 | xfs_dabuf_t *bp; | ||
630 | |||
631 | retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, | ||
632 | XFS_DATA_FORK); | ||
633 | if (retval) | ||
634 | return(retval); | ||
635 | ASSERT(bp != NULL); | ||
636 | leaf = bp->data; | ||
637 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
638 | retval = xfs_dir_leaf_lookup_int(bp, args, &index); | ||
639 | if (retval == EEXIST) { | ||
640 | (void)xfs_dir_leaf_remove(args->trans, bp, index); | ||
641 | *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
642 | *totallen = INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); | ||
643 | retval = 0; | ||
644 | } | ||
645 | xfs_da_buf_done(bp); | ||
646 | return(retval); | ||
647 | } | ||
648 | |||
649 | /* | ||
650 | * Look up a name in a leaf directory structure. | ||
651 | * This is the external routine. | ||
652 | */ | ||
653 | STATIC int | ||
654 | xfs_dir_leaf_lookup(xfs_da_args_t *args) | ||
655 | { | ||
656 | int index, retval; | ||
657 | xfs_dabuf_t *bp; | ||
658 | |||
659 | retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, | ||
660 | XFS_DATA_FORK); | ||
661 | if (retval) | ||
662 | return(retval); | ||
663 | ASSERT(bp != NULL); | ||
664 | retval = xfs_dir_leaf_lookup_int(bp, args, &index); | ||
665 | xfs_da_brelse(args->trans, bp); | ||
666 | return(retval); | ||
667 | } | ||
668 | |||
669 | /* | ||
670 | * Copy out directory entries for getdents(), for leaf directories. | ||
671 | */ | ||
672 | STATIC int | ||
673 | xfs_dir_leaf_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, | ||
674 | int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put) | ||
675 | { | ||
676 | xfs_dabuf_t *bp; | ||
677 | int retval, eob; | ||
678 | |||
679 | retval = xfs_da_read_buf(dp->i_transp, dp, 0, -1, &bp, XFS_DATA_FORK); | ||
680 | if (retval) | ||
681 | return(retval); | ||
682 | ASSERT(bp != NULL); | ||
683 | retval = xfs_dir_leaf_getdents_int(bp, dp, 0, uio, &eob, dbp, put, -1); | ||
684 | xfs_da_brelse(trans, bp); | ||
685 | *eofp = (eob == 0); | ||
686 | return(retval); | ||
687 | } | ||
688 | |||
689 | /* | ||
690 | * Look up a name in a leaf directory structure, replace the inode number. | ||
691 | * This is the external routine. | ||
692 | */ | ||
693 | STATIC int | ||
694 | xfs_dir_leaf_replace(xfs_da_args_t *args) | ||
695 | { | ||
696 | int index, retval; | ||
697 | xfs_dabuf_t *bp; | ||
698 | xfs_ino_t inum; | ||
699 | xfs_dir_leafblock_t *leaf; | ||
700 | xfs_dir_leaf_entry_t *entry; | ||
701 | xfs_dir_leaf_name_t *namest; | ||
702 | |||
703 | inum = args->inumber; | ||
704 | retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp, | ||
705 | XFS_DATA_FORK); | ||
706 | if (retval) | ||
707 | return(retval); | ||
708 | ASSERT(bp != NULL); | ||
709 | retval = xfs_dir_leaf_lookup_int(bp, args, &index); | ||
710 | if (retval == EEXIST) { | ||
711 | leaf = bp->data; | ||
712 | entry = &leaf->entries[index]; | ||
713 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
714 | /* XXX - replace assert? */ | ||
715 | XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); | ||
716 | xfs_da_log_buf(args->trans, bp, | ||
717 | XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber))); | ||
718 | xfs_da_buf_done(bp); | ||
719 | retval = 0; | ||
720 | } else | ||
721 | xfs_da_brelse(args->trans, bp); | ||
722 | return(retval); | ||
723 | } | ||
724 | |||
725 | |||
726 | /*======================================================================== | ||
727 | * External routines when dirsize > XFS_LBSIZE(mp). | ||
728 | *========================================================================*/ | ||
729 | |||
730 | /* | ||
731 | * Add a name to a Btree-format directory. | ||
732 | * | ||
733 | * This will involve walking down the Btree, and may involve splitting | ||
734 | * leaf nodes and even splitting intermediate nodes up to and including | ||
735 | * the root node (a special case of an intermediate node). | ||
736 | */ | ||
737 | STATIC int | ||
738 | xfs_dir_node_addname(xfs_da_args_t *args) | ||
739 | { | ||
740 | xfs_da_state_t *state; | ||
741 | xfs_da_state_blk_t *blk; | ||
742 | int retval, error; | ||
743 | |||
744 | /* | ||
745 | * Fill in bucket of arguments/results/context to carry around. | ||
746 | */ | ||
747 | state = xfs_da_state_alloc(); | ||
748 | state->args = args; | ||
749 | state->mp = args->dp->i_mount; | ||
750 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
751 | state->node_ents = state->mp->m_dir_node_ents; | ||
752 | |||
753 | /* | ||
754 | * Search to see if name already exists, and get back a pointer | ||
755 | * to where it should go. | ||
756 | */ | ||
757 | error = xfs_da_node_lookup_int(state, &retval); | ||
758 | if (error) | ||
759 | retval = error; | ||
760 | if (retval != ENOENT) | ||
761 | goto error; | ||
762 | blk = &state->path.blk[ state->path.active-1 ]; | ||
763 | ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); | ||
764 | retval = xfs_dir_leaf_add(blk->bp, args, blk->index); | ||
765 | if (retval == 0) { | ||
766 | /* | ||
767 | * Addition succeeded, update Btree hashvals. | ||
768 | */ | ||
769 | if (!args->justcheck) | ||
770 | xfs_da_fixhashpath(state, &state->path); | ||
771 | } else { | ||
772 | /* | ||
773 | * Addition failed, split as many Btree elements as required. | ||
774 | */ | ||
775 | if (args->total == 0) { | ||
776 | ASSERT(retval == ENOSPC); | ||
777 | goto error; | ||
778 | } | ||
779 | retval = xfs_da_split(state); | ||
780 | } | ||
781 | error: | ||
782 | xfs_da_state_free(state); | ||
783 | |||
784 | return(retval); | ||
785 | } | ||
786 | |||
787 | /* | ||
788 | * Remove a name from a B-tree directory. | ||
789 | * | ||
790 | * This will involve walking down the Btree, and may involve joining | ||
791 | * leaf nodes and even joining intermediate nodes up to and including | ||
792 | * the root node (a special case of an intermediate node). | ||
793 | */ | ||
794 | STATIC int | ||
795 | xfs_dir_node_removename(xfs_da_args_t *args) | ||
796 | { | ||
797 | xfs_da_state_t *state; | ||
798 | xfs_da_state_blk_t *blk; | ||
799 | int retval, error; | ||
800 | |||
801 | state = xfs_da_state_alloc(); | ||
802 | state->args = args; | ||
803 | state->mp = args->dp->i_mount; | ||
804 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
805 | state->node_ents = state->mp->m_dir_node_ents; | ||
806 | |||
807 | /* | ||
808 | * Search to see if name exists, and get back a pointer to it. | ||
809 | */ | ||
810 | error = xfs_da_node_lookup_int(state, &retval); | ||
811 | if (error) | ||
812 | retval = error; | ||
813 | if (retval != EEXIST) { | ||
814 | xfs_da_state_free(state); | ||
815 | return(retval); | ||
816 | } | ||
817 | |||
818 | /* | ||
819 | * Remove the name and update the hashvals in the tree. | ||
820 | */ | ||
821 | blk = &state->path.blk[ state->path.active-1 ]; | ||
822 | ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); | ||
823 | retval = xfs_dir_leaf_remove(args->trans, blk->bp, blk->index); | ||
824 | xfs_da_fixhashpath(state, &state->path); | ||
825 | |||
826 | /* | ||
827 | * Check to see if the tree needs to be collapsed. | ||
828 | */ | ||
829 | error = 0; | ||
830 | if (retval) { | ||
831 | error = xfs_da_join(state); | ||
832 | } | ||
833 | |||
834 | xfs_da_state_free(state); | ||
835 | if (error) | ||
836 | return(error); | ||
837 | return(0); | ||
838 | } | ||
839 | |||
840 | /* | ||
841 | * Look up a filename in a int directory. | ||
842 | * Use an internal routine to actually do all the work. | ||
843 | */ | ||
844 | STATIC int | ||
845 | xfs_dir_node_lookup(xfs_da_args_t *args) | ||
846 | { | ||
847 | xfs_da_state_t *state; | ||
848 | int retval, error, i; | ||
849 | |||
850 | state = xfs_da_state_alloc(); | ||
851 | state->args = args; | ||
852 | state->mp = args->dp->i_mount; | ||
853 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
854 | state->node_ents = state->mp->m_dir_node_ents; | ||
855 | |||
856 | /* | ||
857 | * Search to see if name exists, | ||
858 | * and get back a pointer to it. | ||
859 | */ | ||
860 | error = xfs_da_node_lookup_int(state, &retval); | ||
861 | if (error) { | ||
862 | retval = error; | ||
863 | } | ||
864 | |||
865 | /* | ||
866 | * If not in a transaction, we have to release all the buffers. | ||
867 | */ | ||
868 | for (i = 0; i < state->path.active; i++) { | ||
869 | xfs_da_brelse(args->trans, state->path.blk[i].bp); | ||
870 | state->path.blk[i].bp = NULL; | ||
871 | } | ||
872 | |||
873 | xfs_da_state_free(state); | ||
874 | return(retval); | ||
875 | } | ||
876 | |||
877 | STATIC int | ||
878 | xfs_dir_node_getdents(xfs_trans_t *trans, xfs_inode_t *dp, uio_t *uio, | ||
879 | int *eofp, xfs_dirent_t *dbp, xfs_dir_put_t put) | ||
880 | { | ||
881 | xfs_da_intnode_t *node; | ||
882 | xfs_da_node_entry_t *btree; | ||
883 | xfs_dir_leafblock_t *leaf = NULL; | ||
884 | xfs_dablk_t bno, nextbno; | ||
885 | xfs_dahash_t cookhash; | ||
886 | xfs_mount_t *mp; | ||
887 | int error, eob, i; | ||
888 | xfs_dabuf_t *bp; | ||
889 | xfs_daddr_t nextda; | ||
890 | |||
891 | /* | ||
892 | * Pick up our context. | ||
893 | */ | ||
894 | mp = dp->i_mount; | ||
895 | bp = NULL; | ||
896 | bno = XFS_DA_COOKIE_BNO(mp, uio->uio_offset); | ||
897 | cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); | ||
898 | |||
899 | xfs_dir_trace_g_du("node: start", dp, uio); | ||
900 | |||
901 | /* | ||
902 | * Re-find our place, even if we're confused about what our place is. | ||
903 | * | ||
904 | * First we check the block number from the magic cookie, it is a | ||
905 | * cache of where we ended last time. If we find a leaf block, and | ||
906 | * the starting hashval in that block is less than our desired | ||
907 | * hashval, then we run with it. | ||
908 | */ | ||
909 | if (bno > 0) { | ||
910 | error = xfs_da_read_buf(trans, dp, bno, -2, &bp, XFS_DATA_FORK); | ||
911 | if ((error != 0) && (error != EFSCORRUPTED)) | ||
912 | return(error); | ||
913 | if (bp) | ||
914 | leaf = bp->data; | ||
915 | if (bp && be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { | ||
916 | xfs_dir_trace_g_dub("node: block not a leaf", | ||
917 | dp, uio, bno); | ||
918 | xfs_da_brelse(trans, bp); | ||
919 | bp = NULL; | ||
920 | } | ||
921 | if (bp && INT_GET(leaf->entries[0].hashval, ARCH_CONVERT) > cookhash) { | ||
922 | xfs_dir_trace_g_dub("node: leaf hash too large", | ||
923 | dp, uio, bno); | ||
924 | xfs_da_brelse(trans, bp); | ||
925 | bp = NULL; | ||
926 | } | ||
927 | if (bp && | ||
928 | cookhash > INT_GET(leaf->entries[INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1].hashval, ARCH_CONVERT)) { | ||
929 | xfs_dir_trace_g_dub("node: leaf hash too small", | ||
930 | dp, uio, bno); | ||
931 | xfs_da_brelse(trans, bp); | ||
932 | bp = NULL; | ||
933 | } | ||
934 | } | ||
935 | |||
936 | /* | ||
937 | * If we did not find a leaf block from the blockno in the cookie, | ||
938 | * or we there was no blockno in the cookie (eg: first time thru), | ||
939 | * the we start at the top of the Btree and re-find our hashval. | ||
940 | */ | ||
941 | if (bp == NULL) { | ||
942 | xfs_dir_trace_g_du("node: start at root" , dp, uio); | ||
943 | bno = 0; | ||
944 | for (;;) { | ||
945 | error = xfs_da_read_buf(trans, dp, bno, -1, &bp, | ||
946 | XFS_DATA_FORK); | ||
947 | if (error) | ||
948 | return(error); | ||
949 | if (bp == NULL) | ||
950 | return(XFS_ERROR(EFSCORRUPTED)); | ||
951 | node = bp->data; | ||
952 | if (be16_to_cpu(node->hdr.info.magic) != XFS_DA_NODE_MAGIC) | ||
953 | break; | ||
954 | btree = &node->btree[0]; | ||
955 | xfs_dir_trace_g_dun("node: node detail", dp, uio, node); | ||
956 | for (i = 0; i < be16_to_cpu(node->hdr.count); btree++, i++) { | ||
957 | if (be32_to_cpu(btree->hashval) >= cookhash) { | ||
958 | bno = be32_to_cpu(btree->before); | ||
959 | break; | ||
960 | } | ||
961 | } | ||
962 | if (i == be16_to_cpu(node->hdr.count)) { | ||
963 | xfs_da_brelse(trans, bp); | ||
964 | xfs_dir_trace_g_du("node: hash beyond EOF", | ||
965 | dp, uio); | ||
966 | uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, | ||
967 | XFS_DA_MAXHASH); | ||
968 | *eofp = 1; | ||
969 | return(0); | ||
970 | } | ||
971 | xfs_dir_trace_g_dub("node: going to block", | ||
972 | dp, uio, bno); | ||
973 | xfs_da_brelse(trans, bp); | ||
974 | } | ||
975 | } | ||
976 | ASSERT(cookhash != XFS_DA_MAXHASH); | ||
977 | |||
978 | /* | ||
979 | * We've dropped down to the (first) leaf block that contains the | ||
980 | * hashval we are interested in. Continue rolling upward thru the | ||
981 | * leaf blocks until we fill up our buffer. | ||
982 | */ | ||
983 | for (;;) { | ||
984 | leaf = bp->data; | ||
985 | if (unlikely(be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC)) { | ||
986 | xfs_dir_trace_g_dul("node: not a leaf", dp, uio, leaf); | ||
987 | xfs_da_brelse(trans, bp); | ||
988 | XFS_CORRUPTION_ERROR("xfs_dir_node_getdents(1)", | ||
989 | XFS_ERRLEVEL_LOW, mp, leaf); | ||
990 | return XFS_ERROR(EFSCORRUPTED); | ||
991 | } | ||
992 | xfs_dir_trace_g_dul("node: leaf detail", dp, uio, leaf); | ||
993 | if ((nextbno = be32_to_cpu(leaf->hdr.info.forw))) { | ||
994 | nextda = xfs_da_reada_buf(trans, dp, nextbno, | ||
995 | XFS_DATA_FORK); | ||
996 | } else | ||
997 | nextda = -1; | ||
998 | error = xfs_dir_leaf_getdents_int(bp, dp, bno, uio, &eob, dbp, | ||
999 | put, nextda); | ||
1000 | xfs_da_brelse(trans, bp); | ||
1001 | bno = nextbno; | ||
1002 | if (eob) { | ||
1003 | xfs_dir_trace_g_dub("node: E-O-B", dp, uio, bno); | ||
1004 | *eofp = 0; | ||
1005 | return(error); | ||
1006 | } | ||
1007 | if (bno == 0) | ||
1008 | break; | ||
1009 | error = xfs_da_read_buf(trans, dp, bno, nextda, &bp, | ||
1010 | XFS_DATA_FORK); | ||
1011 | if (error) | ||
1012 | return(error); | ||
1013 | if (unlikely(bp == NULL)) { | ||
1014 | XFS_ERROR_REPORT("xfs_dir_node_getdents(2)", | ||
1015 | XFS_ERRLEVEL_LOW, mp); | ||
1016 | return(XFS_ERROR(EFSCORRUPTED)); | ||
1017 | } | ||
1018 | } | ||
1019 | *eofp = 1; | ||
1020 | xfs_dir_trace_g_du("node: E-O-F", dp, uio); | ||
1021 | return(0); | ||
1022 | } | ||
1023 | |||
1024 | /* | ||
1025 | * Look up a filename in an int directory, replace the inode number. | ||
1026 | * Use an internal routine to actually do the lookup. | ||
1027 | */ | ||
1028 | STATIC int | ||
1029 | xfs_dir_node_replace(xfs_da_args_t *args) | ||
1030 | { | ||
1031 | xfs_da_state_t *state; | ||
1032 | xfs_da_state_blk_t *blk; | ||
1033 | xfs_dir_leafblock_t *leaf; | ||
1034 | xfs_dir_leaf_entry_t *entry; | ||
1035 | xfs_dir_leaf_name_t *namest; | ||
1036 | xfs_ino_t inum; | ||
1037 | int retval, error, i; | ||
1038 | xfs_dabuf_t *bp; | ||
1039 | |||
1040 | state = xfs_da_state_alloc(); | ||
1041 | state->args = args; | ||
1042 | state->mp = args->dp->i_mount; | ||
1043 | state->blocksize = state->mp->m_sb.sb_blocksize; | ||
1044 | state->node_ents = state->mp->m_dir_node_ents; | ||
1045 | inum = args->inumber; | ||
1046 | |||
1047 | /* | ||
1048 | * Search to see if name exists, | ||
1049 | * and get back a pointer to it. | ||
1050 | */ | ||
1051 | error = xfs_da_node_lookup_int(state, &retval); | ||
1052 | if (error) { | ||
1053 | retval = error; | ||
1054 | } | ||
1055 | |||
1056 | if (retval == EEXIST) { | ||
1057 | blk = &state->path.blk[state->path.active - 1]; | ||
1058 | ASSERT(blk->magic == XFS_DIR_LEAF_MAGIC); | ||
1059 | bp = blk->bp; | ||
1060 | leaf = bp->data; | ||
1061 | entry = &leaf->entries[blk->index]; | ||
1062 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
1063 | /* XXX - replace assert ? */ | ||
1064 | XFS_DIR_SF_PUT_DIRINO(&inum, &namest->inumber); | ||
1065 | xfs_da_log_buf(args->trans, bp, | ||
1066 | XFS_DA_LOGRANGE(leaf, namest, sizeof(namest->inumber))); | ||
1067 | xfs_da_buf_done(bp); | ||
1068 | blk->bp = NULL; | ||
1069 | retval = 0; | ||
1070 | } else { | ||
1071 | i = state->path.active - 1; | ||
1072 | xfs_da_brelse(args->trans, state->path.blk[i].bp); | ||
1073 | state->path.blk[i].bp = NULL; | ||
1074 | } | ||
1075 | for (i = 0; i < state->path.active - 1; i++) { | ||
1076 | xfs_da_brelse(args->trans, state->path.blk[i].bp); | ||
1077 | state->path.blk[i].bp = NULL; | ||
1078 | } | ||
1079 | |||
1080 | xfs_da_state_free(state); | ||
1081 | return(retval); | ||
1082 | } | ||
1083 | |||
1084 | #if defined(XFS_DIR_TRACE) | ||
1085 | /* | ||
1086 | * Add a trace buffer entry for an inode and a uio. | ||
1087 | */ | ||
1088 | void | ||
1089 | xfs_dir_trace_g_du(char *where, xfs_inode_t *dp, uio_t *uio) | ||
1090 | { | ||
1091 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DU, where, | ||
1092 | (void *)dp, (void *)dp->i_mount, | ||
1093 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1094 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1095 | (void *)(unsigned long)uio->uio_resid, | ||
1096 | NULL, NULL, NULL, NULL, NULL, NULL, NULL); | ||
1097 | } | ||
1098 | |||
1099 | /* | ||
1100 | * Add a trace buffer entry for an inode and a uio. | ||
1101 | */ | ||
1102 | void | ||
1103 | xfs_dir_trace_g_dub(char *where, xfs_inode_t *dp, uio_t *uio, xfs_dablk_t bno) | ||
1104 | { | ||
1105 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUB, where, | ||
1106 | (void *)dp, (void *)dp->i_mount, | ||
1107 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1108 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1109 | (void *)(unsigned long)uio->uio_resid, | ||
1110 | (void *)(unsigned long)bno, | ||
1111 | NULL, NULL, NULL, NULL, NULL, NULL); | ||
1112 | } | ||
1113 | |||
1114 | /* | ||
1115 | * Add a trace buffer entry for an inode and a uio. | ||
1116 | */ | ||
1117 | void | ||
1118 | xfs_dir_trace_g_dun(char *where, xfs_inode_t *dp, uio_t *uio, | ||
1119 | xfs_da_intnode_t *node) | ||
1120 | { | ||
1121 | int last = be16_to_cpu(node->hdr.count) - 1; | ||
1122 | |||
1123 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUN, where, | ||
1124 | (void *)dp, (void *)dp->i_mount, | ||
1125 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1126 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1127 | (void *)(unsigned long)uio->uio_resid, | ||
1128 | (void *)(unsigned long)be32_to_cpu(node->hdr.info.forw), | ||
1129 | (void *)(unsigned long) | ||
1130 | be16_to_cpu(node->hdr.count), | ||
1131 | (void *)(unsigned long) | ||
1132 | be32_to_cpu(node->btree[0].hashval), | ||
1133 | (void *)(unsigned long) | ||
1134 | be32_to_cpu(node->btree[last].hashval), | ||
1135 | NULL, NULL, NULL); | ||
1136 | } | ||
1137 | |||
1138 | /* | ||
1139 | * Add a trace buffer entry for an inode and a uio. | ||
1140 | */ | ||
1141 | void | ||
1142 | xfs_dir_trace_g_dul(char *where, xfs_inode_t *dp, uio_t *uio, | ||
1143 | xfs_dir_leafblock_t *leaf) | ||
1144 | { | ||
1145 | int last = INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1; | ||
1146 | |||
1147 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUL, where, | ||
1148 | (void *)dp, (void *)dp->i_mount, | ||
1149 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1150 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1151 | (void *)(unsigned long)uio->uio_resid, | ||
1152 | (void *)(unsigned long)be32_to_cpu(leaf->hdr.info.forw), | ||
1153 | (void *)(unsigned long) | ||
1154 | INT_GET(leaf->hdr.count, ARCH_CONVERT), | ||
1155 | (void *)(unsigned long) | ||
1156 | INT_GET(leaf->entries[0].hashval, ARCH_CONVERT), | ||
1157 | (void *)(unsigned long) | ||
1158 | INT_GET(leaf->entries[last].hashval, ARCH_CONVERT), | ||
1159 | NULL, NULL, NULL); | ||
1160 | } | ||
1161 | |||
1162 | /* | ||
1163 | * Add a trace buffer entry for an inode and a uio. | ||
1164 | */ | ||
1165 | void | ||
1166 | xfs_dir_trace_g_due(char *where, xfs_inode_t *dp, uio_t *uio, | ||
1167 | xfs_dir_leaf_entry_t *entry) | ||
1168 | { | ||
1169 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUE, where, | ||
1170 | (void *)dp, (void *)dp->i_mount, | ||
1171 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1172 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1173 | (void *)(unsigned long)uio->uio_resid, | ||
1174 | (void *)(unsigned long) | ||
1175 | INT_GET(entry->hashval, ARCH_CONVERT), | ||
1176 | NULL, NULL, NULL, NULL, NULL, NULL); | ||
1177 | } | ||
1178 | |||
1179 | /* | ||
1180 | * Add a trace buffer entry for an inode and a uio. | ||
1181 | */ | ||
1182 | void | ||
1183 | xfs_dir_trace_g_duc(char *where, xfs_inode_t *dp, uio_t *uio, xfs_off_t cookie) | ||
1184 | { | ||
1185 | xfs_dir_trace_enter(XFS_DIR_KTRACE_G_DUC, where, | ||
1186 | (void *)dp, (void *)dp->i_mount, | ||
1187 | (void *)((unsigned long)(uio->uio_offset >> 32)), | ||
1188 | (void *)((unsigned long)(uio->uio_offset & 0xFFFFFFFF)), | ||
1189 | (void *)(unsigned long)uio->uio_resid, | ||
1190 | (void *)((unsigned long)(cookie >> 32)), | ||
1191 | (void *)((unsigned long)(cookie & 0xFFFFFFFF)), | ||
1192 | NULL, NULL, NULL, NULL, NULL); | ||
1193 | } | ||
1194 | |||
1195 | /* | ||
1196 | * Add a trace buffer entry for the arguments given to the routine, | ||
1197 | * generic form. | ||
1198 | */ | ||
1199 | void | ||
1200 | xfs_dir_trace_enter(int type, char *where, | ||
1201 | void * a0, void * a1, | ||
1202 | void * a2, void * a3, | ||
1203 | void * a4, void * a5, | ||
1204 | void * a6, void * a7, | ||
1205 | void * a8, void * a9, | ||
1206 | void * a10, void * a11) | ||
1207 | { | ||
1208 | ASSERT(xfs_dir_trace_buf); | ||
1209 | ktrace_enter(xfs_dir_trace_buf, (void *)(unsigned long)type, | ||
1210 | (void *)where, | ||
1211 | (void *)a0, (void *)a1, (void *)a2, | ||
1212 | (void *)a3, (void *)a4, (void *)a5, | ||
1213 | (void *)a6, (void *)a7, (void *)a8, | ||
1214 | (void *)a9, (void *)a10, (void *)a11, | ||
1215 | NULL, NULL); | ||
1216 | } | ||
1217 | #endif /* XFS_DIR_TRACE */ | ||
diff --git a/fs/xfs/xfs_dir.h b/fs/xfs/xfs_dir.h deleted file mode 100644 index 8cc8afb9f6c0..000000000000 --- a/fs/xfs/xfs_dir.h +++ /dev/null | |||
@@ -1,142 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DIR_H__ | ||
19 | #define __XFS_DIR_H__ | ||
20 | |||
21 | /* | ||
22 | * Large directories are structured around Btrees where all the data | ||
23 | * elements are in the leaf nodes. Filenames are hashed into an int, | ||
24 | * then that int is used as the index into the Btree. Since the hashval | ||
25 | * of a filename may not be unique, we may have duplicate keys. The | ||
26 | * internal links in the Btree are logical block offsets into the file. | ||
27 | * | ||
28 | * Small directories use a different format and are packed as tightly | ||
29 | * as possible so as to fit into the literal area of the inode. | ||
30 | */ | ||
31 | |||
32 | /*======================================================================== | ||
33 | * Function prototypes for the kernel. | ||
34 | *========================================================================*/ | ||
35 | |||
36 | struct uio; | ||
37 | struct xfs_bmap_free; | ||
38 | struct xfs_da_args; | ||
39 | struct xfs_dinode; | ||
40 | struct xfs_inode; | ||
41 | struct xfs_mount; | ||
42 | struct xfs_trans; | ||
43 | |||
44 | /* | ||
45 | * Directory function types. | ||
46 | * Put in structures (xfs_dirops_t) for v1 and v2 directories. | ||
47 | */ | ||
48 | typedef void (*xfs_dir_mount_t)(struct xfs_mount *mp); | ||
49 | typedef int (*xfs_dir_isempty_t)(struct xfs_inode *dp); | ||
50 | typedef int (*xfs_dir_init_t)(struct xfs_trans *tp, | ||
51 | struct xfs_inode *dp, | ||
52 | struct xfs_inode *pdp); | ||
53 | typedef int (*xfs_dir_createname_t)(struct xfs_trans *tp, | ||
54 | struct xfs_inode *dp, | ||
55 | char *name, | ||
56 | int namelen, | ||
57 | xfs_ino_t inum, | ||
58 | xfs_fsblock_t *first, | ||
59 | struct xfs_bmap_free *flist, | ||
60 | xfs_extlen_t total); | ||
61 | typedef int (*xfs_dir_lookup_t)(struct xfs_trans *tp, | ||
62 | struct xfs_inode *dp, | ||
63 | char *name, | ||
64 | int namelen, | ||
65 | xfs_ino_t *inum); | ||
66 | typedef int (*xfs_dir_removename_t)(struct xfs_trans *tp, | ||
67 | struct xfs_inode *dp, | ||
68 | char *name, | ||
69 | int namelen, | ||
70 | xfs_ino_t ino, | ||
71 | xfs_fsblock_t *first, | ||
72 | struct xfs_bmap_free *flist, | ||
73 | xfs_extlen_t total); | ||
74 | typedef int (*xfs_dir_getdents_t)(struct xfs_trans *tp, | ||
75 | struct xfs_inode *dp, | ||
76 | struct uio *uio, | ||
77 | int *eofp); | ||
78 | typedef int (*xfs_dir_replace_t)(struct xfs_trans *tp, | ||
79 | struct xfs_inode *dp, | ||
80 | char *name, | ||
81 | int namelen, | ||
82 | xfs_ino_t inum, | ||
83 | xfs_fsblock_t *first, | ||
84 | struct xfs_bmap_free *flist, | ||
85 | xfs_extlen_t total); | ||
86 | typedef int (*xfs_dir_canenter_t)(struct xfs_trans *tp, | ||
87 | struct xfs_inode *dp, | ||
88 | char *name, | ||
89 | int namelen); | ||
90 | typedef int (*xfs_dir_shortform_validate_ondisk_t)(struct xfs_mount *mp, | ||
91 | struct xfs_dinode *dip); | ||
92 | typedef int (*xfs_dir_shortform_to_single_t)(struct xfs_da_args *args); | ||
93 | |||
94 | typedef struct xfs_dirops { | ||
95 | xfs_dir_mount_t xd_mount; | ||
96 | xfs_dir_isempty_t xd_isempty; | ||
97 | xfs_dir_init_t xd_init; | ||
98 | xfs_dir_createname_t xd_createname; | ||
99 | xfs_dir_lookup_t xd_lookup; | ||
100 | xfs_dir_removename_t xd_removename; | ||
101 | xfs_dir_getdents_t xd_getdents; | ||
102 | xfs_dir_replace_t xd_replace; | ||
103 | xfs_dir_canenter_t xd_canenter; | ||
104 | xfs_dir_shortform_validate_ondisk_t xd_shortform_validate_ondisk; | ||
105 | xfs_dir_shortform_to_single_t xd_shortform_to_single; | ||
106 | } xfs_dirops_t; | ||
107 | |||
108 | /* | ||
109 | * Overall external interface routines. | ||
110 | */ | ||
111 | void xfs_dir_startup(void); /* called exactly once */ | ||
112 | |||
113 | #define XFS_DIR_MOUNT(mp) \ | ||
114 | ((mp)->m_dirops.xd_mount(mp)) | ||
115 | #define XFS_DIR_ISEMPTY(mp,dp) \ | ||
116 | ((mp)->m_dirops.xd_isempty(dp)) | ||
117 | #define XFS_DIR_INIT(mp,tp,dp,pdp) \ | ||
118 | ((mp)->m_dirops.xd_init(tp,dp,pdp)) | ||
119 | #define XFS_DIR_CREATENAME(mp,tp,dp,name,namelen,inum,first,flist,total) \ | ||
120 | ((mp)->m_dirops.xd_createname(tp,dp,name,namelen,inum,first,flist,\ | ||
121 | total)) | ||
122 | #define XFS_DIR_LOOKUP(mp,tp,dp,name,namelen,inum) \ | ||
123 | ((mp)->m_dirops.xd_lookup(tp,dp,name,namelen,inum)) | ||
124 | #define XFS_DIR_REMOVENAME(mp,tp,dp,name,namelen,ino,first,flist,total) \ | ||
125 | ((mp)->m_dirops.xd_removename(tp,dp,name,namelen,ino,first,flist,total)) | ||
126 | #define XFS_DIR_GETDENTS(mp,tp,dp,uio,eofp) \ | ||
127 | ((mp)->m_dirops.xd_getdents(tp,dp,uio,eofp)) | ||
128 | #define XFS_DIR_REPLACE(mp,tp,dp,name,namelen,inum,first,flist,total) \ | ||
129 | ((mp)->m_dirops.xd_replace(tp,dp,name,namelen,inum,first,flist,total)) | ||
130 | #define XFS_DIR_CANENTER(mp,tp,dp,name,namelen) \ | ||
131 | ((mp)->m_dirops.xd_canenter(tp,dp,name,namelen)) | ||
132 | #define XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp,dip) \ | ||
133 | ((mp)->m_dirops.xd_shortform_validate_ondisk(mp,dip)) | ||
134 | #define XFS_DIR_SHORTFORM_TO_SINGLE(mp,args) \ | ||
135 | ((mp)->m_dirops.xd_shortform_to_single(args)) | ||
136 | |||
137 | #define XFS_DIR_IS_V1(mp) ((mp)->m_dirversion == 1) | ||
138 | #define XFS_DIR_IS_V2(mp) ((mp)->m_dirversion == 2) | ||
139 | extern xfs_dirops_t xfsv1_dirops; | ||
140 | extern xfs_dirops_t xfsv2_dirops; | ||
141 | |||
142 | #endif /* __XFS_DIR_H__ */ | ||
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 022c8398ab62..8edbe1adb95b 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -24,21 +24,18 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_da_btree.h" | 30 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
38 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
39 | #include "xfs_inode_item.h" | 37 | #include "xfs_inode_item.h" |
40 | #include "xfs_bmap.h" | 38 | #include "xfs_bmap.h" |
41 | #include "xfs_dir_leaf.h" | ||
42 | #include "xfs_dir2_data.h" | 39 | #include "xfs_dir2_data.h" |
43 | #include "xfs_dir2_leaf.h" | 40 | #include "xfs_dir2_leaf.h" |
44 | #include "xfs_dir2_block.h" | 41 | #include "xfs_dir2_block.h" |
@@ -46,69 +43,14 @@ | |||
46 | #include "xfs_dir2_trace.h" | 43 | #include "xfs_dir2_trace.h" |
47 | #include "xfs_error.h" | 44 | #include "xfs_error.h" |
48 | 45 | ||
49 | /* | ||
50 | * Declarations for interface routines. | ||
51 | */ | ||
52 | static void xfs_dir2_mount(xfs_mount_t *mp); | ||
53 | static int xfs_dir2_isempty(xfs_inode_t *dp); | ||
54 | static int xfs_dir2_init(xfs_trans_t *tp, xfs_inode_t *dp, | ||
55 | xfs_inode_t *pdp); | ||
56 | static int xfs_dir2_createname(xfs_trans_t *tp, xfs_inode_t *dp, | ||
57 | char *name, int namelen, xfs_ino_t inum, | ||
58 | xfs_fsblock_t *first, | ||
59 | xfs_bmap_free_t *flist, xfs_extlen_t total); | ||
60 | static int xfs_dir2_lookup(xfs_trans_t *tp, xfs_inode_t *dp, char *name, | ||
61 | int namelen, xfs_ino_t *inum); | ||
62 | static int xfs_dir2_removename(xfs_trans_t *tp, xfs_inode_t *dp, | ||
63 | char *name, int namelen, xfs_ino_t ino, | ||
64 | xfs_fsblock_t *first, | ||
65 | xfs_bmap_free_t *flist, xfs_extlen_t total); | ||
66 | static int xfs_dir2_getdents(xfs_trans_t *tp, xfs_inode_t *dp, uio_t *uio, | ||
67 | int *eofp); | ||
68 | static int xfs_dir2_replace(xfs_trans_t *tp, xfs_inode_t *dp, char *name, | ||
69 | int namelen, xfs_ino_t inum, | ||
70 | xfs_fsblock_t *first, xfs_bmap_free_t *flist, | ||
71 | xfs_extlen_t total); | ||
72 | static int xfs_dir2_canenter(xfs_trans_t *tp, xfs_inode_t *dp, char *name, | ||
73 | int namelen); | ||
74 | static int xfs_dir2_shortform_validate_ondisk(xfs_mount_t *mp, | ||
75 | xfs_dinode_t *dip); | ||
76 | |||
77 | /* | ||
78 | * Utility routine declarations. | ||
79 | */ | ||
80 | static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); | 46 | static int xfs_dir2_put_dirent64_direct(xfs_dir2_put_args_t *pa); |
81 | static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); | 47 | static int xfs_dir2_put_dirent64_uio(xfs_dir2_put_args_t *pa); |
82 | 48 | ||
83 | /* | 49 | void |
84 | * Directory operations vector. | 50 | xfs_dir_mount( |
85 | */ | 51 | xfs_mount_t *mp) |
86 | xfs_dirops_t xfsv2_dirops = { | ||
87 | .xd_mount = xfs_dir2_mount, | ||
88 | .xd_isempty = xfs_dir2_isempty, | ||
89 | .xd_init = xfs_dir2_init, | ||
90 | .xd_createname = xfs_dir2_createname, | ||
91 | .xd_lookup = xfs_dir2_lookup, | ||
92 | .xd_removename = xfs_dir2_removename, | ||
93 | .xd_getdents = xfs_dir2_getdents, | ||
94 | .xd_replace = xfs_dir2_replace, | ||
95 | .xd_canenter = xfs_dir2_canenter, | ||
96 | .xd_shortform_validate_ondisk = xfs_dir2_shortform_validate_ondisk, | ||
97 | .xd_shortform_to_single = xfs_dir2_sf_to_block, | ||
98 | }; | ||
99 | |||
100 | /* | ||
101 | * Interface routines. | ||
102 | */ | ||
103 | |||
104 | /* | ||
105 | * Initialize directory-related fields in the mount structure. | ||
106 | */ | ||
107 | static void | ||
108 | xfs_dir2_mount( | ||
109 | xfs_mount_t *mp) /* filesystem mount point */ | ||
110 | { | 52 | { |
111 | mp->m_dirversion = 2; | 53 | ASSERT(XFS_SB_VERSION_HASDIRV2(&mp->m_sb)); |
112 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= | 54 | ASSERT((1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog)) <= |
113 | XFS_MAX_BLOCKSIZE); | 55 | XFS_MAX_BLOCKSIZE); |
114 | mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); | 56 | mp->m_dirblksize = 1 << (mp->m_sb.sb_blocklog + mp->m_sb.sb_dirblklog); |
@@ -128,19 +70,15 @@ xfs_dir2_mount( | |||
128 | /* | 70 | /* |
129 | * Return 1 if directory contains only "." and "..". | 71 | * Return 1 if directory contains only "." and "..". |
130 | */ | 72 | */ |
131 | static int /* return code */ | 73 | int |
132 | xfs_dir2_isempty( | 74 | xfs_dir_isempty( |
133 | xfs_inode_t *dp) /* incore inode structure */ | 75 | xfs_inode_t *dp) |
134 | { | 76 | { |
135 | xfs_dir2_sf_t *sfp; /* shortform directory structure */ | 77 | xfs_dir2_sf_t *sfp; |
136 | 78 | ||
137 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 79 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
138 | /* | 80 | if (dp->i_d.di_size == 0) /* might happen during shutdown. */ |
139 | * Might happen during shutdown. | ||
140 | */ | ||
141 | if (dp->i_d.di_size == 0) { | ||
142 | return 1; | 81 | return 1; |
143 | } | ||
144 | if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) | 82 | if (dp->i_d.di_size > XFS_IFORK_DSIZE(dp)) |
145 | return 0; | 83 | return 0; |
146 | sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; | 84 | sfp = (xfs_dir2_sf_t *)dp->i_df.if_u1.if_data; |
@@ -148,53 +86,83 @@ xfs_dir2_isempty( | |||
148 | } | 86 | } |
149 | 87 | ||
150 | /* | 88 | /* |
89 | * Validate a given inode number. | ||
90 | */ | ||
91 | int | ||
92 | xfs_dir_ino_validate( | ||
93 | xfs_mount_t *mp, | ||
94 | xfs_ino_t ino) | ||
95 | { | ||
96 | xfs_agblock_t agblkno; | ||
97 | xfs_agino_t agino; | ||
98 | xfs_agnumber_t agno; | ||
99 | int ino_ok; | ||
100 | int ioff; | ||
101 | |||
102 | agno = XFS_INO_TO_AGNO(mp, ino); | ||
103 | agblkno = XFS_INO_TO_AGBNO(mp, ino); | ||
104 | ioff = XFS_INO_TO_OFFSET(mp, ino); | ||
105 | agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); | ||
106 | ino_ok = | ||
107 | agno < mp->m_sb.sb_agcount && | ||
108 | agblkno < mp->m_sb.sb_agblocks && | ||
109 | agblkno != 0 && | ||
110 | ioff < (1 << mp->m_sb.sb_inopblog) && | ||
111 | XFS_AGINO_TO_INO(mp, agno, agino) == ino; | ||
112 | if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, | ||
113 | XFS_RANDOM_DIR_INO_VALIDATE))) { | ||
114 | xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", | ||
115 | (unsigned long long) ino); | ||
116 | XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); | ||
117 | return XFS_ERROR(EFSCORRUPTED); | ||
118 | } | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | /* | ||
151 | * Initialize a directory with its "." and ".." entries. | 123 | * Initialize a directory with its "." and ".." entries. |
152 | */ | 124 | */ |
153 | static int /* error */ | 125 | int |
154 | xfs_dir2_init( | 126 | xfs_dir_init( |
155 | xfs_trans_t *tp, /* transaction pointer */ | 127 | xfs_trans_t *tp, |
156 | xfs_inode_t *dp, /* incore directory inode */ | 128 | xfs_inode_t *dp, |
157 | xfs_inode_t *pdp) /* incore parent directory inode */ | 129 | xfs_inode_t *pdp) |
158 | { | 130 | { |
159 | xfs_da_args_t args; /* operation arguments */ | 131 | xfs_da_args_t args; |
160 | int error; /* error return value */ | 132 | int error; |
161 | 133 | ||
162 | memset((char *)&args, 0, sizeof(args)); | 134 | memset((char *)&args, 0, sizeof(args)); |
163 | args.dp = dp; | 135 | args.dp = dp; |
164 | args.trans = tp; | 136 | args.trans = tp; |
165 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 137 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
166 | if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) { | 138 | if ((error = xfs_dir_ino_validate(tp->t_mountp, pdp->i_ino))) |
167 | return error; | 139 | return error; |
168 | } | ||
169 | return xfs_dir2_sf_create(&args, pdp->i_ino); | 140 | return xfs_dir2_sf_create(&args, pdp->i_ino); |
170 | } | 141 | } |
171 | 142 | ||
172 | /* | 143 | /* |
173 | Enter a name in a directory. | 144 | Enter a name in a directory. |
174 | */ | 145 | */ |
175 | static int /* error */ | 146 | int |
176 | xfs_dir2_createname( | 147 | xfs_dir_createname( |
177 | xfs_trans_t *tp, /* transaction pointer */ | 148 | xfs_trans_t *tp, |
178 | xfs_inode_t *dp, /* incore directory inode */ | 149 | xfs_inode_t *dp, |
179 | char *name, /* new entry name */ | 150 | char *name, |
180 | int namelen, /* new entry name length */ | 151 | int namelen, |
181 | xfs_ino_t inum, /* new entry inode number */ | 152 | xfs_ino_t inum, /* new entry inode number */ |
182 | xfs_fsblock_t *first, /* bmap's firstblock */ | 153 | xfs_fsblock_t *first, /* bmap's firstblock */ |
183 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 154 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
184 | xfs_extlen_t total) /* bmap's total block count */ | 155 | xfs_extlen_t total) /* bmap's total block count */ |
185 | { | 156 | { |
186 | xfs_da_args_t args; /* operation arguments */ | 157 | xfs_da_args_t args; |
187 | int rval; /* return value */ | 158 | int rval; |
188 | int v; /* type-checking value */ | 159 | int v; /* type-checking value */ |
189 | 160 | ||
190 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 161 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
191 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { | 162 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) |
192 | return rval; | 163 | return rval; |
193 | } | ||
194 | XFS_STATS_INC(xs_dir_create); | 164 | XFS_STATS_INC(xs_dir_create); |
195 | /* | 165 | |
196 | * Fill in the arg structure for this request. | ||
197 | */ | ||
198 | args.name = name; | 166 | args.name = name; |
199 | args.namelen = namelen; | 167 | args.namelen = namelen; |
200 | args.hashval = xfs_da_hashname(name, namelen); | 168 | args.hashval = xfs_da_hashname(name, namelen); |
@@ -207,18 +175,16 @@ xfs_dir2_createname( | |||
207 | args.trans = tp; | 175 | args.trans = tp; |
208 | args.justcheck = 0; | 176 | args.justcheck = 0; |
209 | args.addname = args.oknoent = 1; | 177 | args.addname = args.oknoent = 1; |
210 | /* | 178 | |
211 | * Decide on what work routines to call based on the inode size. | ||
212 | */ | ||
213 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 179 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
214 | rval = xfs_dir2_sf_addname(&args); | 180 | rval = xfs_dir2_sf_addname(&args); |
215 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 181 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
216 | return rval; | 182 | return rval; |
217 | } else if (v) | 183 | else if (v) |
218 | rval = xfs_dir2_block_addname(&args); | 184 | rval = xfs_dir2_block_addname(&args); |
219 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { | 185 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) |
220 | return rval; | 186 | return rval; |
221 | } else if (v) | 187 | else if (v) |
222 | rval = xfs_dir2_leaf_addname(&args); | 188 | rval = xfs_dir2_leaf_addname(&args); |
223 | else | 189 | else |
224 | rval = xfs_dir2_node_addname(&args); | 190 | rval = xfs_dir2_node_addname(&args); |
@@ -228,24 +194,21 @@ xfs_dir2_createname( | |||
228 | /* | 194 | /* |
229 | * Lookup a name in a directory, give back the inode number. | 195 | * Lookup a name in a directory, give back the inode number. |
230 | */ | 196 | */ |
231 | static int /* error */ | 197 | int |
232 | xfs_dir2_lookup( | 198 | xfs_dir_lookup( |
233 | xfs_trans_t *tp, /* transaction pointer */ | 199 | xfs_trans_t *tp, |
234 | xfs_inode_t *dp, /* incore directory inode */ | 200 | xfs_inode_t *dp, |
235 | char *name, /* lookup name */ | 201 | char *name, |
236 | int namelen, /* lookup name length */ | 202 | int namelen, |
237 | xfs_ino_t *inum) /* out: inode number */ | 203 | xfs_ino_t *inum) /* out: inode number */ |
238 | { | 204 | { |
239 | xfs_da_args_t args; /* operation arguments */ | 205 | xfs_da_args_t args; |
240 | int rval; /* return value */ | 206 | int rval; |
241 | int v; /* type-checking value */ | 207 | int v; /* type-checking value */ |
242 | 208 | ||
243 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 209 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
244 | XFS_STATS_INC(xs_dir_lookup); | 210 | XFS_STATS_INC(xs_dir_lookup); |
245 | 211 | ||
246 | /* | ||
247 | * Fill in the arg structure for this request. | ||
248 | */ | ||
249 | args.name = name; | 212 | args.name = name; |
250 | args.namelen = namelen; | 213 | args.namelen = namelen; |
251 | args.hashval = xfs_da_hashname(name, namelen); | 214 | args.hashval = xfs_da_hashname(name, namelen); |
@@ -258,18 +221,16 @@ xfs_dir2_lookup( | |||
258 | args.trans = tp; | 221 | args.trans = tp; |
259 | args.justcheck = args.addname = 0; | 222 | args.justcheck = args.addname = 0; |
260 | args.oknoent = 1; | 223 | args.oknoent = 1; |
261 | /* | 224 | |
262 | * Decide on what work routines to call based on the inode size. | ||
263 | */ | ||
264 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 225 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
265 | rval = xfs_dir2_sf_lookup(&args); | 226 | rval = xfs_dir2_sf_lookup(&args); |
266 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 227 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
267 | return rval; | 228 | return rval; |
268 | } else if (v) | 229 | else if (v) |
269 | rval = xfs_dir2_block_lookup(&args); | 230 | rval = xfs_dir2_block_lookup(&args); |
270 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { | 231 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) |
271 | return rval; | 232 | return rval; |
272 | } else if (v) | 233 | else if (v) |
273 | rval = xfs_dir2_leaf_lookup(&args); | 234 | rval = xfs_dir2_leaf_lookup(&args); |
274 | else | 235 | else |
275 | rval = xfs_dir2_node_lookup(&args); | 236 | rval = xfs_dir2_node_lookup(&args); |
@@ -283,26 +244,24 @@ xfs_dir2_lookup( | |||
283 | /* | 244 | /* |
284 | * Remove an entry from a directory. | 245 | * Remove an entry from a directory. |
285 | */ | 246 | */ |
286 | static int /* error */ | 247 | int |
287 | xfs_dir2_removename( | 248 | xfs_dir_removename( |
288 | xfs_trans_t *tp, /* transaction pointer */ | 249 | xfs_trans_t *tp, |
289 | xfs_inode_t *dp, /* incore directory inode */ | 250 | xfs_inode_t *dp, |
290 | char *name, /* name of entry to remove */ | 251 | char *name, |
291 | int namelen, /* name length of entry to remove */ | 252 | int namelen, |
292 | xfs_ino_t ino, /* inode number of entry to remove */ | 253 | xfs_ino_t ino, |
293 | xfs_fsblock_t *first, /* bmap's firstblock */ | 254 | xfs_fsblock_t *first, /* bmap's firstblock */ |
294 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 255 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
295 | xfs_extlen_t total) /* bmap's total block count */ | 256 | xfs_extlen_t total) /* bmap's total block count */ |
296 | { | 257 | { |
297 | xfs_da_args_t args; /* operation arguments */ | 258 | xfs_da_args_t args; |
298 | int rval; /* return value */ | 259 | int rval; |
299 | int v; /* type-checking value */ | 260 | int v; /* type-checking value */ |
300 | 261 | ||
301 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 262 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
302 | XFS_STATS_INC(xs_dir_remove); | 263 | XFS_STATS_INC(xs_dir_remove); |
303 | /* | 264 | |
304 | * Fill in the arg structure for this request. | ||
305 | */ | ||
306 | args.name = name; | 265 | args.name = name; |
307 | args.namelen = namelen; | 266 | args.namelen = namelen; |
308 | args.hashval = xfs_da_hashname(name, namelen); | 267 | args.hashval = xfs_da_hashname(name, namelen); |
@@ -314,18 +273,16 @@ xfs_dir2_removename( | |||
314 | args.whichfork = XFS_DATA_FORK; | 273 | args.whichfork = XFS_DATA_FORK; |
315 | args.trans = tp; | 274 | args.trans = tp; |
316 | args.justcheck = args.addname = args.oknoent = 0; | 275 | args.justcheck = args.addname = args.oknoent = 0; |
317 | /* | 276 | |
318 | * Decide on what work routines to call based on the inode size. | ||
319 | */ | ||
320 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 277 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
321 | rval = xfs_dir2_sf_removename(&args); | 278 | rval = xfs_dir2_sf_removename(&args); |
322 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 279 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
323 | return rval; | 280 | return rval; |
324 | } else if (v) | 281 | else if (v) |
325 | rval = xfs_dir2_block_removename(&args); | 282 | rval = xfs_dir2_block_removename(&args); |
326 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { | 283 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) |
327 | return rval; | 284 | return rval; |
328 | } else if (v) | 285 | else if (v) |
329 | rval = xfs_dir2_leaf_removename(&args); | 286 | rval = xfs_dir2_leaf_removename(&args); |
330 | else | 287 | else |
331 | rval = xfs_dir2_node_removename(&args); | 288 | rval = xfs_dir2_node_removename(&args); |
@@ -335,10 +292,10 @@ xfs_dir2_removename( | |||
335 | /* | 292 | /* |
336 | * Read a directory. | 293 | * Read a directory. |
337 | */ | 294 | */ |
338 | static int /* error */ | 295 | int |
339 | xfs_dir2_getdents( | 296 | xfs_dir_getdents( |
340 | xfs_trans_t *tp, /* transaction pointer */ | 297 | xfs_trans_t *tp, |
341 | xfs_inode_t *dp, /* incore directory inode */ | 298 | xfs_inode_t *dp, |
342 | uio_t *uio, /* caller's buffer control */ | 299 | uio_t *uio, /* caller's buffer control */ |
343 | int *eofp) /* out: eof reached */ | 300 | int *eofp) /* out: eof reached */ |
344 | { | 301 | { |
@@ -367,14 +324,11 @@ xfs_dir2_getdents( | |||
367 | } | 324 | } |
368 | 325 | ||
369 | *eofp = 0; | 326 | *eofp = 0; |
370 | /* | ||
371 | * Decide on what work routines to call based on the inode size. | ||
372 | */ | ||
373 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 327 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
374 | rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); | 328 | rval = xfs_dir2_sf_getdents(dp, uio, eofp, dbp, put); |
375 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 329 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
376 | ; | 330 | ; |
377 | } else if (v) | 331 | else if (v) |
378 | rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); | 332 | rval = xfs_dir2_block_getdents(tp, dp, uio, eofp, dbp, put); |
379 | else | 333 | else |
380 | rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); | 334 | rval = xfs_dir2_leaf_getdents(tp, dp, uio, eofp, dbp, put); |
@@ -386,29 +340,26 @@ xfs_dir2_getdents( | |||
386 | /* | 340 | /* |
387 | * Replace the inode number of a directory entry. | 341 | * Replace the inode number of a directory entry. |
388 | */ | 342 | */ |
389 | static int /* error */ | 343 | int |
390 | xfs_dir2_replace( | 344 | xfs_dir_replace( |
391 | xfs_trans_t *tp, /* transaction pointer */ | 345 | xfs_trans_t *tp, |
392 | xfs_inode_t *dp, /* incore directory inode */ | 346 | xfs_inode_t *dp, |
393 | char *name, /* name of entry to replace */ | 347 | char *name, /* name of entry to replace */ |
394 | int namelen, /* name length of entry to replace */ | 348 | int namelen, |
395 | xfs_ino_t inum, /* new inode number */ | 349 | xfs_ino_t inum, /* new inode number */ |
396 | xfs_fsblock_t *first, /* bmap's firstblock */ | 350 | xfs_fsblock_t *first, /* bmap's firstblock */ |
397 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ | 351 | xfs_bmap_free_t *flist, /* bmap's freeblock list */ |
398 | xfs_extlen_t total) /* bmap's total block count */ | 352 | xfs_extlen_t total) /* bmap's total block count */ |
399 | { | 353 | { |
400 | xfs_da_args_t args; /* operation arguments */ | 354 | xfs_da_args_t args; |
401 | int rval; /* return value */ | 355 | int rval; |
402 | int v; /* type-checking value */ | 356 | int v; /* type-checking value */ |
403 | 357 | ||
404 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 358 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
405 | 359 | ||
406 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) { | 360 | if ((rval = xfs_dir_ino_validate(tp->t_mountp, inum))) |
407 | return rval; | 361 | return rval; |
408 | } | 362 | |
409 | /* | ||
410 | * Fill in the arg structure for this request. | ||
411 | */ | ||
412 | args.name = name; | 363 | args.name = name; |
413 | args.namelen = namelen; | 364 | args.namelen = namelen; |
414 | args.hashval = xfs_da_hashname(name, namelen); | 365 | args.hashval = xfs_da_hashname(name, namelen); |
@@ -420,18 +371,16 @@ xfs_dir2_replace( | |||
420 | args.whichfork = XFS_DATA_FORK; | 371 | args.whichfork = XFS_DATA_FORK; |
421 | args.trans = tp; | 372 | args.trans = tp; |
422 | args.justcheck = args.addname = args.oknoent = 0; | 373 | args.justcheck = args.addname = args.oknoent = 0; |
423 | /* | 374 | |
424 | * Decide on what work routines to call based on the inode size. | ||
425 | */ | ||
426 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 375 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
427 | rval = xfs_dir2_sf_replace(&args); | 376 | rval = xfs_dir2_sf_replace(&args); |
428 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 377 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
429 | return rval; | 378 | return rval; |
430 | } else if (v) | 379 | else if (v) |
431 | rval = xfs_dir2_block_replace(&args); | 380 | rval = xfs_dir2_block_replace(&args); |
432 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { | 381 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) |
433 | return rval; | 382 | return rval; |
434 | } else if (v) | 383 | else if (v) |
435 | rval = xfs_dir2_leaf_replace(&args); | 384 | rval = xfs_dir2_leaf_replace(&args); |
436 | else | 385 | else |
437 | rval = xfs_dir2_node_replace(&args); | 386 | rval = xfs_dir2_node_replace(&args); |
@@ -441,21 +390,19 @@ xfs_dir2_replace( | |||
441 | /* | 390 | /* |
442 | * See if this entry can be added to the directory without allocating space. | 391 | * See if this entry can be added to the directory without allocating space. |
443 | */ | 392 | */ |
444 | static int /* error */ | 393 | int |
445 | xfs_dir2_canenter( | 394 | xfs_dir_canenter( |
446 | xfs_trans_t *tp, /* transaction pointer */ | 395 | xfs_trans_t *tp, |
447 | xfs_inode_t *dp, /* incore directory inode */ | 396 | xfs_inode_t *dp, |
448 | char *name, /* name of entry to add */ | 397 | char *name, /* name of entry to add */ |
449 | int namelen) /* name length of entry to add */ | 398 | int namelen) |
450 | { | 399 | { |
451 | xfs_da_args_t args; /* operation arguments */ | 400 | xfs_da_args_t args; |
452 | int rval; /* return value */ | 401 | int rval; |
453 | int v; /* type-checking value */ | 402 | int v; /* type-checking value */ |
454 | 403 | ||
455 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); | 404 | ASSERT((dp->i_d.di_mode & S_IFMT) == S_IFDIR); |
456 | /* | 405 | |
457 | * Fill in the arg structure for this request. | ||
458 | */ | ||
459 | args.name = name; | 406 | args.name = name; |
460 | args.namelen = namelen; | 407 | args.namelen = namelen; |
461 | args.hashval = xfs_da_hashname(name, namelen); | 408 | args.hashval = xfs_da_hashname(name, namelen); |
@@ -467,18 +414,16 @@ xfs_dir2_canenter( | |||
467 | args.whichfork = XFS_DATA_FORK; | 414 | args.whichfork = XFS_DATA_FORK; |
468 | args.trans = tp; | 415 | args.trans = tp; |
469 | args.justcheck = args.addname = args.oknoent = 1; | 416 | args.justcheck = args.addname = args.oknoent = 1; |
470 | /* | 417 | |
471 | * Decide on what work routines to call based on the inode size. | ||
472 | */ | ||
473 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) | 418 | if (dp->i_d.di_format == XFS_DINODE_FMT_LOCAL) |
474 | rval = xfs_dir2_sf_addname(&args); | 419 | rval = xfs_dir2_sf_addname(&args); |
475 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) { | 420 | else if ((rval = xfs_dir2_isblock(tp, dp, &v))) |
476 | return rval; | 421 | return rval; |
477 | } else if (v) | 422 | else if (v) |
478 | rval = xfs_dir2_block_addname(&args); | 423 | rval = xfs_dir2_block_addname(&args); |
479 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) { | 424 | else if ((rval = xfs_dir2_isleaf(tp, dp, &v))) |
480 | return rval; | 425 | return rval; |
481 | } else if (v) | 426 | else if (v) |
482 | rval = xfs_dir2_leaf_addname(&args); | 427 | rval = xfs_dir2_leaf_addname(&args); |
483 | else | 428 | else |
484 | rval = xfs_dir2_node_addname(&args); | 429 | rval = xfs_dir2_node_addname(&args); |
@@ -486,19 +431,6 @@ xfs_dir2_canenter( | |||
486 | } | 431 | } |
487 | 432 | ||
488 | /* | 433 | /* |
489 | * Dummy routine for shortform inode validation. | ||
490 | * Can't really do this. | ||
491 | */ | ||
492 | /* ARGSUSED */ | ||
493 | static int /* error */ | ||
494 | xfs_dir2_shortform_validate_ondisk( | ||
495 | xfs_mount_t *mp, /* filesystem mount point */ | ||
496 | xfs_dinode_t *dip) /* ondisk inode */ | ||
497 | { | ||
498 | return 0; | ||
499 | } | ||
500 | |||
501 | /* | ||
502 | * Utility routines. | 434 | * Utility routines. |
503 | */ | 435 | */ |
504 | 436 | ||
@@ -507,24 +439,24 @@ xfs_dir2_shortform_validate_ondisk( | |||
507 | * This routine is for data and free blocks, not leaf/node blocks | 439 | * This routine is for data and free blocks, not leaf/node blocks |
508 | * which are handled by xfs_da_grow_inode. | 440 | * which are handled by xfs_da_grow_inode. |
509 | */ | 441 | */ |
510 | int /* error */ | 442 | int |
511 | xfs_dir2_grow_inode( | 443 | xfs_dir2_grow_inode( |
512 | xfs_da_args_t *args, /* operation arguments */ | 444 | xfs_da_args_t *args, |
513 | int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ | 445 | int space, /* v2 dir's space XFS_DIR2_xxx_SPACE */ |
514 | xfs_dir2_db_t *dbp) /* out: block number added */ | 446 | xfs_dir2_db_t *dbp) /* out: block number added */ |
515 | { | 447 | { |
516 | xfs_fileoff_t bno; /* directory offset of new block */ | 448 | xfs_fileoff_t bno; /* directory offset of new block */ |
517 | int count; /* count of filesystem blocks */ | 449 | int count; /* count of filesystem blocks */ |
518 | xfs_inode_t *dp; /* incore directory inode */ | 450 | xfs_inode_t *dp; /* incore directory inode */ |
519 | int error; /* error return value */ | 451 | int error; |
520 | int got; /* blocks actually mapped */ | 452 | int got; /* blocks actually mapped */ |
521 | int i; /* temp mapping index */ | 453 | int i; |
522 | xfs_bmbt_irec_t map; /* single structure for bmap */ | 454 | xfs_bmbt_irec_t map; /* single structure for bmap */ |
523 | int mapi; /* mapping index */ | 455 | int mapi; /* mapping index */ |
524 | xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ | 456 | xfs_bmbt_irec_t *mapp; /* bmap mapping structure(s) */ |
525 | xfs_mount_t *mp; /* filesystem mount point */ | 457 | xfs_mount_t *mp; |
526 | int nmap; /* number of bmap entries */ | 458 | int nmap; /* number of bmap entries */ |
527 | xfs_trans_t *tp; /* transaction pointer */ | 459 | xfs_trans_t *tp; |
528 | 460 | ||
529 | xfs_dir2_trace_args_s("grow_inode", args, space); | 461 | xfs_dir2_trace_args_s("grow_inode", args, space); |
530 | dp = args->dp; | 462 | dp = args->dp; |
@@ -538,9 +470,8 @@ xfs_dir2_grow_inode( | |||
538 | /* | 470 | /* |
539 | * Find the first hole for our block. | 471 | * Find the first hole for our block. |
540 | */ | 472 | */ |
541 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) { | 473 | if ((error = xfs_bmap_first_unused(tp, dp, count, &bno, XFS_DATA_FORK))) |
542 | return error; | 474 | return error; |
543 | } | ||
544 | nmap = 1; | 475 | nmap = 1; |
545 | ASSERT(args->firstblock != NULL); | 476 | ASSERT(args->firstblock != NULL); |
546 | /* | 477 | /* |
@@ -549,13 +480,9 @@ xfs_dir2_grow_inode( | |||
549 | if ((error = xfs_bmapi(tp, dp, bno, count, | 480 | if ((error = xfs_bmapi(tp, dp, bno, count, |
550 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, | 481 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA|XFS_BMAPI_CONTIG, |
551 | args->firstblock, args->total, &map, &nmap, | 482 | args->firstblock, args->total, &map, &nmap, |
552 | args->flist))) { | 483 | args->flist, NULL))) |
553 | return error; | 484 | return error; |
554 | } | ||
555 | ASSERT(nmap <= 1); | 485 | ASSERT(nmap <= 1); |
556 | /* | ||
557 | * Got it in 1. | ||
558 | */ | ||
559 | if (nmap == 1) { | 486 | if (nmap == 1) { |
560 | mapp = ↦ | 487 | mapp = ↦ |
561 | mapi = 1; | 488 | mapi = 1; |
@@ -585,7 +512,8 @@ xfs_dir2_grow_inode( | |||
585 | if ((error = xfs_bmapi(tp, dp, b, c, | 512 | if ((error = xfs_bmapi(tp, dp, b, c, |
586 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, | 513 | XFS_BMAPI_WRITE|XFS_BMAPI_METADATA, |
587 | args->firstblock, args->total, | 514 | args->firstblock, args->total, |
588 | &mapp[mapi], &nmap, args->flist))) { | 515 | &mapp[mapi], &nmap, args->flist, |
516 | NULL))) { | ||
589 | kmem_free(mapp, sizeof(*mapp) * count); | 517 | kmem_free(mapp, sizeof(*mapp) * count); |
590 | return error; | 518 | return error; |
591 | } | 519 | } |
@@ -645,20 +573,19 @@ xfs_dir2_grow_inode( | |||
645 | /* | 573 | /* |
646 | * See if the directory is a single-block form directory. | 574 | * See if the directory is a single-block form directory. |
647 | */ | 575 | */ |
648 | int /* error */ | 576 | int |
649 | xfs_dir2_isblock( | 577 | xfs_dir2_isblock( |
650 | xfs_trans_t *tp, /* transaction pointer */ | 578 | xfs_trans_t *tp, |
651 | xfs_inode_t *dp, /* incore directory inode */ | 579 | xfs_inode_t *dp, |
652 | int *vp) /* out: 1 is block, 0 is not block */ | 580 | int *vp) /* out: 1 is block, 0 is not block */ |
653 | { | 581 | { |
654 | xfs_fileoff_t last; /* last file offset */ | 582 | xfs_fileoff_t last; /* last file offset */ |
655 | xfs_mount_t *mp; /* filesystem mount point */ | 583 | xfs_mount_t *mp; |
656 | int rval; /* return value */ | 584 | int rval; |
657 | 585 | ||
658 | mp = dp->i_mount; | 586 | mp = dp->i_mount; |
659 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { | 587 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) |
660 | return rval; | 588 | return rval; |
661 | } | ||
662 | rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; | 589 | rval = XFS_FSB_TO_B(mp, last) == mp->m_dirblksize; |
663 | ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); | 590 | ASSERT(rval == 0 || dp->i_d.di_size == mp->m_dirblksize); |
664 | *vp = rval; | 591 | *vp = rval; |
@@ -668,20 +595,19 @@ xfs_dir2_isblock( | |||
668 | /* | 595 | /* |
669 | * See if the directory is a single-leaf form directory. | 596 | * See if the directory is a single-leaf form directory. |
670 | */ | 597 | */ |
671 | int /* error */ | 598 | int |
672 | xfs_dir2_isleaf( | 599 | xfs_dir2_isleaf( |
673 | xfs_trans_t *tp, /* transaction pointer */ | 600 | xfs_trans_t *tp, |
674 | xfs_inode_t *dp, /* incore directory inode */ | 601 | xfs_inode_t *dp, |
675 | int *vp) /* out: 1 is leaf, 0 is not leaf */ | 602 | int *vp) /* out: 1 is leaf, 0 is not leaf */ |
676 | { | 603 | { |
677 | xfs_fileoff_t last; /* last file offset */ | 604 | xfs_fileoff_t last; /* last file offset */ |
678 | xfs_mount_t *mp; /* filesystem mount point */ | 605 | xfs_mount_t *mp; |
679 | int rval; /* return value */ | 606 | int rval; |
680 | 607 | ||
681 | mp = dp->i_mount; | 608 | mp = dp->i_mount; |
682 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) { | 609 | if ((rval = xfs_bmap_last_offset(tp, dp, &last, XFS_DATA_FORK))) |
683 | return rval; | 610 | return rval; |
684 | } | ||
685 | *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); | 611 | *vp = last == mp->m_dirleafblk + (1 << mp->m_sb.sb_dirblklog); |
686 | return 0; | 612 | return 0; |
687 | } | 613 | } |
@@ -689,9 +615,9 @@ xfs_dir2_isleaf( | |||
689 | /* | 615 | /* |
690 | * Getdents put routine for 64-bit ABI, direct form. | 616 | * Getdents put routine for 64-bit ABI, direct form. |
691 | */ | 617 | */ |
692 | static int /* error */ | 618 | static int |
693 | xfs_dir2_put_dirent64_direct( | 619 | xfs_dir2_put_dirent64_direct( |
694 | xfs_dir2_put_args_t *pa) /* argument bundle */ | 620 | xfs_dir2_put_args_t *pa) |
695 | { | 621 | { |
696 | xfs_dirent_t *idbp; /* dirent pointer */ | 622 | xfs_dirent_t *idbp; /* dirent pointer */ |
697 | iovec_t *iovp; /* io vector */ | 623 | iovec_t *iovp; /* io vector */ |
@@ -726,9 +652,9 @@ xfs_dir2_put_dirent64_direct( | |||
726 | /* | 652 | /* |
727 | * Getdents put routine for 64-bit ABI, uio form. | 653 | * Getdents put routine for 64-bit ABI, uio form. |
728 | */ | 654 | */ |
729 | static int /* error */ | 655 | static int |
730 | xfs_dir2_put_dirent64_uio( | 656 | xfs_dir2_put_dirent64_uio( |
731 | xfs_dir2_put_args_t *pa) /* argument bundle */ | 657 | xfs_dir2_put_args_t *pa) |
732 | { | 658 | { |
733 | xfs_dirent_t *idbp; /* dirent pointer */ | 659 | xfs_dirent_t *idbp; /* dirent pointer */ |
734 | int namelen; /* entry name length */ | 660 | int namelen; /* entry name length */ |
@@ -764,17 +690,17 @@ xfs_dir2_put_dirent64_uio( | |||
764 | */ | 690 | */ |
765 | int | 691 | int |
766 | xfs_dir2_shrink_inode( | 692 | xfs_dir2_shrink_inode( |
767 | xfs_da_args_t *args, /* operation arguments */ | 693 | xfs_da_args_t *args, |
768 | xfs_dir2_db_t db, /* directory block number */ | 694 | xfs_dir2_db_t db, |
769 | xfs_dabuf_t *bp) /* block's buffer */ | 695 | xfs_dabuf_t *bp) |
770 | { | 696 | { |
771 | xfs_fileoff_t bno; /* directory file offset */ | 697 | xfs_fileoff_t bno; /* directory file offset */ |
772 | xfs_dablk_t da; /* directory file offset */ | 698 | xfs_dablk_t da; /* directory file offset */ |
773 | int done; /* bunmap is finished */ | 699 | int done; /* bunmap is finished */ |
774 | xfs_inode_t *dp; /* incore directory inode */ | 700 | xfs_inode_t *dp; |
775 | int error; /* error return value */ | 701 | int error; |
776 | xfs_mount_t *mp; /* filesystem mount point */ | 702 | xfs_mount_t *mp; |
777 | xfs_trans_t *tp; /* transaction pointer */ | 703 | xfs_trans_t *tp; |
778 | 704 | ||
779 | xfs_dir2_trace_args_db("shrink_inode", args, db, bp); | 705 | xfs_dir2_trace_args_db("shrink_inode", args, db, bp); |
780 | dp = args->dp; | 706 | dp = args->dp; |
@@ -786,7 +712,7 @@ xfs_dir2_shrink_inode( | |||
786 | */ | 712 | */ |
787 | if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, | 713 | if ((error = xfs_bunmapi(tp, dp, da, mp->m_dirblkfsbs, |
788 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, | 714 | XFS_BMAPI_METADATA, 0, args->firstblock, args->flist, |
789 | &done))) { | 715 | NULL, &done))) { |
790 | /* | 716 | /* |
791 | * ENOSPC actually can happen if we're in a removename with | 717 | * ENOSPC actually can happen if we're in a removename with |
792 | * no space reservation, and the resulting block removal | 718 | * no space reservation, and the resulting block removal |
diff --git a/fs/xfs/xfs_dir2.h b/fs/xfs/xfs_dir2.h index 7dd364b1e038..86560b6f794c 100644 --- a/fs/xfs/xfs_dir2.h +++ b/fs/xfs/xfs_dir2.h | |||
@@ -22,7 +22,9 @@ struct uio; | |||
22 | struct xfs_dabuf; | 22 | struct xfs_dabuf; |
23 | struct xfs_da_args; | 23 | struct xfs_da_args; |
24 | struct xfs_dir2_put_args; | 24 | struct xfs_dir2_put_args; |
25 | struct xfs_bmap_free; | ||
25 | struct xfs_inode; | 26 | struct xfs_inode; |
27 | struct xfs_mount; | ||
26 | struct xfs_trans; | 28 | struct xfs_trans; |
27 | 29 | ||
28 | /* | 30 | /* |
@@ -73,7 +75,35 @@ typedef struct xfs_dir2_put_args { | |||
73 | } xfs_dir2_put_args_t; | 75 | } xfs_dir2_put_args_t; |
74 | 76 | ||
75 | /* | 77 | /* |
76 | * Other interfaces used by the rest of the dir v2 code. | 78 | * Generic directory interface routines |
79 | */ | ||
80 | extern void xfs_dir_startup(void); | ||
81 | extern void xfs_dir_mount(struct xfs_mount *mp); | ||
82 | extern int xfs_dir_isempty(struct xfs_inode *dp); | ||
83 | extern int xfs_dir_init(struct xfs_trans *tp, struct xfs_inode *dp, | ||
84 | struct xfs_inode *pdp); | ||
85 | extern int xfs_dir_createname(struct xfs_trans *tp, struct xfs_inode *dp, | ||
86 | char *name, int namelen, xfs_ino_t inum, | ||
87 | xfs_fsblock_t *first, | ||
88 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
89 | extern int xfs_dir_lookup(struct xfs_trans *tp, struct xfs_inode *dp, | ||
90 | char *name, int namelen, xfs_ino_t *inum); | ||
91 | extern int xfs_dir_removename(struct xfs_trans *tp, struct xfs_inode *dp, | ||
92 | char *name, int namelen, xfs_ino_t ino, | ||
93 | xfs_fsblock_t *first, | ||
94 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
95 | extern int xfs_dir_getdents(struct xfs_trans *tp, struct xfs_inode *dp, | ||
96 | uio_t *uio, int *eofp); | ||
97 | extern int xfs_dir_replace(struct xfs_trans *tp, struct xfs_inode *dp, | ||
98 | char *name, int namelen, xfs_ino_t inum, | ||
99 | xfs_fsblock_t *first, | ||
100 | struct xfs_bmap_free *flist, xfs_extlen_t tot); | ||
101 | extern int xfs_dir_canenter(struct xfs_trans *tp, struct xfs_inode *dp, | ||
102 | char *name, int namelen); | ||
103 | extern int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | ||
104 | |||
105 | /* | ||
106 | * Utility routines for v2 directories. | ||
77 | */ | 107 | */ |
78 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, | 108 | extern int xfs_dir2_grow_inode(struct xfs_da_args *args, int space, |
79 | xfs_dir2_db_t *dbp); | 109 | xfs_dir2_db_t *dbp); |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index 972ded595476..9d7438bba30d 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -22,19 +22,16 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir_sf.h" | ||
32 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
36 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
37 | #include "xfs_dir_leaf.h" | ||
38 | #include "xfs_dir2_data.h" | 35 | #include "xfs_dir2_data.h" |
39 | #include "xfs_dir2_leaf.h" | 36 | #include "xfs_dir2_leaf.h" |
40 | #include "xfs_dir2_block.h" | 37 | #include "xfs_dir2_block.h" |
@@ -51,6 +48,18 @@ static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, xfs_dabuf_t **bpp, | |||
51 | int *entno); | 48 | int *entno); |
52 | static int xfs_dir2_block_sort(const void *a, const void *b); | 49 | static int xfs_dir2_block_sort(const void *a, const void *b); |
53 | 50 | ||
51 | static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; | ||
52 | |||
53 | /* | ||
54 | * One-time startup routine called from xfs_init(). | ||
55 | */ | ||
56 | void | ||
57 | xfs_dir_startup(void) | ||
58 | { | ||
59 | xfs_dir_hash_dot = xfs_da_hashname(".", 1); | ||
60 | xfs_dir_hash_dotdot = xfs_da_hashname("..", 2); | ||
61 | } | ||
62 | |||
54 | /* | 63 | /* |
55 | * Add an entry to a block directory. | 64 | * Add an entry to a block directory. |
56 | */ | 65 | */ |
@@ -400,7 +409,7 @@ xfs_dir2_block_addname( | |||
400 | /* | 409 | /* |
401 | * Create the new data entry. | 410 | * Create the new data entry. |
402 | */ | 411 | */ |
403 | INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); | 412 | dep->inumber = cpu_to_be64(args->inumber); |
404 | dep->namelen = args->namelen; | 413 | dep->namelen = args->namelen; |
405 | memcpy(dep->name, args->name, args->namelen); | 414 | memcpy(dep->name, args->name, args->namelen); |
406 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); | 415 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); |
@@ -508,7 +517,7 @@ xfs_dir2_block_getdents( | |||
508 | 517 | ||
509 | p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, | 518 | p.cook = XFS_DIR2_DB_OFF_TO_DATAPTR(mp, mp->m_dirdatablk, |
510 | ptr - (char *)block); | 519 | ptr - (char *)block); |
511 | p.ino = INT_GET(dep->inumber, ARCH_CONVERT); | 520 | p.ino = be64_to_cpu(dep->inumber); |
512 | #if XFS_BIG_INUMS | 521 | #if XFS_BIG_INUMS |
513 | p.ino += mp->m_inoadd; | 522 | p.ino += mp->m_inoadd; |
514 | #endif | 523 | #endif |
@@ -626,7 +635,7 @@ xfs_dir2_block_lookup( | |||
626 | /* | 635 | /* |
627 | * Fill in inode number, release the block. | 636 | * Fill in inode number, release the block. |
628 | */ | 637 | */ |
629 | args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); | 638 | args->inumber = be64_to_cpu(dep->inumber); |
630 | xfs_da_brelse(args->trans, bp); | 639 | xfs_da_brelse(args->trans, bp); |
631 | return XFS_ERROR(EEXIST); | 640 | return XFS_ERROR(EEXIST); |
632 | } | 641 | } |
@@ -844,11 +853,11 @@ xfs_dir2_block_replace( | |||
844 | */ | 853 | */ |
845 | dep = (xfs_dir2_data_entry_t *) | 854 | dep = (xfs_dir2_data_entry_t *) |
846 | ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); | 855 | ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, be32_to_cpu(blp[ent].address))); |
847 | ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) != args->inumber); | 856 | ASSERT(be64_to_cpu(dep->inumber) != args->inumber); |
848 | /* | 857 | /* |
849 | * Change the inode number to the new value. | 858 | * Change the inode number to the new value. |
850 | */ | 859 | */ |
851 | INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); | 860 | dep->inumber = cpu_to_be64(args->inumber); |
852 | xfs_dir2_data_log_entry(args->trans, bp, dep); | 861 | xfs_dir2_data_log_entry(args->trans, bp, dep); |
853 | xfs_dir2_data_check(dp, bp); | 862 | xfs_dir2_data_check(dp, bp); |
854 | xfs_da_buf_done(bp); | 863 | xfs_da_buf_done(bp); |
@@ -1130,7 +1139,7 @@ xfs_dir2_sf_to_block( | |||
1130 | */ | 1139 | */ |
1131 | dep = (xfs_dir2_data_entry_t *) | 1140 | dep = (xfs_dir2_data_entry_t *) |
1132 | ((char *)block + XFS_DIR2_DATA_DOT_OFFSET); | 1141 | ((char *)block + XFS_DIR2_DATA_DOT_OFFSET); |
1133 | INT_SET(dep->inumber, ARCH_CONVERT, dp->i_ino); | 1142 | dep->inumber = cpu_to_be64(dp->i_ino); |
1134 | dep->namelen = 1; | 1143 | dep->namelen = 1; |
1135 | dep->name[0] = '.'; | 1144 | dep->name[0] = '.'; |
1136 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); | 1145 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); |
@@ -1144,7 +1153,7 @@ xfs_dir2_sf_to_block( | |||
1144 | */ | 1153 | */ |
1145 | dep = (xfs_dir2_data_entry_t *) | 1154 | dep = (xfs_dir2_data_entry_t *) |
1146 | ((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET); | 1155 | ((char *)block + XFS_DIR2_DATA_DOTDOT_OFFSET); |
1147 | INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); | 1156 | dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); |
1148 | dep->namelen = 2; | 1157 | dep->namelen = 2; |
1149 | dep->name[0] = dep->name[1] = '.'; | 1158 | dep->name[0] = dep->name[1] = '.'; |
1150 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); | 1159 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); |
@@ -1193,7 +1202,7 @@ xfs_dir2_sf_to_block( | |||
1193 | * Copy a real entry. | 1202 | * Copy a real entry. |
1194 | */ | 1203 | */ |
1195 | dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset); | 1204 | dep = (xfs_dir2_data_entry_t *)((char *)block + newoffset); |
1196 | INT_SET(dep->inumber, ARCH_CONVERT, XFS_DIR2_SF_GET_INUMBER(sfp, | 1205 | dep->inumber = cpu_to_be64(XFS_DIR2_SF_GET_INUMBER(sfp, |
1197 | XFS_DIR2_SF_INUMBERP(sfep))); | 1206 | XFS_DIR2_SF_INUMBERP(sfep))); |
1198 | dep->namelen = sfep->namelen; | 1207 | dep->namelen = sfep->namelen; |
1199 | memcpy(dep->name, sfep->name, dep->namelen); | 1208 | memcpy(dep->name, sfep->name, dep->namelen); |
diff --git a/fs/xfs/xfs_dir2_data.c b/fs/xfs/xfs_dir2_data.c index bb3d03ff002b..f7c799217072 100644 --- a/fs/xfs/xfs_dir2_data.c +++ b/fs/xfs/xfs_dir2_data.c | |||
@@ -22,18 +22,15 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir_sf.h" | ||
32 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
36 | #include "xfs_dir_leaf.h" | ||
37 | #include "xfs_dir2_data.h" | 34 | #include "xfs_dir2_data.h" |
38 | #include "xfs_dir2_leaf.h" | 35 | #include "xfs_dir2_leaf.h" |
39 | #include "xfs_dir2_block.h" | 36 | #include "xfs_dir2_block.h" |
@@ -133,7 +130,7 @@ xfs_dir2_data_check( | |||
133 | */ | 130 | */ |
134 | dep = (xfs_dir2_data_entry_t *)p; | 131 | dep = (xfs_dir2_data_entry_t *)p; |
135 | ASSERT(dep->namelen != 0); | 132 | ASSERT(dep->namelen != 0); |
136 | ASSERT(xfs_dir_ino_validate(mp, INT_GET(dep->inumber, ARCH_CONVERT)) == 0); | 133 | ASSERT(xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)) == 0); |
137 | ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) == | 134 | ASSERT(be16_to_cpu(*XFS_DIR2_DATA_ENTRY_TAG_P(dep)) == |
138 | (char *)dep - (char *)d); | 135 | (char *)dep - (char *)d); |
139 | count++; | 136 | count++; |
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h index 0847cbb53e17..a6ae2d21c40a 100644 --- a/fs/xfs/xfs_dir2_data.h +++ b/fs/xfs/xfs_dir2_data.h | |||
@@ -85,11 +85,11 @@ typedef struct xfs_dir2_data_hdr { | |||
85 | * Tag appears as the last 2 bytes. | 85 | * Tag appears as the last 2 bytes. |
86 | */ | 86 | */ |
87 | typedef struct xfs_dir2_data_entry { | 87 | typedef struct xfs_dir2_data_entry { |
88 | xfs_ino_t inumber; /* inode number */ | 88 | __be64 inumber; /* inode number */ |
89 | __uint8_t namelen; /* name length */ | 89 | __u8 namelen; /* name length */ |
90 | __uint8_t name[1]; /* name bytes, no null */ | 90 | __u8 name[1]; /* name bytes, no null */ |
91 | /* variable offset */ | 91 | /* variable offset */ |
92 | xfs_dir2_data_off_t tag; /* starting offset of us */ | 92 | __be16 tag; /* starting offset of us */ |
93 | } xfs_dir2_data_entry_t; | 93 | } xfs_dir2_data_entry_t; |
94 | 94 | ||
95 | /* | 95 | /* |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index 0f5e2f2ce6ec..b1cf1fbf423d 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_da_btree.h" | 30 | #include "xfs_da_btree.h" |
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_attr_sf.h" | 32 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_dinode.h" | 34 | #include "xfs_dinode.h" |
37 | #include "xfs_inode.h" | 35 | #include "xfs_inode.h" |
@@ -407,7 +405,7 @@ xfs_dir2_leaf_addname( | |||
407 | * Initialize our new entry (at last). | 405 | * Initialize our new entry (at last). |
408 | */ | 406 | */ |
409 | dep = (xfs_dir2_data_entry_t *)dup; | 407 | dep = (xfs_dir2_data_entry_t *)dup; |
410 | INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); | 408 | dep->inumber = cpu_to_be64(args->inumber); |
411 | dep->namelen = args->namelen; | 409 | dep->namelen = args->namelen; |
412 | memcpy(dep->name, args->name, dep->namelen); | 410 | memcpy(dep->name, args->name, dep->namelen); |
413 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); | 411 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); |
@@ -884,7 +882,7 @@ xfs_dir2_leaf_getdents( | |||
884 | XFS_DIR2_BYTE_TO_DA(mp, | 882 | XFS_DIR2_BYTE_TO_DA(mp, |
885 | XFS_DIR2_LEAF_OFFSET) - map_off, | 883 | XFS_DIR2_LEAF_OFFSET) - map_off, |
886 | XFS_BMAPI_METADATA, NULL, 0, | 884 | XFS_BMAPI_METADATA, NULL, 0, |
887 | &map[map_valid], &nmap, NULL); | 885 | &map[map_valid], &nmap, NULL, NULL); |
888 | /* | 886 | /* |
889 | * Don't know if we should ignore this or | 887 | * Don't know if we should ignore this or |
890 | * try to return an error. | 888 | * try to return an error. |
@@ -1098,7 +1096,7 @@ xfs_dir2_leaf_getdents( | |||
1098 | 1096 | ||
1099 | p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); | 1097 | p->cook = XFS_DIR2_BYTE_TO_DATAPTR(mp, curoff + length); |
1100 | 1098 | ||
1101 | p->ino = INT_GET(dep->inumber, ARCH_CONVERT); | 1099 | p->ino = be64_to_cpu(dep->inumber); |
1102 | #if XFS_BIG_INUMS | 1100 | #if XFS_BIG_INUMS |
1103 | p->ino += mp->m_inoadd; | 1101 | p->ino += mp->m_inoadd; |
1104 | #endif | 1102 | #endif |
@@ -1319,7 +1317,7 @@ xfs_dir2_leaf_lookup( | |||
1319 | /* | 1317 | /* |
1320 | * Return the found inode number. | 1318 | * Return the found inode number. |
1321 | */ | 1319 | */ |
1322 | args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); | 1320 | args->inumber = be64_to_cpu(dep->inumber); |
1323 | xfs_da_brelse(tp, dbp); | 1321 | xfs_da_brelse(tp, dbp); |
1324 | xfs_da_brelse(tp, lbp); | 1322 | xfs_da_brelse(tp, lbp); |
1325 | return XFS_ERROR(EEXIST); | 1323 | return XFS_ERROR(EEXIST); |
@@ -1606,11 +1604,11 @@ xfs_dir2_leaf_replace( | |||
1606 | dep = (xfs_dir2_data_entry_t *) | 1604 | dep = (xfs_dir2_data_entry_t *) |
1607 | ((char *)dbp->data + | 1605 | ((char *)dbp->data + |
1608 | XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); | 1606 | XFS_DIR2_DATAPTR_TO_OFF(dp->i_mount, be32_to_cpu(lep->address))); |
1609 | ASSERT(args->inumber != INT_GET(dep->inumber, ARCH_CONVERT)); | 1607 | ASSERT(args->inumber != be64_to_cpu(dep->inumber)); |
1610 | /* | 1608 | /* |
1611 | * Put the new inode number in, log it. | 1609 | * Put the new inode number in, log it. |
1612 | */ | 1610 | */ |
1613 | INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); | 1611 | dep->inumber = cpu_to_be64(args->inumber); |
1614 | tp = args->trans; | 1612 | tp = args->trans; |
1615 | xfs_dir2_data_log_entry(tp, dbp, dep); | 1613 | xfs_dir2_data_log_entry(tp, dbp, dep); |
1616 | xfs_da_buf_done(dbp); | 1614 | xfs_da_buf_done(dbp); |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index ac511ab9c52d..9ca71719b683 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -22,13 +22,11 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir_sf.h" | ||
32 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
@@ -505,7 +503,6 @@ xfs_dir2_leafn_lookup_int( | |||
505 | XFS_DATA_FORK))) { | 503 | XFS_DATA_FORK))) { |
506 | return error; | 504 | return error; |
507 | } | 505 | } |
508 | curfdb = newfdb; | ||
509 | free = curbp->data; | 506 | free = curbp->data; |
510 | ASSERT(be32_to_cpu(free->hdr.magic) == | 507 | ASSERT(be32_to_cpu(free->hdr.magic) == |
511 | XFS_DIR2_FREE_MAGIC); | 508 | XFS_DIR2_FREE_MAGIC); |
@@ -527,8 +524,11 @@ xfs_dir2_leafn_lookup_int( | |||
527 | if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { | 524 | if (unlikely(be16_to_cpu(free->bests[fi]) == NULLDATAOFF)) { |
528 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", | 525 | XFS_ERROR_REPORT("xfs_dir2_leafn_lookup_int", |
529 | XFS_ERRLEVEL_LOW, mp); | 526 | XFS_ERRLEVEL_LOW, mp); |
527 | if (curfdb != newfdb) | ||
528 | xfs_da_brelse(tp, curbp); | ||
530 | return XFS_ERROR(EFSCORRUPTED); | 529 | return XFS_ERROR(EFSCORRUPTED); |
531 | } | 530 | } |
531 | curfdb = newfdb; | ||
532 | if (be16_to_cpu(free->bests[fi]) >= length) { | 532 | if (be16_to_cpu(free->bests[fi]) >= length) { |
533 | *indexp = index; | 533 | *indexp = index; |
534 | state->extravalid = 1; | 534 | state->extravalid = 1; |
@@ -580,7 +580,7 @@ xfs_dir2_leafn_lookup_int( | |||
580 | if (dep->namelen == args->namelen && | 580 | if (dep->namelen == args->namelen && |
581 | dep->name[0] == args->name[0] && | 581 | dep->name[0] == args->name[0] && |
582 | memcmp(dep->name, args->name, args->namelen) == 0) { | 582 | memcmp(dep->name, args->name, args->namelen) == 0) { |
583 | args->inumber = INT_GET(dep->inumber, ARCH_CONVERT); | 583 | args->inumber = be64_to_cpu(dep->inumber); |
584 | *indexp = index; | 584 | *indexp = index; |
585 | state->extravalid = 1; | 585 | state->extravalid = 1; |
586 | state->extrablk.bp = curbp; | 586 | state->extrablk.bp = curbp; |
@@ -970,7 +970,7 @@ xfs_dir2_leafn_remove( | |||
970 | /* | 970 | /* |
971 | * One less used entry in the free table. | 971 | * One less used entry in the free table. |
972 | */ | 972 | */ |
973 | free->hdr.nused = cpu_to_be32(-1); | 973 | be32_add(&free->hdr.nused, -1); |
974 | xfs_dir2_free_log_header(tp, fbp); | 974 | xfs_dir2_free_log_header(tp, fbp); |
975 | /* | 975 | /* |
976 | * If this was the last entry in the table, we can | 976 | * If this was the last entry in the table, we can |
@@ -1695,7 +1695,7 @@ xfs_dir2_node_addname_int( | |||
1695 | * Fill in the new entry and log it. | 1695 | * Fill in the new entry and log it. |
1696 | */ | 1696 | */ |
1697 | dep = (xfs_dir2_data_entry_t *)dup; | 1697 | dep = (xfs_dir2_data_entry_t *)dup; |
1698 | INT_SET(dep->inumber, ARCH_CONVERT, args->inumber); | 1698 | dep->inumber = cpu_to_be64(args->inumber); |
1699 | dep->namelen = args->namelen; | 1699 | dep->namelen = args->namelen; |
1700 | memcpy(dep->name, args->name, dep->namelen); | 1700 | memcpy(dep->name, args->name, dep->namelen); |
1701 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); | 1701 | tagp = XFS_DIR2_DATA_ENTRY_TAG_P(dep); |
@@ -1905,11 +1905,11 @@ xfs_dir2_node_replace( | |||
1905 | dep = (xfs_dir2_data_entry_t *) | 1905 | dep = (xfs_dir2_data_entry_t *) |
1906 | ((char *)data + | 1906 | ((char *)data + |
1907 | XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address))); | 1907 | XFS_DIR2_DATAPTR_TO_OFF(state->mp, be32_to_cpu(lep->address))); |
1908 | ASSERT(inum != INT_GET(dep->inumber, ARCH_CONVERT)); | 1908 | ASSERT(inum != be64_to_cpu(dep->inumber)); |
1909 | /* | 1909 | /* |
1910 | * Fill in the new inode number and log the entry. | 1910 | * Fill in the new inode number and log the entry. |
1911 | */ | 1911 | */ |
1912 | INT_SET(dep->inumber, ARCH_CONVERT, inum); | 1912 | dep->inumber = cpu_to_be64(inum); |
1913 | xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); | 1913 | xfs_dir2_data_log_entry(args->trans, state->extrablk.bp, dep); |
1914 | rval = 0; | 1914 | rval = 0; |
1915 | } | 1915 | } |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index d98a41d1fe63..0cd77b17bf92 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -22,19 +22,16 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir_sf.h" | ||
32 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
35 | #include "xfs_inode.h" | 33 | #include "xfs_inode.h" |
36 | #include "xfs_inode_item.h" | 34 | #include "xfs_inode_item.h" |
37 | #include "xfs_dir_leaf.h" | ||
38 | #include "xfs_error.h" | 35 | #include "xfs_error.h" |
39 | #include "xfs_dir2_data.h" | 36 | #include "xfs_dir2_data.h" |
40 | #include "xfs_dir2_leaf.h" | 37 | #include "xfs_dir2_leaf.h" |
@@ -117,13 +114,13 @@ xfs_dir2_block_sfsize( | |||
117 | dep->name[0] == '.' && dep->name[1] == '.'; | 114 | dep->name[0] == '.' && dep->name[1] == '.'; |
118 | #if XFS_BIG_INUMS | 115 | #if XFS_BIG_INUMS |
119 | if (!isdot) | 116 | if (!isdot) |
120 | i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM; | 117 | i8count += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM; |
121 | #endif | 118 | #endif |
122 | if (!isdot && !isdotdot) { | 119 | if (!isdot && !isdotdot) { |
123 | count++; | 120 | count++; |
124 | namelen += dep->namelen; | 121 | namelen += dep->namelen; |
125 | } else if (isdotdot) | 122 | } else if (isdotdot) |
126 | parent = INT_GET(dep->inumber, ARCH_CONVERT); | 123 | parent = be64_to_cpu(dep->inumber); |
127 | /* | 124 | /* |
128 | * Calculate the new size, see if we should give up yet. | 125 | * Calculate the new size, see if we should give up yet. |
129 | */ | 126 | */ |
@@ -229,13 +226,13 @@ xfs_dir2_block_to_sf( | |||
229 | * Skip . | 226 | * Skip . |
230 | */ | 227 | */ |
231 | if (dep->namelen == 1 && dep->name[0] == '.') | 228 | if (dep->namelen == 1 && dep->name[0] == '.') |
232 | ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == dp->i_ino); | 229 | ASSERT(be64_to_cpu(dep->inumber) == dp->i_ino); |
233 | /* | 230 | /* |
234 | * Skip .., but make sure the inode number is right. | 231 | * Skip .., but make sure the inode number is right. |
235 | */ | 232 | */ |
236 | else if (dep->namelen == 2 && | 233 | else if (dep->namelen == 2 && |
237 | dep->name[0] == '.' && dep->name[1] == '.') | 234 | dep->name[0] == '.' && dep->name[1] == '.') |
238 | ASSERT(INT_GET(dep->inumber, ARCH_CONVERT) == | 235 | ASSERT(be64_to_cpu(dep->inumber) == |
239 | XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); | 236 | XFS_DIR2_SF_GET_INUMBER(sfp, &sfp->hdr.parent)); |
240 | /* | 237 | /* |
241 | * Normal entry, copy it into shortform. | 238 | * Normal entry, copy it into shortform. |
@@ -246,7 +243,7 @@ xfs_dir2_block_to_sf( | |||
246 | (xfs_dir2_data_aoff_t) | 243 | (xfs_dir2_data_aoff_t) |
247 | ((char *)dep - (char *)block)); | 244 | ((char *)dep - (char *)block)); |
248 | memcpy(sfep->name, dep->name, dep->namelen); | 245 | memcpy(sfep->name, dep->name, dep->namelen); |
249 | temp=INT_GET(dep->inumber, ARCH_CONVERT); | 246 | temp = be64_to_cpu(dep->inumber); |
250 | XFS_DIR2_SF_PUT_INUMBER(sfp, &temp, | 247 | XFS_DIR2_SF_PUT_INUMBER(sfp, &temp, |
251 | XFS_DIR2_SF_INUMBERP(sfep)); | 248 | XFS_DIR2_SF_INUMBERP(sfep)); |
252 | sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep); | 249 | sfep = XFS_DIR2_SF_NEXTENTRY(sfp, sfep); |
diff --git a/fs/xfs/xfs_dir2_trace.c b/fs/xfs/xfs_dir2_trace.c index c626943b4112..f3fb2ffd6f5c 100644 --- a/fs/xfs/xfs_dir2_trace.c +++ b/fs/xfs/xfs_dir2_trace.c | |||
@@ -19,11 +19,9 @@ | |||
19 | #include "xfs_fs.h" | 19 | #include "xfs_fs.h" |
20 | #include "xfs_types.h" | 20 | #include "xfs_types.h" |
21 | #include "xfs_inum.h" | 21 | #include "xfs_inum.h" |
22 | #include "xfs_dir.h" | ||
23 | #include "xfs_dir2.h" | 22 | #include "xfs_dir2.h" |
24 | #include "xfs_da_btree.h" | 23 | #include "xfs_da_btree.h" |
25 | #include "xfs_bmap_btree.h" | 24 | #include "xfs_bmap_btree.h" |
26 | #include "xfs_dir_sf.h" | ||
27 | #include "xfs_dir2_sf.h" | 25 | #include "xfs_dir2_sf.h" |
28 | #include "xfs_attr_sf.h" | 26 | #include "xfs_attr_sf.h" |
29 | #include "xfs_dinode.h" | 27 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_dir_leaf.c b/fs/xfs/xfs_dir_leaf.c deleted file mode 100644 index 6d711869262f..000000000000 --- a/fs/xfs/xfs_dir_leaf.c +++ /dev/null | |||
@@ -1,2213 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_fs.h" | ||
20 | #include "xfs_types.h" | ||
21 | #include "xfs_log.h" | ||
22 | #include "xfs_inum.h" | ||
23 | #include "xfs_trans.h" | ||
24 | #include "xfs_sb.h" | ||
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | ||
27 | #include "xfs_dmapi.h" | ||
28 | #include "xfs_mount.h" | ||
29 | #include "xfs_da_btree.h" | ||
30 | #include "xfs_bmap_btree.h" | ||
31 | #include "xfs_alloc_btree.h" | ||
32 | #include "xfs_ialloc_btree.h" | ||
33 | #include "xfs_dir_sf.h" | ||
34 | #include "xfs_dir2_sf.h" | ||
35 | #include "xfs_attr_sf.h" | ||
36 | #include "xfs_dinode.h" | ||
37 | #include "xfs_inode.h" | ||
38 | #include "xfs_inode_item.h" | ||
39 | #include "xfs_alloc.h" | ||
40 | #include "xfs_btree.h" | ||
41 | #include "xfs_bmap.h" | ||
42 | #include "xfs_dir_leaf.h" | ||
43 | #include "xfs_error.h" | ||
44 | |||
45 | /* | ||
46 | * xfs_dir_leaf.c | ||
47 | * | ||
48 | * Routines to implement leaf blocks of directories as Btrees of hashed names. | ||
49 | */ | ||
50 | |||
51 | /*======================================================================== | ||
52 | * Function prototypes for the kernel. | ||
53 | *========================================================================*/ | ||
54 | |||
55 | /* | ||
56 | * Routines used for growing the Btree. | ||
57 | */ | ||
58 | STATIC void xfs_dir_leaf_add_work(xfs_dabuf_t *leaf_buffer, xfs_da_args_t *args, | ||
59 | int insertion_index, | ||
60 | int freemap_index); | ||
61 | STATIC int xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *leaf_buffer, | ||
62 | int musthave, int justcheck); | ||
63 | STATIC void xfs_dir_leaf_rebalance(xfs_da_state_t *state, | ||
64 | xfs_da_state_blk_t *blk1, | ||
65 | xfs_da_state_blk_t *blk2); | ||
66 | STATIC int xfs_dir_leaf_figure_balance(xfs_da_state_t *state, | ||
67 | xfs_da_state_blk_t *leaf_blk_1, | ||
68 | xfs_da_state_blk_t *leaf_blk_2, | ||
69 | int *number_entries_in_blk1, | ||
70 | int *number_namebytes_in_blk1); | ||
71 | |||
72 | STATIC int xfs_dir_leaf_create(struct xfs_da_args *args, | ||
73 | xfs_dablk_t which_block, | ||
74 | struct xfs_dabuf **bpp); | ||
75 | |||
76 | /* | ||
77 | * Utility routines. | ||
78 | */ | ||
79 | STATIC void xfs_dir_leaf_moveents(xfs_dir_leafblock_t *src_leaf, | ||
80 | int src_start, | ||
81 | xfs_dir_leafblock_t *dst_leaf, | ||
82 | int dst_start, int move_count, | ||
83 | xfs_mount_t *mp); | ||
84 | |||
85 | |||
86 | /*======================================================================== | ||
87 | * External routines when dirsize < XFS_IFORK_DSIZE(dp). | ||
88 | *========================================================================*/ | ||
89 | |||
90 | |||
91 | /* | ||
92 | * Validate a given inode number. | ||
93 | */ | ||
94 | int | ||
95 | xfs_dir_ino_validate(xfs_mount_t *mp, xfs_ino_t ino) | ||
96 | { | ||
97 | xfs_agblock_t agblkno; | ||
98 | xfs_agino_t agino; | ||
99 | xfs_agnumber_t agno; | ||
100 | int ino_ok; | ||
101 | int ioff; | ||
102 | |||
103 | agno = XFS_INO_TO_AGNO(mp, ino); | ||
104 | agblkno = XFS_INO_TO_AGBNO(mp, ino); | ||
105 | ioff = XFS_INO_TO_OFFSET(mp, ino); | ||
106 | agino = XFS_OFFBNO_TO_AGINO(mp, agblkno, ioff); | ||
107 | ino_ok = | ||
108 | agno < mp->m_sb.sb_agcount && | ||
109 | agblkno < mp->m_sb.sb_agblocks && | ||
110 | agblkno != 0 && | ||
111 | ioff < (1 << mp->m_sb.sb_inopblog) && | ||
112 | XFS_AGINO_TO_INO(mp, agno, agino) == ino; | ||
113 | if (unlikely(XFS_TEST_ERROR(!ino_ok, mp, XFS_ERRTAG_DIR_INO_VALIDATE, | ||
114 | XFS_RANDOM_DIR_INO_VALIDATE))) { | ||
115 | xfs_fs_cmn_err(CE_WARN, mp, "Invalid inode number 0x%Lx", | ||
116 | (unsigned long long) ino); | ||
117 | XFS_ERROR_REPORT("xfs_dir_ino_validate", XFS_ERRLEVEL_LOW, mp); | ||
118 | return XFS_ERROR(EFSCORRUPTED); | ||
119 | } | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * Create the initial contents of a shortform directory. | ||
125 | */ | ||
126 | int | ||
127 | xfs_dir_shortform_create(xfs_da_args_t *args, xfs_ino_t parent) | ||
128 | { | ||
129 | xfs_dir_sf_hdr_t *hdr; | ||
130 | xfs_inode_t *dp; | ||
131 | |||
132 | dp = args->dp; | ||
133 | ASSERT(dp != NULL); | ||
134 | ASSERT(dp->i_d.di_size == 0); | ||
135 | if (dp->i_d.di_format == XFS_DINODE_FMT_EXTENTS) { | ||
136 | dp->i_df.if_flags &= ~XFS_IFEXTENTS; /* just in case */ | ||
137 | dp->i_d.di_format = XFS_DINODE_FMT_LOCAL; | ||
138 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
139 | dp->i_df.if_flags |= XFS_IFINLINE; | ||
140 | } | ||
141 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | ||
142 | ASSERT(dp->i_df.if_bytes == 0); | ||
143 | xfs_idata_realloc(dp, sizeof(*hdr), XFS_DATA_FORK); | ||
144 | hdr = (xfs_dir_sf_hdr_t *)dp->i_df.if_u1.if_data; | ||
145 | XFS_DIR_SF_PUT_DIRINO(&parent, &hdr->parent); | ||
146 | |||
147 | hdr->count = 0; | ||
148 | dp->i_d.di_size = sizeof(*hdr); | ||
149 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* | ||
154 | * Add a name to the shortform directory structure. | ||
155 | * Overflow from the inode has already been checked for. | ||
156 | */ | ||
157 | int | ||
158 | xfs_dir_shortform_addname(xfs_da_args_t *args) | ||
159 | { | ||
160 | xfs_dir_shortform_t *sf; | ||
161 | xfs_dir_sf_entry_t *sfe; | ||
162 | int i, offset, size; | ||
163 | xfs_inode_t *dp; | ||
164 | |||
165 | dp = args->dp; | ||
166 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | ||
167 | /* | ||
168 | * Catch the case where the conversion from shortform to leaf | ||
169 | * failed part way through. | ||
170 | */ | ||
171 | if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { | ||
172 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); | ||
173 | return XFS_ERROR(EIO); | ||
174 | } | ||
175 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | ||
176 | ASSERT(dp->i_df.if_u1.if_data != NULL); | ||
177 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
178 | sfe = &sf->list[0]; | ||
179 | for (i = sf->hdr.count-1; i >= 0; i--) { | ||
180 | if (sfe->namelen == args->namelen && | ||
181 | args->name[0] == sfe->name[0] && | ||
182 | memcmp(args->name, sfe->name, args->namelen) == 0) | ||
183 | return XFS_ERROR(EEXIST); | ||
184 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
185 | } | ||
186 | |||
187 | offset = (int)((char *)sfe - (char *)sf); | ||
188 | size = XFS_DIR_SF_ENTSIZE_BYNAME(args->namelen); | ||
189 | xfs_idata_realloc(dp, size, XFS_DATA_FORK); | ||
190 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
191 | sfe = (xfs_dir_sf_entry_t *)((char *)sf + offset); | ||
192 | |||
193 | XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); | ||
194 | sfe->namelen = args->namelen; | ||
195 | memcpy(sfe->name, args->name, sfe->namelen); | ||
196 | sf->hdr.count++; | ||
197 | |||
198 | dp->i_d.di_size += size; | ||
199 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | /* | ||
205 | * Remove a name from the shortform directory structure. | ||
206 | */ | ||
207 | int | ||
208 | xfs_dir_shortform_removename(xfs_da_args_t *args) | ||
209 | { | ||
210 | xfs_dir_shortform_t *sf; | ||
211 | xfs_dir_sf_entry_t *sfe; | ||
212 | int base, size = 0, i; | ||
213 | xfs_inode_t *dp; | ||
214 | |||
215 | dp = args->dp; | ||
216 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | ||
217 | /* | ||
218 | * Catch the case where the conversion from shortform to leaf | ||
219 | * failed part way through. | ||
220 | */ | ||
221 | if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { | ||
222 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); | ||
223 | return XFS_ERROR(EIO); | ||
224 | } | ||
225 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | ||
226 | ASSERT(dp->i_df.if_u1.if_data != NULL); | ||
227 | base = sizeof(xfs_dir_sf_hdr_t); | ||
228 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
229 | sfe = &sf->list[0]; | ||
230 | for (i = sf->hdr.count-1; i >= 0; i--) { | ||
231 | size = XFS_DIR_SF_ENTSIZE_BYENTRY(sfe); | ||
232 | if (sfe->namelen == args->namelen && | ||
233 | sfe->name[0] == args->name[0] && | ||
234 | memcmp(sfe->name, args->name, args->namelen) == 0) | ||
235 | break; | ||
236 | base += size; | ||
237 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
238 | } | ||
239 | if (i < 0) { | ||
240 | ASSERT(args->oknoent); | ||
241 | return XFS_ERROR(ENOENT); | ||
242 | } | ||
243 | |||
244 | if ((base + size) != dp->i_d.di_size) { | ||
245 | memmove(&((char *)sf)[base], &((char *)sf)[base+size], | ||
246 | dp->i_d.di_size - (base+size)); | ||
247 | } | ||
248 | sf->hdr.count--; | ||
249 | |||
250 | xfs_idata_realloc(dp, -size, XFS_DATA_FORK); | ||
251 | dp->i_d.di_size -= size; | ||
252 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE | XFS_ILOG_DDATA); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Look up a name in a shortform directory structure. | ||
259 | */ | ||
260 | int | ||
261 | xfs_dir_shortform_lookup(xfs_da_args_t *args) | ||
262 | { | ||
263 | xfs_dir_shortform_t *sf; | ||
264 | xfs_dir_sf_entry_t *sfe; | ||
265 | int i; | ||
266 | xfs_inode_t *dp; | ||
267 | |||
268 | dp = args->dp; | ||
269 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | ||
270 | /* | ||
271 | * Catch the case where the conversion from shortform to leaf | ||
272 | * failed part way through. | ||
273 | */ | ||
274 | if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { | ||
275 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); | ||
276 | return XFS_ERROR(EIO); | ||
277 | } | ||
278 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | ||
279 | ASSERT(dp->i_df.if_u1.if_data != NULL); | ||
280 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
281 | if (args->namelen == 2 && | ||
282 | args->name[0] == '.' && args->name[1] == '.') { | ||
283 | XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &args->inumber); | ||
284 | return(XFS_ERROR(EEXIST)); | ||
285 | } | ||
286 | if (args->namelen == 1 && args->name[0] == '.') { | ||
287 | args->inumber = dp->i_ino; | ||
288 | return(XFS_ERROR(EEXIST)); | ||
289 | } | ||
290 | sfe = &sf->list[0]; | ||
291 | for (i = sf->hdr.count-1; i >= 0; i--) { | ||
292 | if (sfe->namelen == args->namelen && | ||
293 | sfe->name[0] == args->name[0] && | ||
294 | memcmp(args->name, sfe->name, args->namelen) == 0) { | ||
295 | XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args->inumber); | ||
296 | return(XFS_ERROR(EEXIST)); | ||
297 | } | ||
298 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
299 | } | ||
300 | ASSERT(args->oknoent); | ||
301 | return(XFS_ERROR(ENOENT)); | ||
302 | } | ||
303 | |||
304 | /* | ||
305 | * Convert from using the shortform to the leaf. | ||
306 | */ | ||
307 | int | ||
308 | xfs_dir_shortform_to_leaf(xfs_da_args_t *iargs) | ||
309 | { | ||
310 | xfs_inode_t *dp; | ||
311 | xfs_dir_shortform_t *sf; | ||
312 | xfs_dir_sf_entry_t *sfe; | ||
313 | xfs_da_args_t args; | ||
314 | xfs_ino_t inumber; | ||
315 | char *tmpbuffer; | ||
316 | int retval, i, size; | ||
317 | xfs_dablk_t blkno; | ||
318 | xfs_dabuf_t *bp; | ||
319 | |||
320 | dp = iargs->dp; | ||
321 | /* | ||
322 | * Catch the case where the conversion from shortform to leaf | ||
323 | * failed part way through. | ||
324 | */ | ||
325 | if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { | ||
326 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); | ||
327 | return XFS_ERROR(EIO); | ||
328 | } | ||
329 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | ||
330 | ASSERT(dp->i_df.if_u1.if_data != NULL); | ||
331 | size = dp->i_df.if_bytes; | ||
332 | tmpbuffer = kmem_alloc(size, KM_SLEEP); | ||
333 | ASSERT(tmpbuffer != NULL); | ||
334 | |||
335 | memcpy(tmpbuffer, dp->i_df.if_u1.if_data, size); | ||
336 | |||
337 | sf = (xfs_dir_shortform_t *)tmpbuffer; | ||
338 | XFS_DIR_SF_GET_DIRINO(&sf->hdr.parent, &inumber); | ||
339 | |||
340 | xfs_idata_realloc(dp, -size, XFS_DATA_FORK); | ||
341 | dp->i_d.di_size = 0; | ||
342 | xfs_trans_log_inode(iargs->trans, dp, XFS_ILOG_CORE); | ||
343 | retval = xfs_da_grow_inode(iargs, &blkno); | ||
344 | if (retval) | ||
345 | goto out; | ||
346 | |||
347 | ASSERT(blkno == 0); | ||
348 | retval = xfs_dir_leaf_create(iargs, blkno, &bp); | ||
349 | if (retval) | ||
350 | goto out; | ||
351 | xfs_da_buf_done(bp); | ||
352 | |||
353 | args.name = "."; | ||
354 | args.namelen = 1; | ||
355 | args.hashval = xfs_dir_hash_dot; | ||
356 | args.inumber = dp->i_ino; | ||
357 | args.dp = dp; | ||
358 | args.firstblock = iargs->firstblock; | ||
359 | args.flist = iargs->flist; | ||
360 | args.total = iargs->total; | ||
361 | args.whichfork = XFS_DATA_FORK; | ||
362 | args.trans = iargs->trans; | ||
363 | args.justcheck = 0; | ||
364 | args.addname = args.oknoent = 1; | ||
365 | retval = xfs_dir_leaf_addname(&args); | ||
366 | if (retval) | ||
367 | goto out; | ||
368 | |||
369 | args.name = ".."; | ||
370 | args.namelen = 2; | ||
371 | args.hashval = xfs_dir_hash_dotdot; | ||
372 | args.inumber = inumber; | ||
373 | retval = xfs_dir_leaf_addname(&args); | ||
374 | if (retval) | ||
375 | goto out; | ||
376 | |||
377 | sfe = &sf->list[0]; | ||
378 | for (i = 0; i < sf->hdr.count; i++) { | ||
379 | args.name = (char *)(sfe->name); | ||
380 | args.namelen = sfe->namelen; | ||
381 | args.hashval = xfs_da_hashname((char *)(sfe->name), | ||
382 | sfe->namelen); | ||
383 | XFS_DIR_SF_GET_DIRINO(&sfe->inumber, &args.inumber); | ||
384 | retval = xfs_dir_leaf_addname(&args); | ||
385 | if (retval) | ||
386 | goto out; | ||
387 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
388 | } | ||
389 | retval = 0; | ||
390 | |||
391 | out: | ||
392 | kmem_free(tmpbuffer, size); | ||
393 | return retval; | ||
394 | } | ||
395 | |||
396 | STATIC int | ||
397 | xfs_dir_shortform_compare(const void *a, const void *b) | ||
398 | { | ||
399 | xfs_dir_sf_sort_t *sa, *sb; | ||
400 | |||
401 | sa = (xfs_dir_sf_sort_t *)a; | ||
402 | sb = (xfs_dir_sf_sort_t *)b; | ||
403 | if (sa->hash < sb->hash) | ||
404 | return -1; | ||
405 | else if (sa->hash > sb->hash) | ||
406 | return 1; | ||
407 | else | ||
408 | return sa->entno - sb->entno; | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * Copy out directory entries for getdents(), for shortform directories. | ||
413 | */ | ||
414 | /*ARGSUSED*/ | ||
415 | int | ||
416 | xfs_dir_shortform_getdents(xfs_inode_t *dp, uio_t *uio, int *eofp, | ||
417 | xfs_dirent_t *dbp, xfs_dir_put_t put) | ||
418 | { | ||
419 | xfs_dir_shortform_t *sf; | ||
420 | xfs_dir_sf_entry_t *sfe; | ||
421 | int retval, i, sbsize, nsbuf, lastresid=0, want_entno; | ||
422 | xfs_mount_t *mp; | ||
423 | xfs_dahash_t cookhash, hash; | ||
424 | xfs_dir_put_args_t p; | ||
425 | xfs_dir_sf_sort_t *sbuf, *sbp; | ||
426 | |||
427 | mp = dp->i_mount; | ||
428 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
429 | cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); | ||
430 | want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); | ||
431 | nsbuf = sf->hdr.count + 2; | ||
432 | sbsize = (nsbuf + 1) * sizeof(*sbuf); | ||
433 | sbp = sbuf = kmem_alloc(sbsize, KM_SLEEP); | ||
434 | |||
435 | xfs_dir_trace_g_du("sf: start", dp, uio); | ||
436 | |||
437 | /* | ||
438 | * Collect all the entries into the buffer. | ||
439 | * Entry 0 is . | ||
440 | */ | ||
441 | sbp->entno = 0; | ||
442 | sbp->seqno = 0; | ||
443 | sbp->hash = xfs_dir_hash_dot; | ||
444 | sbp->ino = dp->i_ino; | ||
445 | sbp->name = "."; | ||
446 | sbp->namelen = 1; | ||
447 | sbp++; | ||
448 | |||
449 | /* | ||
450 | * Entry 1 is .. | ||
451 | */ | ||
452 | sbp->entno = 1; | ||
453 | sbp->seqno = 0; | ||
454 | sbp->hash = xfs_dir_hash_dotdot; | ||
455 | sbp->ino = XFS_GET_DIR_INO8(sf->hdr.parent); | ||
456 | sbp->name = ".."; | ||
457 | sbp->namelen = 2; | ||
458 | sbp++; | ||
459 | |||
460 | /* | ||
461 | * Scan the directory data for the rest of the entries. | ||
462 | */ | ||
463 | for (i = 0, sfe = &sf->list[0]; i < sf->hdr.count; i++) { | ||
464 | |||
465 | if (unlikely( | ||
466 | ((char *)sfe < (char *)sf) || | ||
467 | ((char *)sfe >= ((char *)sf + dp->i_df.if_bytes)))) { | ||
468 | xfs_dir_trace_g_du("sf: corrupted", dp, uio); | ||
469 | XFS_CORRUPTION_ERROR("xfs_dir_shortform_getdents", | ||
470 | XFS_ERRLEVEL_LOW, mp, sfe); | ||
471 | kmem_free(sbuf, sbsize); | ||
472 | return XFS_ERROR(EFSCORRUPTED); | ||
473 | } | ||
474 | |||
475 | sbp->entno = i + 2; | ||
476 | sbp->seqno = 0; | ||
477 | sbp->hash = xfs_da_hashname((char *)sfe->name, sfe->namelen); | ||
478 | sbp->ino = XFS_GET_DIR_INO8(sfe->inumber); | ||
479 | sbp->name = (char *)sfe->name; | ||
480 | sbp->namelen = sfe->namelen; | ||
481 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
482 | sbp++; | ||
483 | } | ||
484 | |||
485 | /* | ||
486 | * Sort the entries on hash then entno. | ||
487 | */ | ||
488 | xfs_sort(sbuf, nsbuf, sizeof(*sbuf), xfs_dir_shortform_compare); | ||
489 | /* | ||
490 | * Stuff in last entry. | ||
491 | */ | ||
492 | sbp->entno = nsbuf; | ||
493 | sbp->hash = XFS_DA_MAXHASH; | ||
494 | sbp->seqno = 0; | ||
495 | /* | ||
496 | * Figure out the sequence numbers in case there's a hash duplicate. | ||
497 | */ | ||
498 | for (hash = sbuf->hash, sbp = sbuf + 1; | ||
499 | sbp < &sbuf[nsbuf + 1]; sbp++) { | ||
500 | if (sbp->hash == hash) | ||
501 | sbp->seqno = sbp[-1].seqno + 1; | ||
502 | else | ||
503 | hash = sbp->hash; | ||
504 | } | ||
505 | |||
506 | /* | ||
507 | * Set up put routine. | ||
508 | */ | ||
509 | p.dbp = dbp; | ||
510 | p.put = put; | ||
511 | p.uio = uio; | ||
512 | |||
513 | /* | ||
514 | * Find our place. | ||
515 | */ | ||
516 | for (sbp = sbuf; sbp < &sbuf[nsbuf + 1]; sbp++) { | ||
517 | if (sbp->hash > cookhash || | ||
518 | (sbp->hash == cookhash && sbp->seqno >= want_entno)) | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * Did we fail to find anything? We stop at the last entry, | ||
524 | * the one we put maxhash into. | ||
525 | */ | ||
526 | if (sbp == &sbuf[nsbuf]) { | ||
527 | kmem_free(sbuf, sbsize); | ||
528 | xfs_dir_trace_g_du("sf: hash beyond end", dp, uio); | ||
529 | uio->uio_offset = XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); | ||
530 | *eofp = 1; | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | /* | ||
535 | * Loop putting entries into the user buffer. | ||
536 | */ | ||
537 | while (sbp < &sbuf[nsbuf]) { | ||
538 | /* | ||
539 | * Save the first resid in a run of equal-hashval entries | ||
540 | * so that we can back them out if they don't all fit. | ||
541 | */ | ||
542 | if (sbp->seqno == 0 || sbp == sbuf) | ||
543 | lastresid = uio->uio_resid; | ||
544 | XFS_PUT_COOKIE(p.cook, mp, 0, sbp[1].seqno, sbp[1].hash); | ||
545 | p.ino = sbp->ino; | ||
546 | #if XFS_BIG_INUMS | ||
547 | p.ino += mp->m_inoadd; | ||
548 | #endif | ||
549 | p.name = sbp->name; | ||
550 | p.namelen = sbp->namelen; | ||
551 | retval = p.put(&p); | ||
552 | if (!p.done) { | ||
553 | uio->uio_offset = | ||
554 | XFS_DA_MAKE_COOKIE(mp, 0, 0, sbp->hash); | ||
555 | kmem_free(sbuf, sbsize); | ||
556 | uio->uio_resid = lastresid; | ||
557 | xfs_dir_trace_g_du("sf: E-O-B", dp, uio); | ||
558 | return retval; | ||
559 | } | ||
560 | sbp++; | ||
561 | } | ||
562 | kmem_free(sbuf, sbsize); | ||
563 | uio->uio_offset = p.cook.o; | ||
564 | *eofp = 1; | ||
565 | xfs_dir_trace_g_du("sf: E-O-F", dp, uio); | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | /* | ||
570 | * Look up a name in a shortform directory structure, replace the inode number. | ||
571 | */ | ||
572 | int | ||
573 | xfs_dir_shortform_replace(xfs_da_args_t *args) | ||
574 | { | ||
575 | xfs_dir_shortform_t *sf; | ||
576 | xfs_dir_sf_entry_t *sfe; | ||
577 | xfs_inode_t *dp; | ||
578 | int i; | ||
579 | |||
580 | dp = args->dp; | ||
581 | ASSERT(dp->i_df.if_flags & XFS_IFINLINE); | ||
582 | /* | ||
583 | * Catch the case where the conversion from shortform to leaf | ||
584 | * failed part way through. | ||
585 | */ | ||
586 | if (dp->i_d.di_size < sizeof(xfs_dir_sf_hdr_t)) { | ||
587 | ASSERT(XFS_FORCED_SHUTDOWN(dp->i_mount)); | ||
588 | return XFS_ERROR(EIO); | ||
589 | } | ||
590 | ASSERT(dp->i_df.if_bytes == dp->i_d.di_size); | ||
591 | ASSERT(dp->i_df.if_u1.if_data != NULL); | ||
592 | sf = (xfs_dir_shortform_t *)dp->i_df.if_u1.if_data; | ||
593 | if (args->namelen == 2 && | ||
594 | args->name[0] == '.' && args->name[1] == '.') { | ||
595 | /* XXX - replace assert? */ | ||
596 | XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sf->hdr.parent); | ||
597 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); | ||
598 | return 0; | ||
599 | } | ||
600 | ASSERT(args->namelen != 1 || args->name[0] != '.'); | ||
601 | sfe = &sf->list[0]; | ||
602 | for (i = sf->hdr.count-1; i >= 0; i--) { | ||
603 | if (sfe->namelen == args->namelen && | ||
604 | sfe->name[0] == args->name[0] && | ||
605 | memcmp(args->name, sfe->name, args->namelen) == 0) { | ||
606 | ASSERT(memcmp((char *)&args->inumber, | ||
607 | (char *)&sfe->inumber, sizeof(xfs_ino_t))); | ||
608 | XFS_DIR_SF_PUT_DIRINO(&args->inumber, &sfe->inumber); | ||
609 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_DDATA); | ||
610 | return 0; | ||
611 | } | ||
612 | sfe = XFS_DIR_SF_NEXTENTRY(sfe); | ||
613 | } | ||
614 | ASSERT(args->oknoent); | ||
615 | return XFS_ERROR(ENOENT); | ||
616 | } | ||
617 | |||
618 | /* | ||
619 | * Convert a leaf directory to shortform structure | ||
620 | */ | ||
621 | int | ||
622 | xfs_dir_leaf_to_shortform(xfs_da_args_t *iargs) | ||
623 | { | ||
624 | xfs_dir_leafblock_t *leaf; | ||
625 | xfs_dir_leaf_hdr_t *hdr; | ||
626 | xfs_dir_leaf_entry_t *entry; | ||
627 | xfs_dir_leaf_name_t *namest; | ||
628 | xfs_da_args_t args; | ||
629 | xfs_inode_t *dp; | ||
630 | xfs_ino_t parent = 0; | ||
631 | char *tmpbuffer; | ||
632 | int retval, i; | ||
633 | xfs_dabuf_t *bp; | ||
634 | |||
635 | dp = iargs->dp; | ||
636 | tmpbuffer = kmem_alloc(XFS_LBSIZE(dp->i_mount), KM_SLEEP); | ||
637 | ASSERT(tmpbuffer != NULL); | ||
638 | |||
639 | retval = xfs_da_read_buf(iargs->trans, iargs->dp, 0, -1, &bp, | ||
640 | XFS_DATA_FORK); | ||
641 | if (retval) | ||
642 | goto out; | ||
643 | ASSERT(bp != NULL); | ||
644 | memcpy(tmpbuffer, bp->data, XFS_LBSIZE(dp->i_mount)); | ||
645 | leaf = (xfs_dir_leafblock_t *)tmpbuffer; | ||
646 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
647 | memset(bp->data, 0, XFS_LBSIZE(dp->i_mount)); | ||
648 | |||
649 | /* | ||
650 | * Find and special case the parent inode number | ||
651 | */ | ||
652 | hdr = &leaf->hdr; | ||
653 | entry = &leaf->entries[0]; | ||
654 | for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { | ||
655 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
656 | if ((entry->namelen == 2) && | ||
657 | (namest->name[0] == '.') && | ||
658 | (namest->name[1] == '.')) { | ||
659 | XFS_DIR_SF_GET_DIRINO(&namest->inumber, &parent); | ||
660 | entry->nameidx = 0; | ||
661 | } else if ((entry->namelen == 1) && (namest->name[0] == '.')) { | ||
662 | entry->nameidx = 0; | ||
663 | } | ||
664 | } | ||
665 | retval = xfs_da_shrink_inode(iargs, 0, bp); | ||
666 | if (retval) | ||
667 | goto out; | ||
668 | retval = xfs_dir_shortform_create(iargs, parent); | ||
669 | if (retval) | ||
670 | goto out; | ||
671 | |||
672 | /* | ||
673 | * Copy the rest of the filenames | ||
674 | */ | ||
675 | entry = &leaf->entries[0]; | ||
676 | args.dp = dp; | ||
677 | args.firstblock = iargs->firstblock; | ||
678 | args.flist = iargs->flist; | ||
679 | args.total = iargs->total; | ||
680 | args.whichfork = XFS_DATA_FORK; | ||
681 | args.trans = iargs->trans; | ||
682 | args.justcheck = 0; | ||
683 | args.addname = args.oknoent = 1; | ||
684 | for (i = 0; i < INT_GET(hdr->count, ARCH_CONVERT); entry++, i++) { | ||
685 | if (!entry->nameidx) | ||
686 | continue; | ||
687 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
688 | args.name = (char *)(namest->name); | ||
689 | args.namelen = entry->namelen; | ||
690 | args.hashval = INT_GET(entry->hashval, ARCH_CONVERT); | ||
691 | XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args.inumber); | ||
692 | xfs_dir_shortform_addname(&args); | ||
693 | } | ||
694 | |||
695 | out: | ||
696 | kmem_free(tmpbuffer, XFS_LBSIZE(dp->i_mount)); | ||
697 | return retval; | ||
698 | } | ||
699 | |||
700 | /* | ||
701 | * Convert from using a single leaf to a root node and a leaf. | ||
702 | */ | ||
703 | int | ||
704 | xfs_dir_leaf_to_node(xfs_da_args_t *args) | ||
705 | { | ||
706 | xfs_dir_leafblock_t *leaf; | ||
707 | xfs_da_intnode_t *node; | ||
708 | xfs_inode_t *dp; | ||
709 | xfs_dabuf_t *bp1, *bp2; | ||
710 | xfs_dablk_t blkno; | ||
711 | int retval; | ||
712 | |||
713 | dp = args->dp; | ||
714 | retval = xfs_da_grow_inode(args, &blkno); | ||
715 | ASSERT(blkno == 1); | ||
716 | if (retval) | ||
717 | return retval; | ||
718 | retval = xfs_da_read_buf(args->trans, args->dp, 0, -1, &bp1, | ||
719 | XFS_DATA_FORK); | ||
720 | if (retval) | ||
721 | return retval; | ||
722 | ASSERT(bp1 != NULL); | ||
723 | retval = xfs_da_get_buf(args->trans, args->dp, 1, -1, &bp2, | ||
724 | XFS_DATA_FORK); | ||
725 | if (retval) { | ||
726 | xfs_da_buf_done(bp1); | ||
727 | return retval; | ||
728 | } | ||
729 | ASSERT(bp2 != NULL); | ||
730 | memcpy(bp2->data, bp1->data, XFS_LBSIZE(dp->i_mount)); | ||
731 | xfs_da_buf_done(bp1); | ||
732 | xfs_da_log_buf(args->trans, bp2, 0, XFS_LBSIZE(dp->i_mount) - 1); | ||
733 | |||
734 | /* | ||
735 | * Set up the new root node. | ||
736 | */ | ||
737 | retval = xfs_da_node_create(args, 0, 1, &bp1, XFS_DATA_FORK); | ||
738 | if (retval) { | ||
739 | xfs_da_buf_done(bp2); | ||
740 | return retval; | ||
741 | } | ||
742 | node = bp1->data; | ||
743 | leaf = bp2->data; | ||
744 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
745 | node->btree[0].hashval = cpu_to_be32( | ||
746 | INT_GET(leaf->entries[ | ||
747 | INT_GET(leaf->hdr.count, ARCH_CONVERT)-1].hashval, ARCH_CONVERT)); | ||
748 | xfs_da_buf_done(bp2); | ||
749 | node->btree[0].before = cpu_to_be32(blkno); | ||
750 | node->hdr.count = cpu_to_be16(1); | ||
751 | xfs_da_log_buf(args->trans, bp1, | ||
752 | XFS_DA_LOGRANGE(node, &node->btree[0], sizeof(node->btree[0]))); | ||
753 | xfs_da_buf_done(bp1); | ||
754 | |||
755 | return retval; | ||
756 | } | ||
757 | |||
758 | |||
759 | /*======================================================================== | ||
760 | * Routines used for growing the Btree. | ||
761 | *========================================================================*/ | ||
762 | |||
763 | /* | ||
764 | * Create the initial contents of a leaf directory | ||
765 | * or a leaf in a node directory. | ||
766 | */ | ||
767 | STATIC int | ||
768 | xfs_dir_leaf_create(xfs_da_args_t *args, xfs_dablk_t blkno, xfs_dabuf_t **bpp) | ||
769 | { | ||
770 | xfs_dir_leafblock_t *leaf; | ||
771 | xfs_dir_leaf_hdr_t *hdr; | ||
772 | xfs_inode_t *dp; | ||
773 | xfs_dabuf_t *bp; | ||
774 | int retval; | ||
775 | |||
776 | dp = args->dp; | ||
777 | ASSERT(dp != NULL); | ||
778 | retval = xfs_da_get_buf(args->trans, dp, blkno, -1, &bp, XFS_DATA_FORK); | ||
779 | if (retval) | ||
780 | return retval; | ||
781 | ASSERT(bp != NULL); | ||
782 | leaf = bp->data; | ||
783 | memset((char *)leaf, 0, XFS_LBSIZE(dp->i_mount)); | ||
784 | hdr = &leaf->hdr; | ||
785 | hdr->info.magic = cpu_to_be16(XFS_DIR_LEAF_MAGIC); | ||
786 | INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount)); | ||
787 | if (!hdr->firstused) | ||
788 | INT_SET(hdr->firstused, ARCH_CONVERT, XFS_LBSIZE(dp->i_mount) - 1); | ||
789 | INT_SET(hdr->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); | ||
790 | INT_SET(hdr->freemap[0].size, ARCH_CONVERT, INT_GET(hdr->firstused, ARCH_CONVERT) - INT_GET(hdr->freemap[0].base, ARCH_CONVERT)); | ||
791 | |||
792 | xfs_da_log_buf(args->trans, bp, 0, XFS_LBSIZE(dp->i_mount) - 1); | ||
793 | |||
794 | *bpp = bp; | ||
795 | return 0; | ||
796 | } | ||
797 | |||
798 | /* | ||
799 | * Split the leaf node, rebalance, then add the new entry. | ||
800 | */ | ||
801 | int | ||
802 | xfs_dir_leaf_split(xfs_da_state_t *state, xfs_da_state_blk_t *oldblk, | ||
803 | xfs_da_state_blk_t *newblk) | ||
804 | { | ||
805 | xfs_dablk_t blkno; | ||
806 | xfs_da_args_t *args; | ||
807 | int error; | ||
808 | |||
809 | /* | ||
810 | * Allocate space for a new leaf node. | ||
811 | */ | ||
812 | args = state->args; | ||
813 | ASSERT(args != NULL); | ||
814 | ASSERT(oldblk->magic == XFS_DIR_LEAF_MAGIC); | ||
815 | error = xfs_da_grow_inode(args, &blkno); | ||
816 | if (error) | ||
817 | return error; | ||
818 | error = xfs_dir_leaf_create(args, blkno, &newblk->bp); | ||
819 | if (error) | ||
820 | return error; | ||
821 | newblk->blkno = blkno; | ||
822 | newblk->magic = XFS_DIR_LEAF_MAGIC; | ||
823 | |||
824 | /* | ||
825 | * Rebalance the entries across the two leaves. | ||
826 | */ | ||
827 | xfs_dir_leaf_rebalance(state, oldblk, newblk); | ||
828 | error = xfs_da_blk_link(state, oldblk, newblk); | ||
829 | if (error) | ||
830 | return error; | ||
831 | |||
832 | /* | ||
833 | * Insert the new entry in the correct block. | ||
834 | */ | ||
835 | if (state->inleaf) { | ||
836 | error = xfs_dir_leaf_add(oldblk->bp, args, oldblk->index); | ||
837 | } else { | ||
838 | error = xfs_dir_leaf_add(newblk->bp, args, newblk->index); | ||
839 | } | ||
840 | |||
841 | /* | ||
842 | * Update last hashval in each block since we added the name. | ||
843 | */ | ||
844 | oldblk->hashval = xfs_dir_leaf_lasthash(oldblk->bp, NULL); | ||
845 | newblk->hashval = xfs_dir_leaf_lasthash(newblk->bp, NULL); | ||
846 | return error; | ||
847 | } | ||
848 | |||
849 | /* | ||
850 | * Add a name to the leaf directory structure. | ||
851 | * | ||
852 | * Must take into account fragmented leaves and leaves where spacemap has | ||
853 | * lost some freespace information (ie: holes). | ||
854 | */ | ||
855 | int | ||
856 | xfs_dir_leaf_add(xfs_dabuf_t *bp, xfs_da_args_t *args, int index) | ||
857 | { | ||
858 | xfs_dir_leafblock_t *leaf; | ||
859 | xfs_dir_leaf_hdr_t *hdr; | ||
860 | xfs_dir_leaf_map_t *map; | ||
861 | int tablesize, entsize, sum, i, tmp, error; | ||
862 | |||
863 | leaf = bp->data; | ||
864 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
865 | ASSERT((index >= 0) && (index <= INT_GET(leaf->hdr.count, ARCH_CONVERT))); | ||
866 | hdr = &leaf->hdr; | ||
867 | entsize = XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen); | ||
868 | |||
869 | /* | ||
870 | * Search through freemap for first-fit on new name length. | ||
871 | * (may need to figure in size of entry struct too) | ||
872 | */ | ||
873 | tablesize = (INT_GET(hdr->count, ARCH_CONVERT) + 1) * (uint)sizeof(xfs_dir_leaf_entry_t) | ||
874 | + (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
875 | map = &hdr->freemap[XFS_DIR_LEAF_MAPSIZE-1]; | ||
876 | for (sum = 0, i = XFS_DIR_LEAF_MAPSIZE-1; i >= 0; map--, i--) { | ||
877 | if (tablesize > INT_GET(hdr->firstused, ARCH_CONVERT)) { | ||
878 | sum += INT_GET(map->size, ARCH_CONVERT); | ||
879 | continue; | ||
880 | } | ||
881 | if (!map->size) | ||
882 | continue; /* no space in this map */ | ||
883 | tmp = entsize; | ||
884 | if (INT_GET(map->base, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) | ||
885 | tmp += (uint)sizeof(xfs_dir_leaf_entry_t); | ||
886 | if (INT_GET(map->size, ARCH_CONVERT) >= tmp) { | ||
887 | if (!args->justcheck) | ||
888 | xfs_dir_leaf_add_work(bp, args, index, i); | ||
889 | return 0; | ||
890 | } | ||
891 | sum += INT_GET(map->size, ARCH_CONVERT); | ||
892 | } | ||
893 | |||
894 | /* | ||
895 | * If there are no holes in the address space of the block, | ||
896 | * and we don't have enough freespace, then compaction will do us | ||
897 | * no good and we should just give up. | ||
898 | */ | ||
899 | if (!hdr->holes && (sum < entsize)) | ||
900 | return XFS_ERROR(ENOSPC); | ||
901 | |||
902 | /* | ||
903 | * Compact the entries to coalesce free space. | ||
904 | * Pass the justcheck flag so the checking pass can return | ||
905 | * an error, without changing anything, if it won't fit. | ||
906 | */ | ||
907 | error = xfs_dir_leaf_compact(args->trans, bp, | ||
908 | args->total == 0 ? | ||
909 | entsize + | ||
910 | (uint)sizeof(xfs_dir_leaf_entry_t) : 0, | ||
911 | args->justcheck); | ||
912 | if (error) | ||
913 | return error; | ||
914 | /* | ||
915 | * After compaction, the block is guaranteed to have only one | ||
916 | * free region, in freemap[0]. If it is not big enough, give up. | ||
917 | */ | ||
918 | if (INT_GET(hdr->freemap[0].size, ARCH_CONVERT) < | ||
919 | (entsize + (uint)sizeof(xfs_dir_leaf_entry_t))) | ||
920 | return XFS_ERROR(ENOSPC); | ||
921 | |||
922 | if (!args->justcheck) | ||
923 | xfs_dir_leaf_add_work(bp, args, index, 0); | ||
924 | return 0; | ||
925 | } | ||
926 | |||
927 | /* | ||
928 | * Add a name to a leaf directory structure. | ||
929 | */ | ||
930 | STATIC void | ||
931 | xfs_dir_leaf_add_work(xfs_dabuf_t *bp, xfs_da_args_t *args, int index, | ||
932 | int mapindex) | ||
933 | { | ||
934 | xfs_dir_leafblock_t *leaf; | ||
935 | xfs_dir_leaf_hdr_t *hdr; | ||
936 | xfs_dir_leaf_entry_t *entry; | ||
937 | xfs_dir_leaf_name_t *namest; | ||
938 | xfs_dir_leaf_map_t *map; | ||
939 | /* REFERENCED */ | ||
940 | xfs_mount_t *mp; | ||
941 | int tmp, i; | ||
942 | |||
943 | leaf = bp->data; | ||
944 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
945 | hdr = &leaf->hdr; | ||
946 | ASSERT((mapindex >= 0) && (mapindex < XFS_DIR_LEAF_MAPSIZE)); | ||
947 | ASSERT((index >= 0) && (index <= INT_GET(hdr->count, ARCH_CONVERT))); | ||
948 | |||
949 | /* | ||
950 | * Force open some space in the entry array and fill it in. | ||
951 | */ | ||
952 | entry = &leaf->entries[index]; | ||
953 | if (index < INT_GET(hdr->count, ARCH_CONVERT)) { | ||
954 | tmp = INT_GET(hdr->count, ARCH_CONVERT) - index; | ||
955 | tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); | ||
956 | memmove(entry + 1, entry, tmp); | ||
957 | xfs_da_log_buf(args->trans, bp, | ||
958 | XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); | ||
959 | } | ||
960 | INT_MOD(hdr->count, ARCH_CONVERT, +1); | ||
961 | |||
962 | /* | ||
963 | * Allocate space for the new string (at the end of the run). | ||
964 | */ | ||
965 | map = &hdr->freemap[mapindex]; | ||
966 | mp = args->trans->t_mountp; | ||
967 | ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
968 | ASSERT(INT_GET(map->size, ARCH_CONVERT) >= XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen)); | ||
969 | ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
970 | INT_MOD(map->size, ARCH_CONVERT, -(XFS_DIR_LEAF_ENTSIZE_BYNAME(args->namelen))); | ||
971 | INT_SET(entry->nameidx, ARCH_CONVERT, INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)); | ||
972 | INT_SET(entry->hashval, ARCH_CONVERT, args->hashval); | ||
973 | entry->namelen = args->namelen; | ||
974 | xfs_da_log_buf(args->trans, bp, | ||
975 | XFS_DA_LOGRANGE(leaf, entry, sizeof(*entry))); | ||
976 | |||
977 | /* | ||
978 | * Copy the string and inode number into the new space. | ||
979 | */ | ||
980 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
981 | XFS_DIR_SF_PUT_DIRINO(&args->inumber, &namest->inumber); | ||
982 | memcpy(namest->name, args->name, args->namelen); | ||
983 | xfs_da_log_buf(args->trans, bp, | ||
984 | XFS_DA_LOGRANGE(leaf, namest, XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry))); | ||
985 | |||
986 | /* | ||
987 | * Update the control info for this leaf node | ||
988 | */ | ||
989 | if (INT_GET(entry->nameidx, ARCH_CONVERT) < INT_GET(hdr->firstused, ARCH_CONVERT)) | ||
990 | INT_COPY(hdr->firstused, entry->nameidx, ARCH_CONVERT); | ||
991 | ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); | ||
992 | tmp = (INT_GET(hdr->count, ARCH_CONVERT)-1) * (uint)sizeof(xfs_dir_leaf_entry_t) | ||
993 | + (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
994 | map = &hdr->freemap[0]; | ||
995 | for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { | ||
996 | if (INT_GET(map->base, ARCH_CONVERT) == tmp) { | ||
997 | INT_MOD(map->base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); | ||
998 | INT_MOD(map->size, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); | ||
999 | } | ||
1000 | } | ||
1001 | INT_MOD(hdr->namebytes, ARCH_CONVERT, args->namelen); | ||
1002 | xfs_da_log_buf(args->trans, bp, | ||
1003 | XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); | ||
1004 | } | ||
1005 | |||
1006 | /* | ||
1007 | * Garbage collect a leaf directory block by copying it to a new buffer. | ||
1008 | */ | ||
1009 | STATIC int | ||
1010 | xfs_dir_leaf_compact(xfs_trans_t *trans, xfs_dabuf_t *bp, int musthave, | ||
1011 | int justcheck) | ||
1012 | { | ||
1013 | xfs_dir_leafblock_t *leaf_s, *leaf_d; | ||
1014 | xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; | ||
1015 | xfs_mount_t *mp; | ||
1016 | char *tmpbuffer; | ||
1017 | char *tmpbuffer2=NULL; | ||
1018 | int rval; | ||
1019 | int lbsize; | ||
1020 | |||
1021 | mp = trans->t_mountp; | ||
1022 | lbsize = XFS_LBSIZE(mp); | ||
1023 | tmpbuffer = kmem_alloc(lbsize, KM_SLEEP); | ||
1024 | ASSERT(tmpbuffer != NULL); | ||
1025 | memcpy(tmpbuffer, bp->data, lbsize); | ||
1026 | |||
1027 | /* | ||
1028 | * Make a second copy in case xfs_dir_leaf_moveents() | ||
1029 | * below destroys the original. | ||
1030 | */ | ||
1031 | if (musthave || justcheck) { | ||
1032 | tmpbuffer2 = kmem_alloc(lbsize, KM_SLEEP); | ||
1033 | memcpy(tmpbuffer2, bp->data, lbsize); | ||
1034 | } | ||
1035 | memset(bp->data, 0, lbsize); | ||
1036 | |||
1037 | /* | ||
1038 | * Copy basic information | ||
1039 | */ | ||
1040 | leaf_s = (xfs_dir_leafblock_t *)tmpbuffer; | ||
1041 | leaf_d = bp->data; | ||
1042 | hdr_s = &leaf_s->hdr; | ||
1043 | hdr_d = &leaf_d->hdr; | ||
1044 | hdr_d->info = hdr_s->info; /* struct copy */ | ||
1045 | INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize); | ||
1046 | if (!hdr_d->firstused) | ||
1047 | INT_SET(hdr_d->firstused, ARCH_CONVERT, lbsize - 1); | ||
1048 | hdr_d->namebytes = 0; | ||
1049 | hdr_d->count = 0; | ||
1050 | hdr_d->holes = 0; | ||
1051 | INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, sizeof(xfs_dir_leaf_hdr_t)); | ||
1052 | INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); | ||
1053 | |||
1054 | /* | ||
1055 | * Copy all entry's in the same (sorted) order, | ||
1056 | * but allocate filenames packed and in sequence. | ||
1057 | * This changes the source (leaf_s) as well. | ||
1058 | */ | ||
1059 | xfs_dir_leaf_moveents(leaf_s, 0, leaf_d, 0, (int)INT_GET(hdr_s->count, ARCH_CONVERT), mp); | ||
1060 | |||
1061 | if (musthave && INT_GET(hdr_d->freemap[0].size, ARCH_CONVERT) < musthave) | ||
1062 | rval = XFS_ERROR(ENOSPC); | ||
1063 | else | ||
1064 | rval = 0; | ||
1065 | |||
1066 | if (justcheck || rval == ENOSPC) { | ||
1067 | ASSERT(tmpbuffer2); | ||
1068 | memcpy(bp->data, tmpbuffer2, lbsize); | ||
1069 | } else { | ||
1070 | xfs_da_log_buf(trans, bp, 0, lbsize - 1); | ||
1071 | } | ||
1072 | |||
1073 | kmem_free(tmpbuffer, lbsize); | ||
1074 | if (musthave || justcheck) | ||
1075 | kmem_free(tmpbuffer2, lbsize); | ||
1076 | return rval; | ||
1077 | } | ||
1078 | |||
1079 | /* | ||
1080 | * Redistribute the directory entries between two leaf nodes, | ||
1081 | * taking into account the size of the new entry. | ||
1082 | * | ||
1083 | * NOTE: if new block is empty, then it will get the upper half of old block. | ||
1084 | */ | ||
1085 | STATIC void | ||
1086 | xfs_dir_leaf_rebalance(xfs_da_state_t *state, xfs_da_state_blk_t *blk1, | ||
1087 | xfs_da_state_blk_t *blk2) | ||
1088 | { | ||
1089 | xfs_da_state_blk_t *tmp_blk; | ||
1090 | xfs_dir_leafblock_t *leaf1, *leaf2; | ||
1091 | xfs_dir_leaf_hdr_t *hdr1, *hdr2; | ||
1092 | int count, totallen, max, space, swap; | ||
1093 | |||
1094 | /* | ||
1095 | * Set up environment. | ||
1096 | */ | ||
1097 | ASSERT(blk1->magic == XFS_DIR_LEAF_MAGIC); | ||
1098 | ASSERT(blk2->magic == XFS_DIR_LEAF_MAGIC); | ||
1099 | leaf1 = blk1->bp->data; | ||
1100 | leaf2 = blk2->bp->data; | ||
1101 | ASSERT(be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1102 | ASSERT(be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1103 | |||
1104 | /* | ||
1105 | * Check ordering of blocks, reverse if it makes things simpler. | ||
1106 | */ | ||
1107 | swap = 0; | ||
1108 | if (xfs_dir_leaf_order(blk1->bp, blk2->bp)) { | ||
1109 | tmp_blk = blk1; | ||
1110 | blk1 = blk2; | ||
1111 | blk2 = tmp_blk; | ||
1112 | leaf1 = blk1->bp->data; | ||
1113 | leaf2 = blk2->bp->data; | ||
1114 | swap = 1; | ||
1115 | } | ||
1116 | hdr1 = &leaf1->hdr; | ||
1117 | hdr2 = &leaf2->hdr; | ||
1118 | |||
1119 | /* | ||
1120 | * Examine entries until we reduce the absolute difference in | ||
1121 | * byte usage between the two blocks to a minimum. Then get | ||
1122 | * the direction to copy and the number of elements to move. | ||
1123 | */ | ||
1124 | state->inleaf = xfs_dir_leaf_figure_balance(state, blk1, blk2, | ||
1125 | &count, &totallen); | ||
1126 | if (swap) | ||
1127 | state->inleaf = !state->inleaf; | ||
1128 | |||
1129 | /* | ||
1130 | * Move any entries required from leaf to leaf: | ||
1131 | */ | ||
1132 | if (count < INT_GET(hdr1->count, ARCH_CONVERT)) { | ||
1133 | /* | ||
1134 | * Figure the total bytes to be added to the destination leaf. | ||
1135 | */ | ||
1136 | count = INT_GET(hdr1->count, ARCH_CONVERT) - count; /* number entries being moved */ | ||
1137 | space = INT_GET(hdr1->namebytes, ARCH_CONVERT) - totallen; | ||
1138 | space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); | ||
1139 | space += count * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1140 | |||
1141 | /* | ||
1142 | * leaf2 is the destination, compact it if it looks tight. | ||
1143 | */ | ||
1144 | max = INT_GET(hdr2->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1145 | max -= INT_GET(hdr2->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1146 | if (space > max) { | ||
1147 | xfs_dir_leaf_compact(state->args->trans, blk2->bp, | ||
1148 | 0, 0); | ||
1149 | } | ||
1150 | |||
1151 | /* | ||
1152 | * Move high entries from leaf1 to low end of leaf2. | ||
1153 | */ | ||
1154 | xfs_dir_leaf_moveents(leaf1, INT_GET(hdr1->count, ARCH_CONVERT) - count, | ||
1155 | leaf2, 0, count, state->mp); | ||
1156 | |||
1157 | xfs_da_log_buf(state->args->trans, blk1->bp, 0, | ||
1158 | state->blocksize-1); | ||
1159 | xfs_da_log_buf(state->args->trans, blk2->bp, 0, | ||
1160 | state->blocksize-1); | ||
1161 | |||
1162 | } else if (count > INT_GET(hdr1->count, ARCH_CONVERT)) { | ||
1163 | /* | ||
1164 | * Figure the total bytes to be added to the destination leaf. | ||
1165 | */ | ||
1166 | count -= INT_GET(hdr1->count, ARCH_CONVERT); /* number entries being moved */ | ||
1167 | space = totallen - INT_GET(hdr1->namebytes, ARCH_CONVERT); | ||
1168 | space += count * ((uint)sizeof(xfs_dir_leaf_name_t)-1); | ||
1169 | space += count * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1170 | |||
1171 | /* | ||
1172 | * leaf1 is the destination, compact it if it looks tight. | ||
1173 | */ | ||
1174 | max = INT_GET(hdr1->firstused, ARCH_CONVERT) - (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1175 | max -= INT_GET(hdr1->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1176 | if (space > max) { | ||
1177 | xfs_dir_leaf_compact(state->args->trans, blk1->bp, | ||
1178 | 0, 0); | ||
1179 | } | ||
1180 | |||
1181 | /* | ||
1182 | * Move low entries from leaf2 to high end of leaf1. | ||
1183 | */ | ||
1184 | xfs_dir_leaf_moveents(leaf2, 0, leaf1, (int)INT_GET(hdr1->count, ARCH_CONVERT), | ||
1185 | count, state->mp); | ||
1186 | |||
1187 | xfs_da_log_buf(state->args->trans, blk1->bp, 0, | ||
1188 | state->blocksize-1); | ||
1189 | xfs_da_log_buf(state->args->trans, blk2->bp, 0, | ||
1190 | state->blocksize-1); | ||
1191 | } | ||
1192 | |||
1193 | /* | ||
1194 | * Copy out last hashval in each block for B-tree code. | ||
1195 | */ | ||
1196 | blk1->hashval = INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); | ||
1197 | blk2->hashval = INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); | ||
1198 | |||
1199 | /* | ||
1200 | * Adjust the expected index for insertion. | ||
1201 | * GROT: this doesn't work unless blk2 was originally empty. | ||
1202 | */ | ||
1203 | if (!state->inleaf) { | ||
1204 | blk2->index = blk1->index - INT_GET(leaf1->hdr.count, ARCH_CONVERT); | ||
1205 | } | ||
1206 | } | ||
1207 | |||
1208 | /* | ||
1209 | * Examine entries until we reduce the absolute difference in | ||
1210 | * byte usage between the two blocks to a minimum. | ||
1211 | * GROT: Is this really necessary? With other than a 512 byte blocksize, | ||
1212 | * GROT: there will always be enough room in either block for a new entry. | ||
1213 | * GROT: Do a double-split for this case? | ||
1214 | */ | ||
1215 | STATIC int | ||
1216 | xfs_dir_leaf_figure_balance(xfs_da_state_t *state, | ||
1217 | xfs_da_state_blk_t *blk1, | ||
1218 | xfs_da_state_blk_t *blk2, | ||
1219 | int *countarg, int *namebytesarg) | ||
1220 | { | ||
1221 | xfs_dir_leafblock_t *leaf1, *leaf2; | ||
1222 | xfs_dir_leaf_hdr_t *hdr1, *hdr2; | ||
1223 | xfs_dir_leaf_entry_t *entry; | ||
1224 | int count, max, totallen, half; | ||
1225 | int lastdelta, foundit, tmp; | ||
1226 | |||
1227 | /* | ||
1228 | * Set up environment. | ||
1229 | */ | ||
1230 | leaf1 = blk1->bp->data; | ||
1231 | leaf2 = blk2->bp->data; | ||
1232 | hdr1 = &leaf1->hdr; | ||
1233 | hdr2 = &leaf2->hdr; | ||
1234 | foundit = 0; | ||
1235 | totallen = 0; | ||
1236 | |||
1237 | /* | ||
1238 | * Examine entries until we reduce the absolute difference in | ||
1239 | * byte usage between the two blocks to a minimum. | ||
1240 | */ | ||
1241 | max = INT_GET(hdr1->count, ARCH_CONVERT) + INT_GET(hdr2->count, ARCH_CONVERT); | ||
1242 | half = (max+1) * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); | ||
1243 | half += INT_GET(hdr1->namebytes, ARCH_CONVERT) + INT_GET(hdr2->namebytes, ARCH_CONVERT) + state->args->namelen; | ||
1244 | half /= 2; | ||
1245 | lastdelta = state->blocksize; | ||
1246 | entry = &leaf1->entries[0]; | ||
1247 | for (count = 0; count < max; entry++, count++) { | ||
1248 | |||
1249 | #define XFS_DIR_ABS(A) (((A) < 0) ? -(A) : (A)) | ||
1250 | /* | ||
1251 | * The new entry is in the first block, account for it. | ||
1252 | */ | ||
1253 | if (count == blk1->index) { | ||
1254 | tmp = totallen + (uint)sizeof(*entry) | ||
1255 | + XFS_DIR_LEAF_ENTSIZE_BYNAME(state->args->namelen); | ||
1256 | if (XFS_DIR_ABS(half - tmp) > lastdelta) | ||
1257 | break; | ||
1258 | lastdelta = XFS_DIR_ABS(half - tmp); | ||
1259 | totallen = tmp; | ||
1260 | foundit = 1; | ||
1261 | } | ||
1262 | |||
1263 | /* | ||
1264 | * Wrap around into the second block if necessary. | ||
1265 | */ | ||
1266 | if (count == INT_GET(hdr1->count, ARCH_CONVERT)) { | ||
1267 | leaf1 = leaf2; | ||
1268 | entry = &leaf1->entries[0]; | ||
1269 | } | ||
1270 | |||
1271 | /* | ||
1272 | * Figure out if next leaf entry would be too much. | ||
1273 | */ | ||
1274 | tmp = totallen + (uint)sizeof(*entry) | ||
1275 | + XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); | ||
1276 | if (XFS_DIR_ABS(half - tmp) > lastdelta) | ||
1277 | break; | ||
1278 | lastdelta = XFS_DIR_ABS(half - tmp); | ||
1279 | totallen = tmp; | ||
1280 | #undef XFS_DIR_ABS | ||
1281 | } | ||
1282 | |||
1283 | /* | ||
1284 | * Calculate the number of namebytes that will end up in lower block. | ||
1285 | * If new entry not in lower block, fix up the count. | ||
1286 | */ | ||
1287 | totallen -= | ||
1288 | count * (uint)(sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1); | ||
1289 | if (foundit) { | ||
1290 | totallen -= (sizeof(*entry)+sizeof(xfs_dir_leaf_entry_t)-1) + | ||
1291 | state->args->namelen; | ||
1292 | } | ||
1293 | |||
1294 | *countarg = count; | ||
1295 | *namebytesarg = totallen; | ||
1296 | return foundit; | ||
1297 | } | ||
1298 | |||
1299 | /*======================================================================== | ||
1300 | * Routines used for shrinking the Btree. | ||
1301 | *========================================================================*/ | ||
1302 | |||
1303 | /* | ||
1304 | * Check a leaf block and its neighbors to see if the block should be | ||
1305 | * collapsed into one or the other neighbor. Always keep the block | ||
1306 | * with the smaller block number. | ||
1307 | * If the current block is over 50% full, don't try to join it, return 0. | ||
1308 | * If the block is empty, fill in the state structure and return 2. | ||
1309 | * If it can be collapsed, fill in the state structure and return 1. | ||
1310 | * If nothing can be done, return 0. | ||
1311 | */ | ||
1312 | int | ||
1313 | xfs_dir_leaf_toosmall(xfs_da_state_t *state, int *action) | ||
1314 | { | ||
1315 | xfs_dir_leafblock_t *leaf; | ||
1316 | xfs_da_state_blk_t *blk; | ||
1317 | xfs_da_blkinfo_t *info; | ||
1318 | int count, bytes, forward, error, retval, i; | ||
1319 | xfs_dablk_t blkno; | ||
1320 | xfs_dabuf_t *bp; | ||
1321 | |||
1322 | /* | ||
1323 | * Check for the degenerate case of the block being over 50% full. | ||
1324 | * If so, it's not worth even looking to see if we might be able | ||
1325 | * to coalesce with a sibling. | ||
1326 | */ | ||
1327 | blk = &state->path.blk[ state->path.active-1 ]; | ||
1328 | info = blk->bp->data; | ||
1329 | ASSERT(be16_to_cpu(info->magic) == XFS_DIR_LEAF_MAGIC); | ||
1330 | leaf = (xfs_dir_leafblock_t *)info; | ||
1331 | count = INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
1332 | bytes = (uint)sizeof(xfs_dir_leaf_hdr_t) + | ||
1333 | count * (uint)sizeof(xfs_dir_leaf_entry_t) + | ||
1334 | count * ((uint)sizeof(xfs_dir_leaf_name_t)-1) + | ||
1335 | INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); | ||
1336 | if (bytes > (state->blocksize >> 1)) { | ||
1337 | *action = 0; /* blk over 50%, don't try to join */ | ||
1338 | return 0; | ||
1339 | } | ||
1340 | |||
1341 | /* | ||
1342 | * Check for the degenerate case of the block being empty. | ||
1343 | * If the block is empty, we'll simply delete it, no need to | ||
1344 | * coalesce it with a sibling block. We choose (arbitrarily) | ||
1345 | * to merge with the forward block unless it is NULL. | ||
1346 | */ | ||
1347 | if (count == 0) { | ||
1348 | /* | ||
1349 | * Make altpath point to the block we want to keep and | ||
1350 | * path point to the block we want to drop (this one). | ||
1351 | */ | ||
1352 | forward = (info->forw != 0); | ||
1353 | memcpy(&state->altpath, &state->path, sizeof(state->path)); | ||
1354 | error = xfs_da_path_shift(state, &state->altpath, forward, | ||
1355 | 0, &retval); | ||
1356 | if (error) | ||
1357 | return error; | ||
1358 | if (retval) { | ||
1359 | *action = 0; | ||
1360 | } else { | ||
1361 | *action = 2; | ||
1362 | } | ||
1363 | return 0; | ||
1364 | } | ||
1365 | |||
1366 | /* | ||
1367 | * Examine each sibling block to see if we can coalesce with | ||
1368 | * at least 25% free space to spare. We need to figure out | ||
1369 | * whether to merge with the forward or the backward block. | ||
1370 | * We prefer coalescing with the lower numbered sibling so as | ||
1371 | * to shrink a directory over time. | ||
1372 | */ | ||
1373 | forward = (be32_to_cpu(info->forw) < be32_to_cpu(info->back)); /* start with smaller blk num */ | ||
1374 | for (i = 0; i < 2; forward = !forward, i++) { | ||
1375 | if (forward) | ||
1376 | blkno = be32_to_cpu(info->forw); | ||
1377 | else | ||
1378 | blkno = be32_to_cpu(info->back); | ||
1379 | if (blkno == 0) | ||
1380 | continue; | ||
1381 | error = xfs_da_read_buf(state->args->trans, state->args->dp, | ||
1382 | blkno, -1, &bp, | ||
1383 | XFS_DATA_FORK); | ||
1384 | if (error) | ||
1385 | return error; | ||
1386 | ASSERT(bp != NULL); | ||
1387 | |||
1388 | leaf = (xfs_dir_leafblock_t *)info; | ||
1389 | count = INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
1390 | bytes = state->blocksize - (state->blocksize>>2); | ||
1391 | bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); | ||
1392 | leaf = bp->data; | ||
1393 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1394 | count += INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
1395 | bytes -= INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); | ||
1396 | bytes -= count * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); | ||
1397 | bytes -= count * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1398 | bytes -= (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1399 | if (bytes >= 0) | ||
1400 | break; /* fits with at least 25% to spare */ | ||
1401 | |||
1402 | xfs_da_brelse(state->args->trans, bp); | ||
1403 | } | ||
1404 | if (i >= 2) { | ||
1405 | *action = 0; | ||
1406 | return 0; | ||
1407 | } | ||
1408 | xfs_da_buf_done(bp); | ||
1409 | |||
1410 | /* | ||
1411 | * Make altpath point to the block we want to keep (the lower | ||
1412 | * numbered block) and path point to the block we want to drop. | ||
1413 | */ | ||
1414 | memcpy(&state->altpath, &state->path, sizeof(state->path)); | ||
1415 | if (blkno < blk->blkno) { | ||
1416 | error = xfs_da_path_shift(state, &state->altpath, forward, | ||
1417 | 0, &retval); | ||
1418 | } else { | ||
1419 | error = xfs_da_path_shift(state, &state->path, forward, | ||
1420 | 0, &retval); | ||
1421 | } | ||
1422 | if (error) | ||
1423 | return error; | ||
1424 | if (retval) { | ||
1425 | *action = 0; | ||
1426 | } else { | ||
1427 | *action = 1; | ||
1428 | } | ||
1429 | return 0; | ||
1430 | } | ||
1431 | |||
1432 | /* | ||
1433 | * Remove a name from the leaf directory structure. | ||
1434 | * | ||
1435 | * Return 1 if leaf is less than 37% full, 0 if >= 37% full. | ||
1436 | * If two leaves are 37% full, when combined they will leave 25% free. | ||
1437 | */ | ||
1438 | int | ||
1439 | xfs_dir_leaf_remove(xfs_trans_t *trans, xfs_dabuf_t *bp, int index) | ||
1440 | { | ||
1441 | xfs_dir_leafblock_t *leaf; | ||
1442 | xfs_dir_leaf_hdr_t *hdr; | ||
1443 | xfs_dir_leaf_map_t *map; | ||
1444 | xfs_dir_leaf_entry_t *entry; | ||
1445 | xfs_dir_leaf_name_t *namest; | ||
1446 | int before, after, smallest, entsize; | ||
1447 | int tablesize, tmp, i; | ||
1448 | xfs_mount_t *mp; | ||
1449 | |||
1450 | leaf = bp->data; | ||
1451 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1452 | hdr = &leaf->hdr; | ||
1453 | mp = trans->t_mountp; | ||
1454 | ASSERT((INT_GET(hdr->count, ARCH_CONVERT) > 0) && (INT_GET(hdr->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); | ||
1455 | ASSERT((index >= 0) && (index < INT_GET(hdr->count, ARCH_CONVERT))); | ||
1456 | ASSERT(INT_GET(hdr->firstused, ARCH_CONVERT) >= ((INT_GET(hdr->count, ARCH_CONVERT)*sizeof(*entry))+sizeof(*hdr))); | ||
1457 | entry = &leaf->entries[index]; | ||
1458 | ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); | ||
1459 | ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
1460 | |||
1461 | /* | ||
1462 | * Scan through free region table: | ||
1463 | * check for adjacency of free'd entry with an existing one, | ||
1464 | * find smallest free region in case we need to replace it, | ||
1465 | * adjust any map that borders the entry table, | ||
1466 | */ | ||
1467 | tablesize = INT_GET(hdr->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) | ||
1468 | + (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1469 | map = &hdr->freemap[0]; | ||
1470 | tmp = INT_GET(map->size, ARCH_CONVERT); | ||
1471 | before = after = -1; | ||
1472 | smallest = XFS_DIR_LEAF_MAPSIZE - 1; | ||
1473 | entsize = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry); | ||
1474 | for (i = 0; i < XFS_DIR_LEAF_MAPSIZE; map++, i++) { | ||
1475 | ASSERT(INT_GET(map->base, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
1476 | ASSERT(INT_GET(map->size, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
1477 | if (INT_GET(map->base, ARCH_CONVERT) == tablesize) { | ||
1478 | INT_MOD(map->base, ARCH_CONVERT, -((uint)sizeof(xfs_dir_leaf_entry_t))); | ||
1479 | INT_MOD(map->size, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_entry_t)); | ||
1480 | } | ||
1481 | |||
1482 | if ((INT_GET(map->base, ARCH_CONVERT) + INT_GET(map->size, ARCH_CONVERT)) == INT_GET(entry->nameidx, ARCH_CONVERT)) { | ||
1483 | before = i; | ||
1484 | } else if (INT_GET(map->base, ARCH_CONVERT) == (INT_GET(entry->nameidx, ARCH_CONVERT) + entsize)) { | ||
1485 | after = i; | ||
1486 | } else if (INT_GET(map->size, ARCH_CONVERT) < tmp) { | ||
1487 | tmp = INT_GET(map->size, ARCH_CONVERT); | ||
1488 | smallest = i; | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | /* | ||
1493 | * Coalesce adjacent freemap regions, | ||
1494 | * or replace the smallest region. | ||
1495 | */ | ||
1496 | if ((before >= 0) || (after >= 0)) { | ||
1497 | if ((before >= 0) && (after >= 0)) { | ||
1498 | map = &hdr->freemap[before]; | ||
1499 | INT_MOD(map->size, ARCH_CONVERT, entsize); | ||
1500 | INT_MOD(map->size, ARCH_CONVERT, INT_GET(hdr->freemap[after].size, ARCH_CONVERT)); | ||
1501 | hdr->freemap[after].base = 0; | ||
1502 | hdr->freemap[after].size = 0; | ||
1503 | } else if (before >= 0) { | ||
1504 | map = &hdr->freemap[before]; | ||
1505 | INT_MOD(map->size, ARCH_CONVERT, entsize); | ||
1506 | } else { | ||
1507 | map = &hdr->freemap[after]; | ||
1508 | INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); | ||
1509 | INT_MOD(map->size, ARCH_CONVERT, entsize); | ||
1510 | } | ||
1511 | } else { | ||
1512 | /* | ||
1513 | * Replace smallest region (if it is smaller than free'd entry) | ||
1514 | */ | ||
1515 | map = &hdr->freemap[smallest]; | ||
1516 | if (INT_GET(map->size, ARCH_CONVERT) < entsize) { | ||
1517 | INT_COPY(map->base, entry->nameidx, ARCH_CONVERT); | ||
1518 | INT_SET(map->size, ARCH_CONVERT, entsize); | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | /* | ||
1523 | * Did we remove the first entry? | ||
1524 | */ | ||
1525 | if (INT_GET(entry->nameidx, ARCH_CONVERT) == INT_GET(hdr->firstused, ARCH_CONVERT)) | ||
1526 | smallest = 1; | ||
1527 | else | ||
1528 | smallest = 0; | ||
1529 | |||
1530 | /* | ||
1531 | * Compress the remaining entries and zero out the removed stuff. | ||
1532 | */ | ||
1533 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
1534 | memset((char *)namest, 0, entsize); | ||
1535 | xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, namest, entsize)); | ||
1536 | |||
1537 | INT_MOD(hdr->namebytes, ARCH_CONVERT, -(entry->namelen)); | ||
1538 | tmp = (INT_GET(hdr->count, ARCH_CONVERT) - index) * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1539 | memmove(entry, entry + 1, tmp); | ||
1540 | INT_MOD(hdr->count, ARCH_CONVERT, -1); | ||
1541 | xfs_da_log_buf(trans, bp, | ||
1542 | XFS_DA_LOGRANGE(leaf, entry, tmp + (uint)sizeof(*entry))); | ||
1543 | entry = &leaf->entries[INT_GET(hdr->count, ARCH_CONVERT)]; | ||
1544 | memset((char *)entry, 0, sizeof(xfs_dir_leaf_entry_t)); | ||
1545 | |||
1546 | /* | ||
1547 | * If we removed the first entry, re-find the first used byte | ||
1548 | * in the name area. Note that if the entry was the "firstused", | ||
1549 | * then we don't have a "hole" in our block resulting from | ||
1550 | * removing the name. | ||
1551 | */ | ||
1552 | if (smallest) { | ||
1553 | tmp = XFS_LBSIZE(mp); | ||
1554 | entry = &leaf->entries[0]; | ||
1555 | for (i = INT_GET(hdr->count, ARCH_CONVERT)-1; i >= 0; entry++, i--) { | ||
1556 | ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) >= INT_GET(hdr->firstused, ARCH_CONVERT)); | ||
1557 | ASSERT(INT_GET(entry->nameidx, ARCH_CONVERT) < XFS_LBSIZE(mp)); | ||
1558 | if (INT_GET(entry->nameidx, ARCH_CONVERT) < tmp) | ||
1559 | tmp = INT_GET(entry->nameidx, ARCH_CONVERT); | ||
1560 | } | ||
1561 | INT_SET(hdr->firstused, ARCH_CONVERT, tmp); | ||
1562 | if (!hdr->firstused) | ||
1563 | INT_SET(hdr->firstused, ARCH_CONVERT, tmp - 1); | ||
1564 | } else { | ||
1565 | hdr->holes = 1; /* mark as needing compaction */ | ||
1566 | } | ||
1567 | |||
1568 | xfs_da_log_buf(trans, bp, XFS_DA_LOGRANGE(leaf, hdr, sizeof(*hdr))); | ||
1569 | |||
1570 | /* | ||
1571 | * Check if leaf is less than 50% full, caller may want to | ||
1572 | * "join" the leaf with a sibling if so. | ||
1573 | */ | ||
1574 | tmp = (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1575 | tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1576 | tmp += INT_GET(leaf->hdr.count, ARCH_CONVERT) * ((uint)sizeof(xfs_dir_leaf_name_t) - 1); | ||
1577 | tmp += INT_GET(leaf->hdr.namebytes, ARCH_CONVERT); | ||
1578 | if (tmp < mp->m_dir_magicpct) | ||
1579 | return 1; /* leaf is < 37% full */ | ||
1580 | return 0; | ||
1581 | } | ||
1582 | |||
1583 | /* | ||
1584 | * Move all the directory entries from drop_leaf into save_leaf. | ||
1585 | */ | ||
1586 | void | ||
1587 | xfs_dir_leaf_unbalance(xfs_da_state_t *state, xfs_da_state_blk_t *drop_blk, | ||
1588 | xfs_da_state_blk_t *save_blk) | ||
1589 | { | ||
1590 | xfs_dir_leafblock_t *drop_leaf, *save_leaf, *tmp_leaf; | ||
1591 | xfs_dir_leaf_hdr_t *drop_hdr, *save_hdr, *tmp_hdr; | ||
1592 | xfs_mount_t *mp; | ||
1593 | char *tmpbuffer; | ||
1594 | |||
1595 | /* | ||
1596 | * Set up environment. | ||
1597 | */ | ||
1598 | mp = state->mp; | ||
1599 | ASSERT(drop_blk->magic == XFS_DIR_LEAF_MAGIC); | ||
1600 | ASSERT(save_blk->magic == XFS_DIR_LEAF_MAGIC); | ||
1601 | drop_leaf = drop_blk->bp->data; | ||
1602 | save_leaf = save_blk->bp->data; | ||
1603 | ASSERT(be16_to_cpu(drop_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1604 | ASSERT(be16_to_cpu(save_leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1605 | drop_hdr = &drop_leaf->hdr; | ||
1606 | save_hdr = &save_leaf->hdr; | ||
1607 | |||
1608 | /* | ||
1609 | * Save last hashval from dying block for later Btree fixup. | ||
1610 | */ | ||
1611 | drop_blk->hashval = INT_GET(drop_leaf->entries[ drop_leaf->hdr.count-1 ].hashval, ARCH_CONVERT); | ||
1612 | |||
1613 | /* | ||
1614 | * Check if we need a temp buffer, or can we do it in place. | ||
1615 | * Note that we don't check "leaf" for holes because we will | ||
1616 | * always be dropping it, toosmall() decided that for us already. | ||
1617 | */ | ||
1618 | if (save_hdr->holes == 0) { | ||
1619 | /* | ||
1620 | * dest leaf has no holes, so we add there. May need | ||
1621 | * to make some room in the entry array. | ||
1622 | */ | ||
1623 | if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { | ||
1624 | xfs_dir_leaf_moveents(drop_leaf, 0, save_leaf, 0, | ||
1625 | (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); | ||
1626 | } else { | ||
1627 | xfs_dir_leaf_moveents(drop_leaf, 0, | ||
1628 | save_leaf, INT_GET(save_hdr->count, ARCH_CONVERT), | ||
1629 | (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); | ||
1630 | } | ||
1631 | } else { | ||
1632 | /* | ||
1633 | * Destination has holes, so we make a temporary copy | ||
1634 | * of the leaf and add them both to that. | ||
1635 | */ | ||
1636 | tmpbuffer = kmem_alloc(state->blocksize, KM_SLEEP); | ||
1637 | ASSERT(tmpbuffer != NULL); | ||
1638 | memset(tmpbuffer, 0, state->blocksize); | ||
1639 | tmp_leaf = (xfs_dir_leafblock_t *)tmpbuffer; | ||
1640 | tmp_hdr = &tmp_leaf->hdr; | ||
1641 | tmp_hdr->info = save_hdr->info; /* struct copy */ | ||
1642 | tmp_hdr->count = 0; | ||
1643 | INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize); | ||
1644 | if (!tmp_hdr->firstused) | ||
1645 | INT_SET(tmp_hdr->firstused, ARCH_CONVERT, state->blocksize - 1); | ||
1646 | tmp_hdr->namebytes = 0; | ||
1647 | if (xfs_dir_leaf_order(save_blk->bp, drop_blk->bp)) { | ||
1648 | xfs_dir_leaf_moveents(drop_leaf, 0, tmp_leaf, 0, | ||
1649 | (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); | ||
1650 | xfs_dir_leaf_moveents(save_leaf, 0, | ||
1651 | tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), | ||
1652 | (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); | ||
1653 | } else { | ||
1654 | xfs_dir_leaf_moveents(save_leaf, 0, tmp_leaf, 0, | ||
1655 | (int)INT_GET(save_hdr->count, ARCH_CONVERT), mp); | ||
1656 | xfs_dir_leaf_moveents(drop_leaf, 0, | ||
1657 | tmp_leaf, INT_GET(tmp_leaf->hdr.count, ARCH_CONVERT), | ||
1658 | (int)INT_GET(drop_hdr->count, ARCH_CONVERT), mp); | ||
1659 | } | ||
1660 | memcpy(save_leaf, tmp_leaf, state->blocksize); | ||
1661 | kmem_free(tmpbuffer, state->blocksize); | ||
1662 | } | ||
1663 | |||
1664 | xfs_da_log_buf(state->args->trans, save_blk->bp, 0, | ||
1665 | state->blocksize - 1); | ||
1666 | |||
1667 | /* | ||
1668 | * Copy out last hashval in each block for B-tree code. | ||
1669 | */ | ||
1670 | save_blk->hashval = INT_GET(save_leaf->entries[ INT_GET(save_leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT); | ||
1671 | } | ||
1672 | |||
1673 | /*======================================================================== | ||
1674 | * Routines used for finding things in the Btree. | ||
1675 | *========================================================================*/ | ||
1676 | |||
1677 | /* | ||
1678 | * Look up a name in a leaf directory structure. | ||
1679 | * This is the internal routine, it uses the caller's buffer. | ||
1680 | * | ||
1681 | * Note that duplicate keys are allowed, but only check within the | ||
1682 | * current leaf node. The Btree code must check in adjacent leaf nodes. | ||
1683 | * | ||
1684 | * Return in *index the index into the entry[] array of either the found | ||
1685 | * entry, or where the entry should have been (insert before that entry). | ||
1686 | * | ||
1687 | * Don't change the args->inumber unless we find the filename. | ||
1688 | */ | ||
1689 | int | ||
1690 | xfs_dir_leaf_lookup_int(xfs_dabuf_t *bp, xfs_da_args_t *args, int *index) | ||
1691 | { | ||
1692 | xfs_dir_leafblock_t *leaf; | ||
1693 | xfs_dir_leaf_entry_t *entry; | ||
1694 | xfs_dir_leaf_name_t *namest; | ||
1695 | int probe, span; | ||
1696 | xfs_dahash_t hashval; | ||
1697 | |||
1698 | leaf = bp->data; | ||
1699 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1700 | ASSERT(INT_GET(leaf->hdr.count, ARCH_CONVERT) < (XFS_LBSIZE(args->dp->i_mount)/8)); | ||
1701 | |||
1702 | /* | ||
1703 | * Binary search. (note: small blocks will skip this loop) | ||
1704 | */ | ||
1705 | hashval = args->hashval; | ||
1706 | probe = span = INT_GET(leaf->hdr.count, ARCH_CONVERT) / 2; | ||
1707 | for (entry = &leaf->entries[probe]; span > 4; | ||
1708 | entry = &leaf->entries[probe]) { | ||
1709 | span /= 2; | ||
1710 | if (INT_GET(entry->hashval, ARCH_CONVERT) < hashval) | ||
1711 | probe += span; | ||
1712 | else if (INT_GET(entry->hashval, ARCH_CONVERT) > hashval) | ||
1713 | probe -= span; | ||
1714 | else | ||
1715 | break; | ||
1716 | } | ||
1717 | ASSERT((probe >= 0) && \ | ||
1718 | ((!leaf->hdr.count) || (probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)))); | ||
1719 | ASSERT((span <= 4) || (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)); | ||
1720 | |||
1721 | /* | ||
1722 | * Since we may have duplicate hashval's, find the first matching | ||
1723 | * hashval in the leaf. | ||
1724 | */ | ||
1725 | while ((probe > 0) && (INT_GET(entry->hashval, ARCH_CONVERT) >= hashval)) { | ||
1726 | entry--; | ||
1727 | probe--; | ||
1728 | } | ||
1729 | while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) < hashval)) { | ||
1730 | entry++; | ||
1731 | probe++; | ||
1732 | } | ||
1733 | if ((probe == INT_GET(leaf->hdr.count, ARCH_CONVERT)) || (INT_GET(entry->hashval, ARCH_CONVERT) != hashval)) { | ||
1734 | *index = probe; | ||
1735 | ASSERT(args->oknoent); | ||
1736 | return XFS_ERROR(ENOENT); | ||
1737 | } | ||
1738 | |||
1739 | /* | ||
1740 | * Duplicate keys may be present, so search all of them for a match. | ||
1741 | */ | ||
1742 | while ((probe < INT_GET(leaf->hdr.count, ARCH_CONVERT)) && (INT_GET(entry->hashval, ARCH_CONVERT) == hashval)) { | ||
1743 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
1744 | if (entry->namelen == args->namelen && | ||
1745 | namest->name[0] == args->name[0] && | ||
1746 | memcmp(args->name, namest->name, args->namelen) == 0) { | ||
1747 | XFS_DIR_SF_GET_DIRINO(&namest->inumber, &args->inumber); | ||
1748 | *index = probe; | ||
1749 | return XFS_ERROR(EEXIST); | ||
1750 | } | ||
1751 | entry++; | ||
1752 | probe++; | ||
1753 | } | ||
1754 | *index = probe; | ||
1755 | ASSERT(probe == INT_GET(leaf->hdr.count, ARCH_CONVERT) || args->oknoent); | ||
1756 | return XFS_ERROR(ENOENT); | ||
1757 | } | ||
1758 | |||
1759 | /*======================================================================== | ||
1760 | * Utility routines. | ||
1761 | *========================================================================*/ | ||
1762 | |||
1763 | /* | ||
1764 | * Move the indicated entries from one leaf to another. | ||
1765 | * NOTE: this routine modifies both source and destination leaves. | ||
1766 | */ | ||
1767 | /* ARGSUSED */ | ||
1768 | STATIC void | ||
1769 | xfs_dir_leaf_moveents(xfs_dir_leafblock_t *leaf_s, int start_s, | ||
1770 | xfs_dir_leafblock_t *leaf_d, int start_d, | ||
1771 | int count, xfs_mount_t *mp) | ||
1772 | { | ||
1773 | xfs_dir_leaf_hdr_t *hdr_s, *hdr_d; | ||
1774 | xfs_dir_leaf_entry_t *entry_s, *entry_d; | ||
1775 | int tmp, i; | ||
1776 | |||
1777 | /* | ||
1778 | * Check for nothing to do. | ||
1779 | */ | ||
1780 | if (count == 0) | ||
1781 | return; | ||
1782 | |||
1783 | /* | ||
1784 | * Set up environment. | ||
1785 | */ | ||
1786 | ASSERT(be16_to_cpu(leaf_s->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1787 | ASSERT(be16_to_cpu(leaf_d->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1788 | hdr_s = &leaf_s->hdr; | ||
1789 | hdr_d = &leaf_d->hdr; | ||
1790 | ASSERT((INT_GET(hdr_s->count, ARCH_CONVERT) > 0) && (INT_GET(hdr_s->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8))); | ||
1791 | ASSERT(INT_GET(hdr_s->firstused, ARCH_CONVERT) >= | ||
1792 | ((INT_GET(hdr_s->count, ARCH_CONVERT)*sizeof(*entry_s))+sizeof(*hdr_s))); | ||
1793 | ASSERT(INT_GET(hdr_d->count, ARCH_CONVERT) < (XFS_LBSIZE(mp)/8)); | ||
1794 | ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= | ||
1795 | ((INT_GET(hdr_d->count, ARCH_CONVERT)*sizeof(*entry_d))+sizeof(*hdr_d))); | ||
1796 | |||
1797 | ASSERT(start_s < INT_GET(hdr_s->count, ARCH_CONVERT)); | ||
1798 | ASSERT(start_d <= INT_GET(hdr_d->count, ARCH_CONVERT)); | ||
1799 | ASSERT(count <= INT_GET(hdr_s->count, ARCH_CONVERT)); | ||
1800 | |||
1801 | /* | ||
1802 | * Move the entries in the destination leaf up to make a hole? | ||
1803 | */ | ||
1804 | if (start_d < INT_GET(hdr_d->count, ARCH_CONVERT)) { | ||
1805 | tmp = INT_GET(hdr_d->count, ARCH_CONVERT) - start_d; | ||
1806 | tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1807 | entry_s = &leaf_d->entries[start_d]; | ||
1808 | entry_d = &leaf_d->entries[start_d + count]; | ||
1809 | memcpy(entry_d, entry_s, tmp); | ||
1810 | } | ||
1811 | |||
1812 | /* | ||
1813 | * Copy all entry's in the same (sorted) order, | ||
1814 | * but allocate filenames packed and in sequence. | ||
1815 | */ | ||
1816 | entry_s = &leaf_s->entries[start_s]; | ||
1817 | entry_d = &leaf_d->entries[start_d]; | ||
1818 | for (i = 0; i < count; entry_s++, entry_d++, i++) { | ||
1819 | ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) >= INT_GET(hdr_s->firstused, ARCH_CONVERT)); | ||
1820 | tmp = XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry_s); | ||
1821 | INT_MOD(hdr_d->firstused, ARCH_CONVERT, -(tmp)); | ||
1822 | entry_d->hashval = entry_s->hashval; /* INT_: direct copy */ | ||
1823 | INT_COPY(entry_d->nameidx, hdr_d->firstused, ARCH_CONVERT); | ||
1824 | entry_d->namelen = entry_s->namelen; | ||
1825 | ASSERT(INT_GET(entry_d->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); | ||
1826 | memcpy(XFS_DIR_LEAF_NAMESTRUCT(leaf_d, INT_GET(entry_d->nameidx, ARCH_CONVERT)), | ||
1827 | XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), tmp); | ||
1828 | ASSERT(INT_GET(entry_s->nameidx, ARCH_CONVERT) + tmp <= XFS_LBSIZE(mp)); | ||
1829 | memset((char *)XFS_DIR_LEAF_NAMESTRUCT(leaf_s, INT_GET(entry_s->nameidx, ARCH_CONVERT)), | ||
1830 | 0, tmp); | ||
1831 | INT_MOD(hdr_s->namebytes, ARCH_CONVERT, -(entry_d->namelen)); | ||
1832 | INT_MOD(hdr_d->namebytes, ARCH_CONVERT, entry_d->namelen); | ||
1833 | INT_MOD(hdr_s->count, ARCH_CONVERT, -1); | ||
1834 | INT_MOD(hdr_d->count, ARCH_CONVERT, +1); | ||
1835 | tmp = INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t) | ||
1836 | + (uint)sizeof(xfs_dir_leaf_hdr_t); | ||
1837 | ASSERT(INT_GET(hdr_d->firstused, ARCH_CONVERT) >= tmp); | ||
1838 | |||
1839 | } | ||
1840 | |||
1841 | /* | ||
1842 | * Zero out the entries we just copied. | ||
1843 | */ | ||
1844 | if (start_s == INT_GET(hdr_s->count, ARCH_CONVERT)) { | ||
1845 | tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1846 | entry_s = &leaf_s->entries[start_s]; | ||
1847 | ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); | ||
1848 | memset((char *)entry_s, 0, tmp); | ||
1849 | } else { | ||
1850 | /* | ||
1851 | * Move the remaining entries down to fill the hole, | ||
1852 | * then zero the entries at the top. | ||
1853 | */ | ||
1854 | tmp = INT_GET(hdr_s->count, ARCH_CONVERT) - count; | ||
1855 | tmp *= (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1856 | entry_s = &leaf_s->entries[start_s + count]; | ||
1857 | entry_d = &leaf_s->entries[start_s]; | ||
1858 | memcpy(entry_d, entry_s, tmp); | ||
1859 | |||
1860 | tmp = count * (uint)sizeof(xfs_dir_leaf_entry_t); | ||
1861 | entry_s = &leaf_s->entries[INT_GET(hdr_s->count, ARCH_CONVERT)]; | ||
1862 | ASSERT((char *)entry_s + tmp <= (char *)leaf_s + XFS_LBSIZE(mp)); | ||
1863 | memset((char *)entry_s, 0, tmp); | ||
1864 | } | ||
1865 | |||
1866 | /* | ||
1867 | * Fill in the freemap information | ||
1868 | */ | ||
1869 | INT_SET(hdr_d->freemap[0].base, ARCH_CONVERT, (uint)sizeof(xfs_dir_leaf_hdr_t)); | ||
1870 | INT_MOD(hdr_d->freemap[0].base, ARCH_CONVERT, INT_GET(hdr_d->count, ARCH_CONVERT) * (uint)sizeof(xfs_dir_leaf_entry_t)); | ||
1871 | INT_SET(hdr_d->freemap[0].size, ARCH_CONVERT, INT_GET(hdr_d->firstused, ARCH_CONVERT) - INT_GET(hdr_d->freemap[0].base, ARCH_CONVERT)); | ||
1872 | INT_SET(hdr_d->freemap[1].base, ARCH_CONVERT, (hdr_d->freemap[2].base = 0)); | ||
1873 | INT_SET(hdr_d->freemap[1].size, ARCH_CONVERT, (hdr_d->freemap[2].size = 0)); | ||
1874 | hdr_s->holes = 1; /* leaf may not be compact */ | ||
1875 | } | ||
1876 | |||
1877 | /* | ||
1878 | * Compare two leaf blocks "order". | ||
1879 | */ | ||
1880 | int | ||
1881 | xfs_dir_leaf_order(xfs_dabuf_t *leaf1_bp, xfs_dabuf_t *leaf2_bp) | ||
1882 | { | ||
1883 | xfs_dir_leafblock_t *leaf1, *leaf2; | ||
1884 | |||
1885 | leaf1 = leaf1_bp->data; | ||
1886 | leaf2 = leaf2_bp->data; | ||
1887 | ASSERT((be16_to_cpu(leaf1->hdr.info.magic) == XFS_DIR_LEAF_MAGIC) && | ||
1888 | (be16_to_cpu(leaf2->hdr.info.magic) == XFS_DIR_LEAF_MAGIC)); | ||
1889 | if ((INT_GET(leaf1->hdr.count, ARCH_CONVERT) > 0) && (INT_GET(leaf2->hdr.count, ARCH_CONVERT) > 0) && | ||
1890 | ((INT_GET(leaf2->entries[ 0 ].hashval, ARCH_CONVERT) < | ||
1891 | INT_GET(leaf1->entries[ 0 ].hashval, ARCH_CONVERT)) || | ||
1892 | (INT_GET(leaf2->entries[ INT_GET(leaf2->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT) < | ||
1893 | INT_GET(leaf1->entries[ INT_GET(leaf1->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)))) { | ||
1894 | return 1; | ||
1895 | } | ||
1896 | return 0; | ||
1897 | } | ||
1898 | |||
1899 | /* | ||
1900 | * Pick up the last hashvalue from a leaf block. | ||
1901 | */ | ||
1902 | xfs_dahash_t | ||
1903 | xfs_dir_leaf_lasthash(xfs_dabuf_t *bp, int *count) | ||
1904 | { | ||
1905 | xfs_dir_leafblock_t *leaf; | ||
1906 | |||
1907 | leaf = bp->data; | ||
1908 | ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR_LEAF_MAGIC); | ||
1909 | if (count) | ||
1910 | *count = INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
1911 | if (!leaf->hdr.count) | ||
1912 | return(0); | ||
1913 | return(INT_GET(leaf->entries[ INT_GET(leaf->hdr.count, ARCH_CONVERT)-1 ].hashval, ARCH_CONVERT)); | ||
1914 | } | ||
1915 | |||
1916 | /* | ||
1917 | * Copy out directory entries for getdents(), for leaf directories. | ||
1918 | */ | ||
1919 | int | ||
1920 | xfs_dir_leaf_getdents_int( | ||
1921 | xfs_dabuf_t *bp, | ||
1922 | xfs_inode_t *dp, | ||
1923 | xfs_dablk_t bno, | ||
1924 | uio_t *uio, | ||
1925 | int *eobp, | ||
1926 | xfs_dirent_t *dbp, | ||
1927 | xfs_dir_put_t put, | ||
1928 | xfs_daddr_t nextda) | ||
1929 | { | ||
1930 | xfs_dir_leafblock_t *leaf; | ||
1931 | xfs_dir_leaf_entry_t *entry; | ||
1932 | xfs_dir_leaf_name_t *namest; | ||
1933 | int entno, want_entno, i, nextentno; | ||
1934 | xfs_mount_t *mp; | ||
1935 | xfs_dahash_t cookhash; | ||
1936 | xfs_dahash_t nexthash = 0; | ||
1937 | #if (BITS_PER_LONG == 32) | ||
1938 | xfs_dahash_t lasthash = XFS_DA_MAXHASH; | ||
1939 | #endif | ||
1940 | xfs_dir_put_args_t p; | ||
1941 | |||
1942 | mp = dp->i_mount; | ||
1943 | leaf = bp->data; | ||
1944 | if (be16_to_cpu(leaf->hdr.info.magic) != XFS_DIR_LEAF_MAGIC) { | ||
1945 | *eobp = 1; | ||
1946 | return XFS_ERROR(ENOENT); /* XXX wrong code */ | ||
1947 | } | ||
1948 | |||
1949 | want_entno = XFS_DA_COOKIE_ENTRY(mp, uio->uio_offset); | ||
1950 | |||
1951 | cookhash = XFS_DA_COOKIE_HASH(mp, uio->uio_offset); | ||
1952 | |||
1953 | xfs_dir_trace_g_dul("leaf: start", dp, uio, leaf); | ||
1954 | |||
1955 | /* | ||
1956 | * Re-find our place. | ||
1957 | */ | ||
1958 | for (i = entno = 0, entry = &leaf->entries[0]; | ||
1959 | i < INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
1960 | entry++, i++) { | ||
1961 | |||
1962 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, | ||
1963 | INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
1964 | |||
1965 | if (unlikely( | ||
1966 | ((char *)namest < (char *)leaf) || | ||
1967 | ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { | ||
1968 | XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(1)", | ||
1969 | XFS_ERRLEVEL_LOW, mp, leaf); | ||
1970 | xfs_dir_trace_g_du("leaf: corrupted", dp, uio); | ||
1971 | return XFS_ERROR(EFSCORRUPTED); | ||
1972 | } | ||
1973 | if (INT_GET(entry->hashval, ARCH_CONVERT) >= cookhash) { | ||
1974 | if ( entno < want_entno | ||
1975 | && INT_GET(entry->hashval, ARCH_CONVERT) | ||
1976 | == cookhash) { | ||
1977 | /* | ||
1978 | * Trying to get to a particular offset in a | ||
1979 | * run of equal-hashval entries. | ||
1980 | */ | ||
1981 | entno++; | ||
1982 | } else if ( want_entno > 0 | ||
1983 | && entno == want_entno | ||
1984 | && INT_GET(entry->hashval, ARCH_CONVERT) | ||
1985 | == cookhash) { | ||
1986 | break; | ||
1987 | } else { | ||
1988 | entno = 0; | ||
1989 | break; | ||
1990 | } | ||
1991 | } | ||
1992 | } | ||
1993 | |||
1994 | if (i == INT_GET(leaf->hdr.count, ARCH_CONVERT)) { | ||
1995 | xfs_dir_trace_g_du("leaf: hash not found", dp, uio); | ||
1996 | if (!leaf->hdr.info.forw) | ||
1997 | uio->uio_offset = | ||
1998 | XFS_DA_MAKE_COOKIE(mp, 0, 0, XFS_DA_MAXHASH); | ||
1999 | /* | ||
2000 | * Don't set uio_offset if there's another block: | ||
2001 | * the node code will be setting uio_offset anyway. | ||
2002 | */ | ||
2003 | *eobp = 0; | ||
2004 | return 0; | ||
2005 | } | ||
2006 | xfs_dir_trace_g_due("leaf: hash found", dp, uio, entry); | ||
2007 | |||
2008 | p.dbp = dbp; | ||
2009 | p.put = put; | ||
2010 | p.uio = uio; | ||
2011 | |||
2012 | /* | ||
2013 | * We're synchronized, start copying entries out to the user. | ||
2014 | */ | ||
2015 | for (; entno >= 0 && i < INT_GET(leaf->hdr.count, ARCH_CONVERT); | ||
2016 | entry++, i++, (entno = nextentno)) { | ||
2017 | int lastresid=0, retval; | ||
2018 | xfs_dircook_t lastoffset; | ||
2019 | xfs_dahash_t thishash; | ||
2020 | |||
2021 | /* | ||
2022 | * Check for a damaged directory leaf block and pick up | ||
2023 | * the inode number from this entry. | ||
2024 | */ | ||
2025 | namest = XFS_DIR_LEAF_NAMESTRUCT(leaf, | ||
2026 | INT_GET(entry->nameidx, ARCH_CONVERT)); | ||
2027 | |||
2028 | if (unlikely( | ||
2029 | ((char *)namest < (char *)leaf) || | ||
2030 | ((char *)namest >= (char *)leaf + XFS_LBSIZE(mp)))) { | ||
2031 | XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(2)", | ||
2032 | XFS_ERRLEVEL_LOW, mp, leaf); | ||
2033 | xfs_dir_trace_g_du("leaf: corrupted", dp, uio); | ||
2034 | return XFS_ERROR(EFSCORRUPTED); | ||
2035 | } | ||
2036 | |||
2037 | xfs_dir_trace_g_duc("leaf: middle cookie ", | ||
2038 | dp, uio, p.cook.o); | ||
2039 | |||
2040 | if (i < (INT_GET(leaf->hdr.count, ARCH_CONVERT) - 1)) { | ||
2041 | nexthash = INT_GET(entry[1].hashval, ARCH_CONVERT); | ||
2042 | |||
2043 | if (nexthash == INT_GET(entry->hashval, ARCH_CONVERT)) | ||
2044 | nextentno = entno + 1; | ||
2045 | else | ||
2046 | nextentno = 0; | ||
2047 | XFS_PUT_COOKIE(p.cook, mp, bno, nextentno, nexthash); | ||
2048 | xfs_dir_trace_g_duc("leaf: middle cookie ", | ||
2049 | dp, uio, p.cook.o); | ||
2050 | |||
2051 | } else if ((thishash = be32_to_cpu(leaf->hdr.info.forw))) { | ||
2052 | xfs_dabuf_t *bp2; | ||
2053 | xfs_dir_leafblock_t *leaf2; | ||
2054 | |||
2055 | ASSERT(nextda != -1); | ||
2056 | |||
2057 | retval = xfs_da_read_buf(dp->i_transp, dp, thishash, | ||
2058 | nextda, &bp2, XFS_DATA_FORK); | ||
2059 | if (retval) | ||
2060 | return retval; | ||
2061 | |||
2062 | ASSERT(bp2 != NULL); | ||
2063 | |||
2064 | leaf2 = bp2->data; | ||
2065 | |||
2066 | if (unlikely( | ||
2067 | (be16_to_cpu(leaf2->hdr.info.magic) | ||
2068 | != XFS_DIR_LEAF_MAGIC) | ||
2069 | || (be32_to_cpu(leaf2->hdr.info.back) | ||
2070 | != bno))) { /* GROT */ | ||
2071 | XFS_CORRUPTION_ERROR("xfs_dir_leaf_getdents_int(3)", | ||
2072 | XFS_ERRLEVEL_LOW, mp, | ||
2073 | leaf2); | ||
2074 | xfs_da_brelse(dp->i_transp, bp2); | ||
2075 | |||
2076 | return XFS_ERROR(EFSCORRUPTED); | ||
2077 | } | ||
2078 | |||
2079 | nexthash = INT_GET(leaf2->entries[0].hashval, | ||
2080 | ARCH_CONVERT); | ||
2081 | nextentno = -1; | ||
2082 | XFS_PUT_COOKIE(p.cook, mp, thishash, 0, nexthash); | ||
2083 | xfs_da_brelse(dp->i_transp, bp2); | ||
2084 | xfs_dir_trace_g_duc("leaf: next blk cookie", | ||
2085 | dp, uio, p.cook.o); | ||
2086 | } else { | ||
2087 | nextentno = -1; | ||
2088 | XFS_PUT_COOKIE(p.cook, mp, 0, 0, XFS_DA_MAXHASH); | ||
2089 | } | ||
2090 | |||
2091 | /* | ||
2092 | * Save off the cookie so we can fall back should the | ||
2093 | * 'put' into the outgoing buffer fails. To handle a run | ||
2094 | * of equal-hashvals, the off_t structure on 64bit | ||
2095 | * builds has entno built into the cookie to ID the | ||
2096 | * entry. On 32bit builds, we only have space for the | ||
2097 | * hashval so we can't ID specific entries within a group | ||
2098 | * of same hashval entries. For this, lastoffset is set | ||
2099 | * to the first in the run of equal hashvals so we don't | ||
2100 | * include any entries unless we can include all entries | ||
2101 | * that share the same hashval. Hopefully the buffer | ||
2102 | * provided is big enough to handle it (see pv763517). | ||
2103 | */ | ||
2104 | #if (BITS_PER_LONG == 32) | ||
2105 | if ((thishash = INT_GET(entry->hashval, ARCH_CONVERT)) | ||
2106 | != lasthash) { | ||
2107 | XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); | ||
2108 | lastresid = uio->uio_resid; | ||
2109 | lasthash = thishash; | ||
2110 | } else { | ||
2111 | xfs_dir_trace_g_duc("leaf: DUP COOKIES, skipped", | ||
2112 | dp, uio, p.cook.o); | ||
2113 | } | ||
2114 | #else | ||
2115 | thishash = INT_GET(entry->hashval, ARCH_CONVERT); | ||
2116 | XFS_PUT_COOKIE(lastoffset, mp, bno, entno, thishash); | ||
2117 | lastresid = uio->uio_resid; | ||
2118 | #endif /* BITS_PER_LONG == 32 */ | ||
2119 | |||
2120 | /* | ||
2121 | * Put the current entry into the outgoing buffer. If we fail | ||
2122 | * then restore the UIO to the first entry in the current | ||
2123 | * run of equal-hashval entries (probably one 1 entry long). | ||
2124 | */ | ||
2125 | p.ino = XFS_GET_DIR_INO8(namest->inumber); | ||
2126 | #if XFS_BIG_INUMS | ||
2127 | p.ino += mp->m_inoadd; | ||
2128 | #endif | ||
2129 | p.name = (char *)namest->name; | ||
2130 | p.namelen = entry->namelen; | ||
2131 | |||
2132 | retval = p.put(&p); | ||
2133 | |||
2134 | if (!p.done) { | ||
2135 | uio->uio_offset = lastoffset.o; | ||
2136 | uio->uio_resid = lastresid; | ||
2137 | |||
2138 | *eobp = 1; | ||
2139 | |||
2140 | xfs_dir_trace_g_du("leaf: E-O-B", dp, uio); | ||
2141 | |||
2142 | return retval; | ||
2143 | } | ||
2144 | } | ||
2145 | |||
2146 | uio->uio_offset = p.cook.o; | ||
2147 | |||
2148 | *eobp = 0; | ||
2149 | |||
2150 | xfs_dir_trace_g_du("leaf: E-O-F", dp, uio); | ||
2151 | |||
2152 | return 0; | ||
2153 | } | ||
2154 | |||
2155 | /* | ||
2156 | * Format a dirent64 structure and copy it out the the user's buffer. | ||
2157 | */ | ||
2158 | int | ||
2159 | xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa) | ||
2160 | { | ||
2161 | iovec_t *iovp; | ||
2162 | int reclen, namelen; | ||
2163 | xfs_dirent_t *idbp; | ||
2164 | uio_t *uio; | ||
2165 | |||
2166 | namelen = pa->namelen; | ||
2167 | reclen = DIRENTSIZE(namelen); | ||
2168 | uio = pa->uio; | ||
2169 | if (reclen > uio->uio_resid) { | ||
2170 | pa->done = 0; | ||
2171 | return 0; | ||
2172 | } | ||
2173 | iovp = uio->uio_iov; | ||
2174 | idbp = (xfs_dirent_t *)iovp->iov_base; | ||
2175 | iovp->iov_base = (char *)idbp + reclen; | ||
2176 | iovp->iov_len -= reclen; | ||
2177 | uio->uio_resid -= reclen; | ||
2178 | idbp->d_reclen = reclen; | ||
2179 | idbp->d_ino = pa->ino; | ||
2180 | idbp->d_off = pa->cook.o; | ||
2181 | idbp->d_name[namelen] = '\0'; | ||
2182 | pa->done = 1; | ||
2183 | memcpy(idbp->d_name, pa->name, namelen); | ||
2184 | return 0; | ||
2185 | } | ||
2186 | |||
2187 | /* | ||
2188 | * Format a dirent64 structure and copy it out the the user's buffer. | ||
2189 | */ | ||
2190 | int | ||
2191 | xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa) | ||
2192 | { | ||
2193 | int retval, reclen, namelen; | ||
2194 | xfs_dirent_t *idbp; | ||
2195 | uio_t *uio; | ||
2196 | |||
2197 | namelen = pa->namelen; | ||
2198 | reclen = DIRENTSIZE(namelen); | ||
2199 | uio = pa->uio; | ||
2200 | if (reclen > uio->uio_resid) { | ||
2201 | pa->done = 0; | ||
2202 | return 0; | ||
2203 | } | ||
2204 | idbp = pa->dbp; | ||
2205 | idbp->d_reclen = reclen; | ||
2206 | idbp->d_ino = pa->ino; | ||
2207 | idbp->d_off = pa->cook.o; | ||
2208 | idbp->d_name[namelen] = '\0'; | ||
2209 | memcpy(idbp->d_name, pa->name, namelen); | ||
2210 | retval = uio_read((caddr_t)idbp, reclen, uio); | ||
2211 | pa->done = (retval == 0); | ||
2212 | return retval; | ||
2213 | } | ||
diff --git a/fs/xfs/xfs_dir_leaf.h b/fs/xfs/xfs_dir_leaf.h deleted file mode 100644 index eb8cd9a4667f..000000000000 --- a/fs/xfs/xfs_dir_leaf.h +++ /dev/null | |||
@@ -1,231 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2001,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DIR_LEAF_H__ | ||
19 | #define __XFS_DIR_LEAF_H__ | ||
20 | |||
21 | /* | ||
22 | * Directory layout, internal structure, access macros, etc. | ||
23 | * | ||
24 | * Large directories are structured around Btrees where all the data | ||
25 | * elements are in the leaf nodes. Filenames are hashed into an int, | ||
26 | * then that int is used as the index into the Btree. Since the hashval | ||
27 | * of a filename may not be unique, we may have duplicate keys. The | ||
28 | * internal links in the Btree are logical block offsets into the file. | ||
29 | */ | ||
30 | |||
31 | struct uio; | ||
32 | struct xfs_bmap_free; | ||
33 | struct xfs_dabuf; | ||
34 | struct xfs_da_args; | ||
35 | struct xfs_da_state; | ||
36 | struct xfs_da_state_blk; | ||
37 | struct xfs_dir_put_args; | ||
38 | struct xfs_inode; | ||
39 | struct xfs_mount; | ||
40 | struct xfs_trans; | ||
41 | |||
42 | /*======================================================================== | ||
43 | * Directory Structure when equal to XFS_LBSIZE(mp) bytes. | ||
44 | *========================================================================*/ | ||
45 | |||
46 | /* | ||
47 | * This is the structure of the leaf nodes in the Btree. | ||
48 | * | ||
49 | * Struct leaf_entry's are packed from the top. Names grow from the bottom | ||
50 | * but are not packed. The freemap contains run-length-encoded entries | ||
51 | * for the free bytes after the leaf_entry's, but only the N largest such, | ||
52 | * smaller runs are dropped. When the freemap doesn't show enough space | ||
53 | * for an allocation, we compact the namelist area and try again. If we | ||
54 | * still don't have enough space, then we have to split the block. | ||
55 | * | ||
56 | * Since we have duplicate hash keys, for each key that matches, compare | ||
57 | * the actual string. The root and intermediate node search always takes | ||
58 | * the first-in-the-block key match found, so we should only have to work | ||
59 | * "forw"ard. If none matches, continue with the "forw"ard leaf nodes | ||
60 | * until the hash key changes or the filename is found. | ||
61 | * | ||
62 | * The parent directory and the self-pointer are explicitly represented | ||
63 | * (ie: there are entries for "." and ".."). | ||
64 | * | ||
65 | * Note that the count being a __uint16_t limits us to something like a | ||
66 | * blocksize of 1.3MB in the face of worst case (short) filenames. | ||
67 | */ | ||
68 | #define XFS_DIR_LEAF_MAPSIZE 3 /* how many freespace slots */ | ||
69 | |||
70 | typedef struct xfs_dir_leaf_map { /* RLE map of free bytes */ | ||
71 | __uint16_t base; /* base of free region */ | ||
72 | __uint16_t size; /* run length of free region */ | ||
73 | } xfs_dir_leaf_map_t; | ||
74 | |||
75 | typedef struct xfs_dir_leaf_hdr { /* constant-structure header block */ | ||
76 | xfs_da_blkinfo_t info; /* block type, links, etc. */ | ||
77 | __uint16_t count; /* count of active leaf_entry's */ | ||
78 | __uint16_t namebytes; /* num bytes of name strings stored */ | ||
79 | __uint16_t firstused; /* first used byte in name area */ | ||
80 | __uint8_t holes; /* != 0 if blk needs compaction */ | ||
81 | __uint8_t pad1; | ||
82 | xfs_dir_leaf_map_t freemap[XFS_DIR_LEAF_MAPSIZE]; | ||
83 | } xfs_dir_leaf_hdr_t; | ||
84 | |||
85 | typedef struct xfs_dir_leaf_entry { /* sorted on key, not name */ | ||
86 | xfs_dahash_t hashval; /* hash value of name */ | ||
87 | __uint16_t nameidx; /* index into buffer of name */ | ||
88 | __uint8_t namelen; /* length of name string */ | ||
89 | __uint8_t pad2; | ||
90 | } xfs_dir_leaf_entry_t; | ||
91 | |||
92 | typedef struct xfs_dir_leaf_name { | ||
93 | xfs_dir_ino_t inumber; /* inode number for this key */ | ||
94 | __uint8_t name[1]; /* name string itself */ | ||
95 | } xfs_dir_leaf_name_t; | ||
96 | |||
97 | typedef struct xfs_dir_leafblock { | ||
98 | xfs_dir_leaf_hdr_t hdr; /* constant-structure header block */ | ||
99 | xfs_dir_leaf_entry_t entries[1]; /* var sized array */ | ||
100 | xfs_dir_leaf_name_t namelist[1]; /* grows from bottom of buf */ | ||
101 | } xfs_dir_leafblock_t; | ||
102 | |||
103 | /* | ||
104 | * Length of name for which a 512-byte block filesystem | ||
105 | * can get a double split. | ||
106 | */ | ||
107 | #define XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN \ | ||
108 | (512 - (uint)sizeof(xfs_dir_leaf_hdr_t) - \ | ||
109 | (uint)sizeof(xfs_dir_leaf_entry_t) * 2 - \ | ||
110 | (uint)sizeof(xfs_dir_leaf_name_t) * 2 - (MAXNAMELEN - 2) + 1 + 1) | ||
111 | |||
112 | typedef int (*xfs_dir_put_t)(struct xfs_dir_put_args *pa); | ||
113 | |||
114 | typedef union { | ||
115 | xfs_off_t o; /* offset (cookie) */ | ||
116 | /* | ||
117 | * Watch the order here (endian-ness dependent). | ||
118 | */ | ||
119 | struct { | ||
120 | #ifndef XFS_NATIVE_HOST | ||
121 | xfs_dahash_t h; /* hash value */ | ||
122 | __uint32_t be; /* block and entry */ | ||
123 | #else | ||
124 | __uint32_t be; /* block and entry */ | ||
125 | xfs_dahash_t h; /* hash value */ | ||
126 | #endif /* XFS_NATIVE_HOST */ | ||
127 | } s; | ||
128 | } xfs_dircook_t; | ||
129 | |||
130 | #define XFS_PUT_COOKIE(c,mp,bno,entry,hash) \ | ||
131 | ((c).s.be = XFS_DA_MAKE_BNOENTRY(mp, bno, entry), (c).s.h = (hash)) | ||
132 | |||
133 | typedef struct xfs_dir_put_args { | ||
134 | xfs_dircook_t cook; /* cookie of (next) entry */ | ||
135 | xfs_intino_t ino; /* inode number */ | ||
136 | struct xfs_dirent *dbp; /* buffer pointer */ | ||
137 | char *name; /* directory entry name */ | ||
138 | int namelen; /* length of name */ | ||
139 | int done; /* output: set if value was stored */ | ||
140 | xfs_dir_put_t put; /* put function ptr (i/o) */ | ||
141 | struct uio *uio; /* uio control structure */ | ||
142 | } xfs_dir_put_args_t; | ||
143 | |||
144 | #define XFS_DIR_LEAF_ENTSIZE_BYNAME(len) \ | ||
145 | xfs_dir_leaf_entsize_byname(len) | ||
146 | static inline int xfs_dir_leaf_entsize_byname(int len) | ||
147 | { | ||
148 | return (uint)sizeof(xfs_dir_leaf_name_t)-1 + len; | ||
149 | } | ||
150 | |||
151 | #define XFS_DIR_LEAF_ENTSIZE_BYENTRY(entry) \ | ||
152 | xfs_dir_leaf_entsize_byentry(entry) | ||
153 | static inline int xfs_dir_leaf_entsize_byentry(xfs_dir_leaf_entry_t *entry) | ||
154 | { | ||
155 | return (uint)sizeof(xfs_dir_leaf_name_t)-1 + (entry)->namelen; | ||
156 | } | ||
157 | |||
158 | #define XFS_DIR_LEAF_NAMESTRUCT(leafp,offset) \ | ||
159 | xfs_dir_leaf_namestruct(leafp,offset) | ||
160 | static inline xfs_dir_leaf_name_t * | ||
161 | xfs_dir_leaf_namestruct(xfs_dir_leafblock_t *leafp, int offset) | ||
162 | { | ||
163 | return (xfs_dir_leaf_name_t *)&((char *)(leafp))[offset]; | ||
164 | } | ||
165 | |||
166 | /*======================================================================== | ||
167 | * Function prototypes for the kernel. | ||
168 | *========================================================================*/ | ||
169 | |||
170 | /* | ||
171 | * Internal routines when dirsize < XFS_LITINO(mp). | ||
172 | */ | ||
173 | int xfs_dir_shortform_create(struct xfs_da_args *args, xfs_ino_t parent); | ||
174 | int xfs_dir_shortform_addname(struct xfs_da_args *args); | ||
175 | int xfs_dir_shortform_lookup(struct xfs_da_args *args); | ||
176 | int xfs_dir_shortform_to_leaf(struct xfs_da_args *args); | ||
177 | int xfs_dir_shortform_removename(struct xfs_da_args *args); | ||
178 | int xfs_dir_shortform_getdents(struct xfs_inode *dp, struct uio *uio, int *eofp, | ||
179 | struct xfs_dirent *dbp, xfs_dir_put_t put); | ||
180 | int xfs_dir_shortform_replace(struct xfs_da_args *args); | ||
181 | |||
182 | /* | ||
183 | * Internal routines when dirsize == XFS_LBSIZE(mp). | ||
184 | */ | ||
185 | int xfs_dir_leaf_to_node(struct xfs_da_args *args); | ||
186 | int xfs_dir_leaf_to_shortform(struct xfs_da_args *args); | ||
187 | |||
188 | /* | ||
189 | * Routines used for growing the Btree. | ||
190 | */ | ||
191 | int xfs_dir_leaf_split(struct xfs_da_state *state, | ||
192 | struct xfs_da_state_blk *oldblk, | ||
193 | struct xfs_da_state_blk *newblk); | ||
194 | int xfs_dir_leaf_add(struct xfs_dabuf *leaf_buffer, | ||
195 | struct xfs_da_args *args, int insertion_index); | ||
196 | int xfs_dir_leaf_addname(struct xfs_da_args *args); | ||
197 | int xfs_dir_leaf_lookup_int(struct xfs_dabuf *leaf_buffer, | ||
198 | struct xfs_da_args *args, | ||
199 | int *index_found_at); | ||
200 | int xfs_dir_leaf_remove(struct xfs_trans *trans, | ||
201 | struct xfs_dabuf *leaf_buffer, | ||
202 | int index_to_remove); | ||
203 | int xfs_dir_leaf_getdents_int(struct xfs_dabuf *bp, struct xfs_inode *dp, | ||
204 | xfs_dablk_t bno, struct uio *uio, | ||
205 | int *eobp, struct xfs_dirent *dbp, | ||
206 | xfs_dir_put_t put, xfs_daddr_t nextda); | ||
207 | |||
208 | /* | ||
209 | * Routines used for shrinking the Btree. | ||
210 | */ | ||
211 | int xfs_dir_leaf_toosmall(struct xfs_da_state *state, int *retval); | ||
212 | void xfs_dir_leaf_unbalance(struct xfs_da_state *state, | ||
213 | struct xfs_da_state_blk *drop_blk, | ||
214 | struct xfs_da_state_blk *save_blk); | ||
215 | |||
216 | /* | ||
217 | * Utility routines. | ||
218 | */ | ||
219 | uint xfs_dir_leaf_lasthash(struct xfs_dabuf *bp, int *count); | ||
220 | int xfs_dir_leaf_order(struct xfs_dabuf *leaf1_bp, | ||
221 | struct xfs_dabuf *leaf2_bp); | ||
222 | int xfs_dir_put_dirent64_direct(xfs_dir_put_args_t *pa); | ||
223 | int xfs_dir_put_dirent64_uio(xfs_dir_put_args_t *pa); | ||
224 | int xfs_dir_ino_validate(struct xfs_mount *mp, xfs_ino_t ino); | ||
225 | |||
226 | /* | ||
227 | * Global data. | ||
228 | */ | ||
229 | extern xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot; | ||
230 | |||
231 | #endif /* __XFS_DIR_LEAF_H__ */ | ||
diff --git a/fs/xfs/xfs_dir_sf.h b/fs/xfs/xfs_dir_sf.h deleted file mode 100644 index 5b20b4d3f57d..000000000000 --- a/fs/xfs/xfs_dir_sf.h +++ /dev/null | |||
@@ -1,155 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_DIR_SF_H__ | ||
19 | #define __XFS_DIR_SF_H__ | ||
20 | |||
21 | /* | ||
22 | * Directory layout when stored internal to an inode. | ||
23 | * | ||
24 | * Small directories are packed as tightly as possible so as to | ||
25 | * fit into the literal area of the inode. | ||
26 | */ | ||
27 | |||
28 | typedef struct { __uint8_t i[sizeof(xfs_ino_t)]; } xfs_dir_ino_t; | ||
29 | |||
30 | /* | ||
31 | * The parent directory has a dedicated field, and the self-pointer must | ||
32 | * be calculated on the fly. | ||
33 | * | ||
34 | * Entries are packed toward the top as tight as possible. The header | ||
35 | * and the elements much be memcpy'd out into a work area to get correct | ||
36 | * alignment for the inode number fields. | ||
37 | */ | ||
38 | typedef struct xfs_dir_sf_hdr { /* constant-structure header block */ | ||
39 | xfs_dir_ino_t parent; /* parent dir inode number */ | ||
40 | __uint8_t count; /* count of active entries */ | ||
41 | } xfs_dir_sf_hdr_t; | ||
42 | |||
43 | typedef struct xfs_dir_sf_entry { | ||
44 | xfs_dir_ino_t inumber; /* referenced inode number */ | ||
45 | __uint8_t namelen; /* actual length of name (no NULL) */ | ||
46 | __uint8_t name[1]; /* name */ | ||
47 | } xfs_dir_sf_entry_t; | ||
48 | |||
49 | typedef struct xfs_dir_shortform { | ||
50 | xfs_dir_sf_hdr_t hdr; | ||
51 | xfs_dir_sf_entry_t list[1]; /* variable sized array */ | ||
52 | } xfs_dir_shortform_t; | ||
53 | |||
54 | /* | ||
55 | * We generate this then sort it, so that readdirs are returned in | ||
56 | * hash-order. Else seekdir won't work. | ||
57 | */ | ||
58 | typedef struct xfs_dir_sf_sort { | ||
59 | __uint8_t entno; /* .=0, ..=1, else entry# + 2 */ | ||
60 | __uint8_t seqno; /* sequence # with same hash value */ | ||
61 | __uint8_t namelen; /* length of name value (no null) */ | ||
62 | xfs_dahash_t hash; /* this entry's hash value */ | ||
63 | xfs_intino_t ino; /* this entry's inode number */ | ||
64 | char *name; /* name value, pointer into buffer */ | ||
65 | } xfs_dir_sf_sort_t; | ||
66 | |||
67 | #define XFS_DIR_SF_GET_DIRINO(from,to) xfs_dir_sf_get_dirino(from, to) | ||
68 | static inline void xfs_dir_sf_get_dirino(xfs_dir_ino_t *from, xfs_ino_t *to) | ||
69 | { | ||
70 | *(to) = XFS_GET_DIR_INO8(*from); | ||
71 | } | ||
72 | |||
73 | #define XFS_DIR_SF_PUT_DIRINO(from,to) xfs_dir_sf_put_dirino(from, to) | ||
74 | static inline void xfs_dir_sf_put_dirino(xfs_ino_t *from, xfs_dir_ino_t *to) | ||
75 | { | ||
76 | XFS_PUT_DIR_INO8(*(from), *(to)); | ||
77 | } | ||
78 | |||
79 | #define XFS_DIR_SF_ENTSIZE_BYNAME(len) xfs_dir_sf_entsize_byname(len) | ||
80 | static inline int xfs_dir_sf_entsize_byname(int len) | ||
81 | { | ||
82 | return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (len); | ||
83 | } | ||
84 | |||
85 | #define XFS_DIR_SF_ENTSIZE_BYENTRY(sfep) xfs_dir_sf_entsize_byentry(sfep) | ||
86 | static inline int xfs_dir_sf_entsize_byentry(xfs_dir_sf_entry_t *sfep) | ||
87 | { | ||
88 | return (uint)sizeof(xfs_dir_sf_entry_t)-1 + (sfep)->namelen; | ||
89 | } | ||
90 | |||
91 | #define XFS_DIR_SF_NEXTENTRY(sfep) xfs_dir_sf_nextentry(sfep) | ||
92 | static inline xfs_dir_sf_entry_t *xfs_dir_sf_nextentry(xfs_dir_sf_entry_t *sfep) | ||
93 | { | ||
94 | return (xfs_dir_sf_entry_t *) \ | ||
95 | ((char *)(sfep) + XFS_DIR_SF_ENTSIZE_BYENTRY(sfep)); | ||
96 | } | ||
97 | |||
98 | #define XFS_DIR_SF_ALLFIT(count,totallen) \ | ||
99 | xfs_dir_sf_allfit(count,totallen) | ||
100 | static inline int xfs_dir_sf_allfit(int count, int totallen) | ||
101 | { | ||
102 | return ((uint)sizeof(xfs_dir_sf_hdr_t) + \ | ||
103 | ((uint)sizeof(xfs_dir_sf_entry_t)-1)*(count) + (totallen)); | ||
104 | } | ||
105 | |||
106 | #if defined(XFS_DIR_TRACE) | ||
107 | |||
108 | /* | ||
109 | * Kernel tracing support for directories. | ||
110 | */ | ||
111 | struct uio; | ||
112 | struct xfs_inode; | ||
113 | struct xfs_da_intnode; | ||
114 | struct xfs_dinode; | ||
115 | struct xfs_dir_leafblock; | ||
116 | struct xfs_dir_leaf_entry; | ||
117 | |||
118 | #define XFS_DIR_TRACE_SIZE 4096 /* size of global trace buffer */ | ||
119 | extern ktrace_t *xfs_dir_trace_buf; | ||
120 | |||
121 | /* | ||
122 | * Trace record types. | ||
123 | */ | ||
124 | #define XFS_DIR_KTRACE_G_DU 1 /* dp, uio */ | ||
125 | #define XFS_DIR_KTRACE_G_DUB 2 /* dp, uio, bno */ | ||
126 | #define XFS_DIR_KTRACE_G_DUN 3 /* dp, uio, node */ | ||
127 | #define XFS_DIR_KTRACE_G_DUL 4 /* dp, uio, leaf */ | ||
128 | #define XFS_DIR_KTRACE_G_DUE 5 /* dp, uio, leaf entry */ | ||
129 | #define XFS_DIR_KTRACE_G_DUC 6 /* dp, uio, cookie */ | ||
130 | |||
131 | void xfs_dir_trace_g_du(char *where, struct xfs_inode *dp, struct uio *uio); | ||
132 | void xfs_dir_trace_g_dub(char *where, struct xfs_inode *dp, struct uio *uio, | ||
133 | xfs_dablk_t bno); | ||
134 | void xfs_dir_trace_g_dun(char *where, struct xfs_inode *dp, struct uio *uio, | ||
135 | struct xfs_da_intnode *node); | ||
136 | void xfs_dir_trace_g_dul(char *where, struct xfs_inode *dp, struct uio *uio, | ||
137 | struct xfs_dir_leafblock *leaf); | ||
138 | void xfs_dir_trace_g_due(char *where, struct xfs_inode *dp, struct uio *uio, | ||
139 | struct xfs_dir_leaf_entry *entry); | ||
140 | void xfs_dir_trace_g_duc(char *where, struct xfs_inode *dp, struct uio *uio, | ||
141 | xfs_off_t cookie); | ||
142 | void xfs_dir_trace_enter(int type, char *where, | ||
143 | void *a0, void *a1, void *a2, void *a3, | ||
144 | void *a4, void *a5, void *a6, void *a7, | ||
145 | void *a8, void *a9, void *a10, void *a11); | ||
146 | #else | ||
147 | #define xfs_dir_trace_g_du(w,d,u) | ||
148 | #define xfs_dir_trace_g_dub(w,d,u,b) | ||
149 | #define xfs_dir_trace_g_dun(w,d,u,n) | ||
150 | #define xfs_dir_trace_g_dul(w,d,u,l) | ||
151 | #define xfs_dir_trace_g_due(w,d,u,e) | ||
152 | #define xfs_dir_trace_g_duc(w,d,u,c) | ||
153 | #endif /* DEBUG */ | ||
154 | |||
155 | #endif /* __XFS_DIR_SF_H__ */ | ||
diff --git a/fs/xfs/xfs_dmapi.h b/fs/xfs/xfs_dmapi.h index 00b1540f8108..4e7865ad6f0e 100644 --- a/fs/xfs/xfs_dmapi.h +++ b/fs/xfs/xfs_dmapi.h | |||
@@ -189,6 +189,6 @@ typedef enum { | |||
189 | #define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) | 189 | #define AT_DELAY_FLAG(f) ((f&ATTR_NONBLOCK) ? DM_FLAGS_NDELAY : 0) |
190 | 190 | ||
191 | 191 | ||
192 | extern struct bhv_vfsops xfs_dmops; | 192 | extern struct bhv_module_vfsops xfs_dmops; |
193 | 193 | ||
194 | #endif /* __XFS_DMAPI_H__ */ | 194 | #endif /* __XFS_DMAPI_H__ */ |
diff --git a/fs/xfs/xfs_dmops.c b/fs/xfs/xfs_dmops.c index 629795b3b3d5..1e4a35ddf7f9 100644 --- a/fs/xfs/xfs_dmops.c +++ b/fs/xfs/xfs_dmops.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 27 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
diff --git a/fs/xfs/xfs_error.c b/fs/xfs/xfs_error.c index 2a21c5024017..b95681b03d81 100644 --- a/fs/xfs/xfs_error.c +++ b/fs/xfs/xfs_error.c | |||
@@ -22,12 +22,10 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_bmap_btree.h" | 28 | #include "xfs_bmap_btree.h" |
30 | #include "xfs_dir_sf.h" | ||
31 | #include "xfs_dir2_sf.h" | 29 | #include "xfs_dir2_sf.h" |
32 | #include "xfs_attr_sf.h" | 30 | #include "xfs_attr_sf.h" |
33 | #include "xfs_dinode.h" | 31 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_extfree_item.c b/fs/xfs/xfs_extfree_item.c index f19282ec8549..6cf6d8769b97 100644 --- a/fs/xfs/xfs_extfree_item.c +++ b/fs/xfs/xfs_extfree_item.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_buf_item.h" | 24 | #include "xfs_buf_item.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_trans_priv.h" | 28 | #include "xfs_trans_priv.h" |
@@ -294,6 +293,62 @@ xfs_efi_init(xfs_mount_t *mp, | |||
294 | } | 293 | } |
295 | 294 | ||
296 | /* | 295 | /* |
296 | * Copy an EFI format buffer from the given buf, and into the destination | ||
297 | * EFI format structure. | ||
298 | * The given buffer can be in 32 bit or 64 bit form (which has different padding), | ||
299 | * one of which will be the native format for this kernel. | ||
300 | * It will handle the conversion of formats if necessary. | ||
301 | */ | ||
302 | int | ||
303 | xfs_efi_copy_format(xfs_log_iovec_t *buf, xfs_efi_log_format_t *dst_efi_fmt) | ||
304 | { | ||
305 | xfs_efi_log_format_t *src_efi_fmt = (xfs_efi_log_format_t *)buf->i_addr; | ||
306 | uint i; | ||
307 | uint len = sizeof(xfs_efi_log_format_t) + | ||
308 | (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_t); | ||
309 | uint len32 = sizeof(xfs_efi_log_format_32_t) + | ||
310 | (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_32_t); | ||
311 | uint len64 = sizeof(xfs_efi_log_format_64_t) + | ||
312 | (src_efi_fmt->efi_nextents - 1) * sizeof(xfs_extent_64_t); | ||
313 | |||
314 | if (buf->i_len == len) { | ||
315 | memcpy((char *)dst_efi_fmt, (char*)src_efi_fmt, len); | ||
316 | return 0; | ||
317 | } else if (buf->i_len == len32) { | ||
318 | xfs_efi_log_format_32_t *src_efi_fmt_32 = | ||
319 | (xfs_efi_log_format_32_t *)buf->i_addr; | ||
320 | |||
321 | dst_efi_fmt->efi_type = src_efi_fmt_32->efi_type; | ||
322 | dst_efi_fmt->efi_size = src_efi_fmt_32->efi_size; | ||
323 | dst_efi_fmt->efi_nextents = src_efi_fmt_32->efi_nextents; | ||
324 | dst_efi_fmt->efi_id = src_efi_fmt_32->efi_id; | ||
325 | for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { | ||
326 | dst_efi_fmt->efi_extents[i].ext_start = | ||
327 | src_efi_fmt_32->efi_extents[i].ext_start; | ||
328 | dst_efi_fmt->efi_extents[i].ext_len = | ||
329 | src_efi_fmt_32->efi_extents[i].ext_len; | ||
330 | } | ||
331 | return 0; | ||
332 | } else if (buf->i_len == len64) { | ||
333 | xfs_efi_log_format_64_t *src_efi_fmt_64 = | ||
334 | (xfs_efi_log_format_64_t *)buf->i_addr; | ||
335 | |||
336 | dst_efi_fmt->efi_type = src_efi_fmt_64->efi_type; | ||
337 | dst_efi_fmt->efi_size = src_efi_fmt_64->efi_size; | ||
338 | dst_efi_fmt->efi_nextents = src_efi_fmt_64->efi_nextents; | ||
339 | dst_efi_fmt->efi_id = src_efi_fmt_64->efi_id; | ||
340 | for (i = 0; i < dst_efi_fmt->efi_nextents; i++) { | ||
341 | dst_efi_fmt->efi_extents[i].ext_start = | ||
342 | src_efi_fmt_64->efi_extents[i].ext_start; | ||
343 | dst_efi_fmt->efi_extents[i].ext_len = | ||
344 | src_efi_fmt_64->efi_extents[i].ext_len; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | return EFSCORRUPTED; | ||
349 | } | ||
350 | |||
351 | /* | ||
297 | * This is called by the efd item code below to release references to | 352 | * This is called by the efd item code below to release references to |
298 | * the given efi item. Each efd calls this with the number of | 353 | * the given efi item. Each efd calls this with the number of |
299 | * extents that it has logged, and when the sum of these reaches | 354 | * extents that it has logged, and when the sum of these reaches |
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h index 5bf681708fec..0ea45edaab03 100644 --- a/fs/xfs/xfs_extfree_item.h +++ b/fs/xfs/xfs_extfree_item.h | |||
@@ -27,6 +27,24 @@ typedef struct xfs_extent { | |||
27 | } xfs_extent_t; | 27 | } xfs_extent_t; |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Since an xfs_extent_t has types (start:64, len: 32) | ||
31 | * there are different alignments on 32 bit and 64 bit kernels. | ||
32 | * So we provide the different variants for use by a | ||
33 | * conversion routine. | ||
34 | */ | ||
35 | |||
36 | typedef struct xfs_extent_32 { | ||
37 | xfs_dfsbno_t ext_start; | ||
38 | xfs_extlen_t ext_len; | ||
39 | } __attribute__((packed)) xfs_extent_32_t; | ||
40 | |||
41 | typedef struct xfs_extent_64 { | ||
42 | xfs_dfsbno_t ext_start; | ||
43 | xfs_extlen_t ext_len; | ||
44 | __uint32_t ext_pad; | ||
45 | } xfs_extent_64_t; | ||
46 | |||
47 | /* | ||
30 | * This is the structure used to lay out an efi log item in the | 48 | * This is the structure used to lay out an efi log item in the |
31 | * log. The efi_extents field is a variable size array whose | 49 | * log. The efi_extents field is a variable size array whose |
32 | * size is given by efi_nextents. | 50 | * size is given by efi_nextents. |
@@ -39,6 +57,22 @@ typedef struct xfs_efi_log_format { | |||
39 | xfs_extent_t efi_extents[1]; /* array of extents to free */ | 57 | xfs_extent_t efi_extents[1]; /* array of extents to free */ |
40 | } xfs_efi_log_format_t; | 58 | } xfs_efi_log_format_t; |
41 | 59 | ||
60 | typedef struct xfs_efi_log_format_32 { | ||
61 | unsigned short efi_type; /* efi log item type */ | ||
62 | unsigned short efi_size; /* size of this item */ | ||
63 | uint efi_nextents; /* # extents to free */ | ||
64 | __uint64_t efi_id; /* efi identifier */ | ||
65 | xfs_extent_32_t efi_extents[1]; /* array of extents to free */ | ||
66 | } __attribute__((packed)) xfs_efi_log_format_32_t; | ||
67 | |||
68 | typedef struct xfs_efi_log_format_64 { | ||
69 | unsigned short efi_type; /* efi log item type */ | ||
70 | unsigned short efi_size; /* size of this item */ | ||
71 | uint efi_nextents; /* # extents to free */ | ||
72 | __uint64_t efi_id; /* efi identifier */ | ||
73 | xfs_extent_64_t efi_extents[1]; /* array of extents to free */ | ||
74 | } xfs_efi_log_format_64_t; | ||
75 | |||
42 | /* | 76 | /* |
43 | * This is the structure used to lay out an efd log item in the | 77 | * This is the structure used to lay out an efd log item in the |
44 | * log. The efd_extents array is a variable size array whose | 78 | * log. The efd_extents array is a variable size array whose |
@@ -52,6 +86,22 @@ typedef struct xfs_efd_log_format { | |||
52 | xfs_extent_t efd_extents[1]; /* array of extents freed */ | 86 | xfs_extent_t efd_extents[1]; /* array of extents freed */ |
53 | } xfs_efd_log_format_t; | 87 | } xfs_efd_log_format_t; |
54 | 88 | ||
89 | typedef struct xfs_efd_log_format_32 { | ||
90 | unsigned short efd_type; /* efd log item type */ | ||
91 | unsigned short efd_size; /* size of this item */ | ||
92 | uint efd_nextents; /* # of extents freed */ | ||
93 | __uint64_t efd_efi_id; /* id of corresponding efi */ | ||
94 | xfs_extent_32_t efd_extents[1]; /* array of extents freed */ | ||
95 | } __attribute__((packed)) xfs_efd_log_format_32_t; | ||
96 | |||
97 | typedef struct xfs_efd_log_format_64 { | ||
98 | unsigned short efd_type; /* efd log item type */ | ||
99 | unsigned short efd_size; /* size of this item */ | ||
100 | uint efd_nextents; /* # of extents freed */ | ||
101 | __uint64_t efd_efi_id; /* id of corresponding efi */ | ||
102 | xfs_extent_64_t efd_extents[1]; /* array of extents freed */ | ||
103 | } xfs_efd_log_format_64_t; | ||
104 | |||
55 | 105 | ||
56 | #ifdef __KERNEL__ | 106 | #ifdef __KERNEL__ |
57 | 107 | ||
@@ -103,7 +153,8 @@ extern struct kmem_zone *xfs_efd_zone; | |||
103 | xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); | 153 | xfs_efi_log_item_t *xfs_efi_init(struct xfs_mount *, uint); |
104 | xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, | 154 | xfs_efd_log_item_t *xfs_efd_init(struct xfs_mount *, xfs_efi_log_item_t *, |
105 | uint); | 155 | uint); |
106 | 156 | int xfs_efi_copy_format(xfs_log_iovec_t *buf, | |
157 | xfs_efi_log_format_t *dst_efi_fmt); | ||
107 | void xfs_efi_item_free(xfs_efi_log_item_t *); | 158 | void xfs_efi_item_free(xfs_efi_log_item_t *); |
108 | 159 | ||
109 | #endif /* __KERNEL__ */ | 160 | #endif /* __KERNEL__ */ |
diff --git a/fs/xfs/xfs_fs.h b/fs/xfs/xfs_fs.h index 14010f1fa82f..0f0ad1535951 100644 --- a/fs/xfs/xfs_fs.h +++ b/fs/xfs/xfs_fs.h | |||
@@ -67,14 +67,15 @@ struct fsxattr { | |||
67 | #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ | 67 | #define XFS_XFLAG_NOSYMLINKS 0x00000400 /* disallow symlink creation */ |
68 | #define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ | 68 | #define XFS_XFLAG_EXTSIZE 0x00000800 /* extent size allocator hint */ |
69 | #define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ | 69 | #define XFS_XFLAG_EXTSZINHERIT 0x00001000 /* inherit inode extent size */ |
70 | #define XFS_XFLAG_NODEFRAG 0x00002000 /* do not defragment */ | ||
70 | #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ | 71 | #define XFS_XFLAG_HASATTR 0x80000000 /* no DIFLAG for this */ |
71 | 72 | ||
72 | /* | 73 | /* |
73 | * Structure for XFS_IOC_GETBMAP. | 74 | * Structure for XFS_IOC_GETBMAP. |
74 | * On input, fill in bmv_offset and bmv_length of the first structure | 75 | * On input, fill in bmv_offset and bmv_length of the first structure |
75 | * to indicate the area of interest in the file, and bmv_entry with the | 76 | * to indicate the area of interest in the file, and bmv_entries with |
76 | * number of array elements given. The first structure is updated on | 77 | * the number of array elements given back. The first structure is |
77 | * return to give the offset and length for the next call. | 78 | * updated on return to give the offset and length for the next call. |
78 | */ | 79 | */ |
79 | #ifndef HAVE_GETBMAP | 80 | #ifndef HAVE_GETBMAP |
80 | struct getbmap { | 81 | struct getbmap { |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index dfa3527b20a7..077629bab532 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -542,14 +540,13 @@ xfs_reserve_blocks( | |||
542 | } | 540 | } |
543 | 541 | ||
544 | void | 542 | void |
545 | xfs_fs_log_dummy(xfs_mount_t *mp) | 543 | xfs_fs_log_dummy( |
544 | xfs_mount_t *mp) | ||
546 | { | 545 | { |
547 | xfs_trans_t *tp; | 546 | xfs_trans_t *tp; |
548 | xfs_inode_t *ip; | 547 | xfs_inode_t *ip; |
549 | |||
550 | 548 | ||
551 | tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); | 549 | tp = _xfs_trans_alloc(mp, XFS_TRANS_DUMMY1); |
552 | atomic_inc(&mp->m_active_trans); | ||
553 | if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) { | 550 | if (xfs_trans_reserve(tp, 0, XFS_ICHANGE_LOG_RES(mp), 0, 0, 0)) { |
554 | xfs_trans_cancel(tp, 0); | 551 | xfs_trans_cancel(tp, 0); |
555 | return; | 552 | return; |
@@ -574,21 +571,22 @@ xfs_fs_goingdown( | |||
574 | { | 571 | { |
575 | switch (inflags) { | 572 | switch (inflags) { |
576 | case XFS_FSOP_GOING_FLAGS_DEFAULT: { | 573 | case XFS_FSOP_GOING_FLAGS_DEFAULT: { |
577 | struct vfs *vfsp = XFS_MTOVFS(mp); | 574 | struct bhv_vfs *vfsp = XFS_MTOVFS(mp); |
578 | struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); | 575 | struct super_block *sb = freeze_bdev(vfsp->vfs_super->s_bdev); |
579 | 576 | ||
580 | if (sb && !IS_ERR(sb)) { | 577 | if (sb && !IS_ERR(sb)) { |
581 | xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); | 578 | xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); |
582 | thaw_bdev(sb->s_bdev, sb); | 579 | thaw_bdev(sb->s_bdev, sb); |
583 | } | 580 | } |
584 | 581 | ||
585 | break; | 582 | break; |
586 | } | 583 | } |
587 | case XFS_FSOP_GOING_FLAGS_LOGFLUSH: | 584 | case XFS_FSOP_GOING_FLAGS_LOGFLUSH: |
588 | xfs_force_shutdown(mp, XFS_FORCE_UMOUNT); | 585 | xfs_force_shutdown(mp, SHUTDOWN_FORCE_UMOUNT); |
589 | break; | 586 | break; |
590 | case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH: | 587 | case XFS_FSOP_GOING_FLAGS_NOLOGFLUSH: |
591 | xfs_force_shutdown(mp, XFS_FORCE_UMOUNT|XFS_LOG_IO_ERROR); | 588 | xfs_force_shutdown(mp, |
589 | SHUTDOWN_FORCE_UMOUNT | SHUTDOWN_LOG_IO_ERROR); | ||
592 | break; | 590 | break; |
593 | default: | 591 | default: |
594 | return XFS_ERROR(EINVAL); | 592 | return XFS_ERROR(EINVAL); |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index deddbd03c166..33164a85aa9d 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -1174,6 +1172,9 @@ xfs_dilocate( | |||
1174 | if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || | 1172 | if (agno >= mp->m_sb.sb_agcount || agbno >= mp->m_sb.sb_agblocks || |
1175 | ino != XFS_AGINO_TO_INO(mp, agno, agino)) { | 1173 | ino != XFS_AGINO_TO_INO(mp, agno, agino)) { |
1176 | #ifdef DEBUG | 1174 | #ifdef DEBUG |
1175 | /* no diagnostics for bulkstat, ino comes from userspace */ | ||
1176 | if (flags & XFS_IMAP_BULKSTAT) | ||
1177 | return XFS_ERROR(EINVAL); | ||
1177 | if (agno >= mp->m_sb.sb_agcount) { | 1178 | if (agno >= mp->m_sb.sb_agcount) { |
1178 | xfs_fs_cmn_err(CE_ALERT, mp, | 1179 | xfs_fs_cmn_err(CE_ALERT, mp, |
1179 | "xfs_dilocate: agno (%d) >= " | 1180 | "xfs_dilocate: agno (%d) >= " |
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 60c65683462d..616eeeb6953e 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_iget.c b/fs/xfs/xfs_iget.c index b53854325266..0724df7fabb7 100644 --- a/fs/xfs/xfs_iget.c +++ b/fs/xfs/xfs_iget.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -186,7 +184,7 @@ xfs_ihash_promote( | |||
186 | */ | 184 | */ |
187 | STATIC int | 185 | STATIC int |
188 | xfs_iget_core( | 186 | xfs_iget_core( |
189 | vnode_t *vp, | 187 | bhv_vnode_t *vp, |
190 | xfs_mount_t *mp, | 188 | xfs_mount_t *mp, |
191 | xfs_trans_t *tp, | 189 | xfs_trans_t *tp, |
192 | xfs_ino_t ino, | 190 | xfs_ino_t ino, |
@@ -198,7 +196,7 @@ xfs_iget_core( | |||
198 | xfs_ihash_t *ih; | 196 | xfs_ihash_t *ih; |
199 | xfs_inode_t *ip; | 197 | xfs_inode_t *ip; |
200 | xfs_inode_t *iq; | 198 | xfs_inode_t *iq; |
201 | vnode_t *inode_vp; | 199 | bhv_vnode_t *inode_vp; |
202 | ulong version; | 200 | ulong version; |
203 | int error; | 201 | int error; |
204 | /* REFERENCED */ | 202 | /* REFERENCED */ |
@@ -468,7 +466,7 @@ finish_inode: | |||
468 | * If we have a real type for an on-disk inode, we can set ops(&unlock) | 466 | * If we have a real type for an on-disk inode, we can set ops(&unlock) |
469 | * now. If it's a new inode being created, xfs_ialloc will handle it. | 467 | * now. If it's a new inode being created, xfs_ialloc will handle it. |
470 | */ | 468 | */ |
471 | VFS_INIT_VNODE(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1); | 469 | bhv_vfs_init_vnode(XFS_MTOVFS(mp), vp, XFS_ITOBHV(ip), 1); |
472 | 470 | ||
473 | return 0; | 471 | return 0; |
474 | } | 472 | } |
@@ -489,7 +487,7 @@ xfs_iget( | |||
489 | xfs_daddr_t bno) | 487 | xfs_daddr_t bno) |
490 | { | 488 | { |
491 | struct inode *inode; | 489 | struct inode *inode; |
492 | vnode_t *vp = NULL; | 490 | bhv_vnode_t *vp = NULL; |
493 | int error; | 491 | int error; |
494 | 492 | ||
495 | XFS_STATS_INC(xs_ig_attempts); | 493 | XFS_STATS_INC(xs_ig_attempts); |
@@ -543,7 +541,7 @@ retry: | |||
543 | void | 541 | void |
544 | xfs_inode_lock_init( | 542 | xfs_inode_lock_init( |
545 | xfs_inode_t *ip, | 543 | xfs_inode_t *ip, |
546 | vnode_t *vp) | 544 | bhv_vnode_t *vp) |
547 | { | 545 | { |
548 | mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, | 546 | mrlock_init(&ip->i_lock, MRLOCK_ALLOW_EQUAL_PRI|MRLOCK_BARRIER, |
549 | "xfsino", (long)vp->v_number); | 547 | "xfsino", (long)vp->v_number); |
@@ -603,12 +601,10 @@ void | |||
603 | xfs_iput(xfs_inode_t *ip, | 601 | xfs_iput(xfs_inode_t *ip, |
604 | uint lock_flags) | 602 | uint lock_flags) |
605 | { | 603 | { |
606 | vnode_t *vp = XFS_ITOV(ip); | 604 | bhv_vnode_t *vp = XFS_ITOV(ip); |
607 | 605 | ||
608 | vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address); | 606 | vn_trace_entry(vp, "xfs_iput", (inst_t *)__return_address); |
609 | |||
610 | xfs_iunlock(ip, lock_flags); | 607 | xfs_iunlock(ip, lock_flags); |
611 | |||
612 | VN_RELE(vp); | 608 | VN_RELE(vp); |
613 | } | 609 | } |
614 | 610 | ||
@@ -619,7 +615,7 @@ void | |||
619 | xfs_iput_new(xfs_inode_t *ip, | 615 | xfs_iput_new(xfs_inode_t *ip, |
620 | uint lock_flags) | 616 | uint lock_flags) |
621 | { | 617 | { |
622 | vnode_t *vp = XFS_ITOV(ip); | 618 | bhv_vnode_t *vp = XFS_ITOV(ip); |
623 | struct inode *inode = vn_to_inode(vp); | 619 | struct inode *inode = vn_to_inode(vp); |
624 | 620 | ||
625 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); | 621 | vn_trace_entry(vp, "xfs_iput_new", (inst_t *)__return_address); |
@@ -645,7 +641,7 @@ xfs_iput_new(xfs_inode_t *ip, | |||
645 | void | 641 | void |
646 | xfs_ireclaim(xfs_inode_t *ip) | 642 | xfs_ireclaim(xfs_inode_t *ip) |
647 | { | 643 | { |
648 | vnode_t *vp; | 644 | bhv_vnode_t *vp; |
649 | 645 | ||
650 | /* | 646 | /* |
651 | * Remove from old hash list and mount list. | 647 | * Remove from old hash list and mount list. |
@@ -1033,6 +1029,6 @@ xfs_iflock_nowait(xfs_inode_t *ip) | |||
1033 | void | 1029 | void |
1034 | xfs_ifunlock(xfs_inode_t *ip) | 1030 | xfs_ifunlock(xfs_inode_t *ip) |
1035 | { | 1031 | { |
1036 | ASSERT(valusema(&(ip->i_flock)) <= 0); | 1032 | ASSERT(issemalocked(&(ip->i_flock))); |
1037 | vsema(&(ip->i_flock)); | 1033 | vsema(&(ip->i_flock)); |
1038 | } | 1034 | } |
diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index 94b60dd03801..5fa0adb7e173 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -26,14 +26,12 @@ | |||
26 | #include "xfs_trans_priv.h" | 26 | #include "xfs_trans_priv.h" |
27 | #include "xfs_sb.h" | 27 | #include "xfs_sb.h" |
28 | #include "xfs_ag.h" | 28 | #include "xfs_ag.h" |
29 | #include "xfs_dir.h" | ||
30 | #include "xfs_dir2.h" | 29 | #include "xfs_dir2.h" |
31 | #include "xfs_dmapi.h" | 30 | #include "xfs_dmapi.h" |
32 | #include "xfs_mount.h" | 31 | #include "xfs_mount.h" |
33 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
39 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
@@ -256,13 +254,11 @@ xfs_itobp( | |||
256 | xfs_daddr_t bno, | 254 | xfs_daddr_t bno, |
257 | uint imap_flags) | 255 | uint imap_flags) |
258 | { | 256 | { |
257 | xfs_imap_t imap; | ||
259 | xfs_buf_t *bp; | 258 | xfs_buf_t *bp; |
260 | int error; | 259 | int error; |
261 | xfs_imap_t imap; | ||
262 | #ifdef __KERNEL__ | ||
263 | int i; | 260 | int i; |
264 | int ni; | 261 | int ni; |
265 | #endif | ||
266 | 262 | ||
267 | if (ip->i_blkno == (xfs_daddr_t)0) { | 263 | if (ip->i_blkno == (xfs_daddr_t)0) { |
268 | /* | 264 | /* |
@@ -319,7 +315,6 @@ xfs_itobp( | |||
319 | */ | 315 | */ |
320 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno, | 316 | error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, imap.im_blkno, |
321 | (int)imap.im_len, XFS_BUF_LOCK, &bp); | 317 | (int)imap.im_len, XFS_BUF_LOCK, &bp); |
322 | |||
323 | if (error) { | 318 | if (error) { |
324 | #ifdef DEBUG | 319 | #ifdef DEBUG |
325 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: " | 320 | xfs_fs_cmn_err(CE_ALERT, mp, "xfs_itobp: " |
@@ -330,17 +325,21 @@ xfs_itobp( | |||
330 | #endif /* DEBUG */ | 325 | #endif /* DEBUG */ |
331 | return error; | 326 | return error; |
332 | } | 327 | } |
333 | #ifdef __KERNEL__ | 328 | |
334 | /* | 329 | /* |
335 | * Validate the magic number and version of every inode in the buffer | 330 | * Validate the magic number and version of every inode in the buffer |
336 | * (if DEBUG kernel) or the first inode in the buffer, otherwise. | 331 | * (if DEBUG kernel) or the first inode in the buffer, otherwise. |
332 | * No validation is done here in userspace (xfs_repair). | ||
337 | */ | 333 | */ |
338 | #ifdef DEBUG | 334 | #if !defined(__KERNEL__) |
335 | ni = 0; | ||
336 | #elif defined(DEBUG) | ||
339 | ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : | 337 | ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : |
340 | (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); | 338 | (BBTOB(imap.im_len) >> mp->m_sb.sb_inodelog); |
341 | #else | 339 | #else /* usual case */ |
342 | ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; | 340 | ni = (imap_flags & XFS_IMAP_BULKSTAT) ? 0 : 1; |
343 | #endif | 341 | #endif |
342 | |||
344 | for (i = 0; i < ni; i++) { | 343 | for (i = 0; i < ni; i++) { |
345 | int di_ok; | 344 | int di_ok; |
346 | xfs_dinode_t *dip; | 345 | xfs_dinode_t *dip; |
@@ -352,8 +351,11 @@ xfs_itobp( | |||
352 | if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, | 351 | if (unlikely(XFS_TEST_ERROR(!di_ok, mp, XFS_ERRTAG_ITOBP_INOTOBP, |
353 | XFS_RANDOM_ITOBP_INOTOBP))) { | 352 | XFS_RANDOM_ITOBP_INOTOBP))) { |
354 | #ifdef DEBUG | 353 | #ifdef DEBUG |
355 | prdev("bad inode magic/vsn daddr %lld #%d (magic=%x)", | 354 | if (!(imap_flags & XFS_IMAP_BULKSTAT)) |
356 | mp->m_ddev_targp, | 355 | cmn_err(CE_ALERT, |
356 | "Device %s - bad inode magic/vsn " | ||
357 | "daddr %lld #%d (magic=%x)", | ||
358 | XFS_BUFTARG_NAME(mp->m_ddev_targp), | ||
357 | (unsigned long long)imap.im_blkno, i, | 359 | (unsigned long long)imap.im_blkno, i, |
358 | INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); | 360 | INT_GET(dip->di_core.di_magic, ARCH_CONVERT)); |
359 | #endif | 361 | #endif |
@@ -363,7 +365,6 @@ xfs_itobp( | |||
363 | return XFS_ERROR(EFSCORRUPTED); | 365 | return XFS_ERROR(EFSCORRUPTED); |
364 | } | 366 | } |
365 | } | 367 | } |
366 | #endif /* __KERNEL__ */ | ||
367 | 368 | ||
368 | xfs_inobp_check(mp, bp); | 369 | xfs_inobp_check(mp, bp); |
369 | 370 | ||
@@ -782,7 +783,6 @@ xfs_xlate_dinode_core( | |||
782 | 783 | ||
783 | STATIC uint | 784 | STATIC uint |
784 | _xfs_dic2xflags( | 785 | _xfs_dic2xflags( |
785 | xfs_dinode_core_t *dic, | ||
786 | __uint16_t di_flags) | 786 | __uint16_t di_flags) |
787 | { | 787 | { |
788 | uint flags = 0; | 788 | uint flags = 0; |
@@ -812,6 +812,8 @@ _xfs_dic2xflags( | |||
812 | flags |= XFS_XFLAG_EXTSIZE; | 812 | flags |= XFS_XFLAG_EXTSIZE; |
813 | if (di_flags & XFS_DIFLAG_EXTSZINHERIT) | 813 | if (di_flags & XFS_DIFLAG_EXTSZINHERIT) |
814 | flags |= XFS_XFLAG_EXTSZINHERIT; | 814 | flags |= XFS_XFLAG_EXTSZINHERIT; |
815 | if (di_flags & XFS_DIFLAG_NODEFRAG) | ||
816 | flags |= XFS_XFLAG_NODEFRAG; | ||
815 | } | 817 | } |
816 | 818 | ||
817 | return flags; | 819 | return flags; |
@@ -823,16 +825,16 @@ xfs_ip2xflags( | |||
823 | { | 825 | { |
824 | xfs_dinode_core_t *dic = &ip->i_d; | 826 | xfs_dinode_core_t *dic = &ip->i_d; |
825 | 827 | ||
826 | return _xfs_dic2xflags(dic, dic->di_flags) | | 828 | return _xfs_dic2xflags(dic->di_flags) | |
827 | (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); | 829 | (XFS_CFORK_Q(dic) ? XFS_XFLAG_HASATTR : 0); |
828 | } | 830 | } |
829 | 831 | ||
830 | uint | 832 | uint |
831 | xfs_dic2xflags( | 833 | xfs_dic2xflags( |
832 | xfs_dinode_core_t *dic) | 834 | xfs_dinode_core_t *dic) |
833 | { | 835 | { |
834 | return _xfs_dic2xflags(dic, INT_GET(dic->di_flags, ARCH_CONVERT)) | | 836 | return _xfs_dic2xflags(INT_GET(dic->di_flags, ARCH_CONVERT)) | |
835 | (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); | 837 | (XFS_CFORK_Q_DISK(dic) ? XFS_XFLAG_HASATTR : 0); |
836 | } | 838 | } |
837 | 839 | ||
838 | /* | 840 | /* |
@@ -1083,7 +1085,7 @@ xfs_ialloc( | |||
1083 | { | 1085 | { |
1084 | xfs_ino_t ino; | 1086 | xfs_ino_t ino; |
1085 | xfs_inode_t *ip; | 1087 | xfs_inode_t *ip; |
1086 | vnode_t *vp; | 1088 | bhv_vnode_t *vp; |
1087 | uint flags; | 1089 | uint flags; |
1088 | int error; | 1090 | int error; |
1089 | 1091 | ||
@@ -1221,6 +1223,9 @@ xfs_ialloc( | |||
1221 | di_flags |= XFS_DIFLAG_NOSYMLINKS; | 1223 | di_flags |= XFS_DIFLAG_NOSYMLINKS; |
1222 | if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 1224 | if (pip->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
1223 | di_flags |= XFS_DIFLAG_PROJINHERIT; | 1225 | di_flags |= XFS_DIFLAG_PROJINHERIT; |
1226 | if ((pip->i_d.di_flags & XFS_DIFLAG_NODEFRAG) && | ||
1227 | xfs_inherit_nodefrag) | ||
1228 | di_flags |= XFS_DIFLAG_NODEFRAG; | ||
1224 | ip->i_d.di_flags |= di_flags; | 1229 | ip->i_d.di_flags |= di_flags; |
1225 | } | 1230 | } |
1226 | /* FALLTHROUGH */ | 1231 | /* FALLTHROUGH */ |
@@ -1244,8 +1249,8 @@ xfs_ialloc( | |||
1244 | */ | 1249 | */ |
1245 | xfs_trans_log_inode(tp, ip, flags); | 1250 | xfs_trans_log_inode(tp, ip, flags); |
1246 | 1251 | ||
1247 | /* now that we have an i_mode we can set Linux inode ops (& unlock) */ | 1252 | /* now that we have an i_mode we can setup inode ops and unlock */ |
1248 | VFS_INIT_VNODE(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1); | 1253 | bhv_vfs_init_vnode(XFS_MTOVFS(tp->t_mountp), vp, XFS_ITOBHV(ip), 1); |
1249 | 1254 | ||
1250 | *ipp = ip; | 1255 | *ipp = ip; |
1251 | return 0; | 1256 | return 0; |
@@ -1285,7 +1290,7 @@ xfs_isize_check( | |||
1285 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - | 1290 | (xfs_ufsize_t)XFS_MAXIOFFSET(mp)) - |
1286 | map_first), | 1291 | map_first), |
1287 | XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, | 1292 | XFS_BMAPI_ENTIRE, NULL, 0, imaps, &nimaps, |
1288 | NULL)) | 1293 | NULL, NULL)) |
1289 | return; | 1294 | return; |
1290 | ASSERT(nimaps == 1); | 1295 | ASSERT(nimaps == 1); |
1291 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); | 1296 | ASSERT(imaps[0].br_startblock == HOLESTARTBLOCK); |
@@ -1421,7 +1426,7 @@ xfs_itruncate_start( | |||
1421 | xfs_fsize_t last_byte; | 1426 | xfs_fsize_t last_byte; |
1422 | xfs_off_t toss_start; | 1427 | xfs_off_t toss_start; |
1423 | xfs_mount_t *mp; | 1428 | xfs_mount_t *mp; |
1424 | vnode_t *vp; | 1429 | bhv_vnode_t *vp; |
1425 | 1430 | ||
1426 | ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0); | 1431 | ASSERT(ismrlocked(&ip->i_iolock, MR_UPDATE) != 0); |
1427 | ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size)); | 1432 | ASSERT((new_size == 0) || (new_size <= ip->i_d.di_size)); |
@@ -1434,9 +1439,9 @@ xfs_itruncate_start( | |||
1434 | vn_iowait(vp); /* wait for the completion of any pending DIOs */ | 1439 | vn_iowait(vp); /* wait for the completion of any pending DIOs */ |
1435 | 1440 | ||
1436 | /* | 1441 | /* |
1437 | * Call VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES() to get rid of pages and buffers | 1442 | * Call toss_pages or flushinval_pages to get rid of pages |
1438 | * overlapping the region being removed. We have to use | 1443 | * overlapping the region being removed. We have to use |
1439 | * the less efficient VOP_FLUSHINVAL_PAGES() in the case that the | 1444 | * the less efficient flushinval_pages in the case that the |
1440 | * caller may not be able to finish the truncate without | 1445 | * caller may not be able to finish the truncate without |
1441 | * dropping the inode's I/O lock. Make sure | 1446 | * dropping the inode's I/O lock. Make sure |
1442 | * to catch any pages brought in by buffers overlapping | 1447 | * to catch any pages brought in by buffers overlapping |
@@ -1445,10 +1450,10 @@ xfs_itruncate_start( | |||
1445 | * so that we don't toss things on the same block as | 1450 | * so that we don't toss things on the same block as |
1446 | * new_size but before it. | 1451 | * new_size but before it. |
1447 | * | 1452 | * |
1448 | * Before calling VOP_TOSS_PAGES() or VOP_FLUSHINVAL_PAGES(), make sure to | 1453 | * Before calling toss_page or flushinval_pages, make sure to |
1449 | * call remapf() over the same region if the file is mapped. | 1454 | * call remapf() over the same region if the file is mapped. |
1450 | * This frees up mapped file references to the pages in the | 1455 | * This frees up mapped file references to the pages in the |
1451 | * given range and for the VOP_FLUSHINVAL_PAGES() case it ensures | 1456 | * given range and for the flushinval_pages case it ensures |
1452 | * that we get the latest mapped changes flushed out. | 1457 | * that we get the latest mapped changes flushed out. |
1453 | */ | 1458 | */ |
1454 | toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); | 1459 | toss_start = XFS_B_TO_FSB(mp, (xfs_ufsize_t)new_size); |
@@ -1466,9 +1471,9 @@ xfs_itruncate_start( | |||
1466 | last_byte); | 1471 | last_byte); |
1467 | if (last_byte > toss_start) { | 1472 | if (last_byte > toss_start) { |
1468 | if (flags & XFS_ITRUNC_DEFINITE) { | 1473 | if (flags & XFS_ITRUNC_DEFINITE) { |
1469 | VOP_TOSS_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); | 1474 | bhv_vop_toss_pages(vp, toss_start, -1, FI_REMAPF_LOCKED); |
1470 | } else { | 1475 | } else { |
1471 | VOP_FLUSHINVAL_PAGES(vp, toss_start, -1, FI_REMAPF_LOCKED); | 1476 | bhv_vop_flushinval_pages(vp, toss_start, -1, FI_REMAPF_LOCKED); |
1472 | } | 1477 | } |
1473 | } | 1478 | } |
1474 | 1479 | ||
@@ -1666,12 +1671,13 @@ xfs_itruncate_finish( | |||
1666 | * runs. | 1671 | * runs. |
1667 | */ | 1672 | */ |
1668 | XFS_BMAP_INIT(&free_list, &first_block); | 1673 | XFS_BMAP_INIT(&free_list, &first_block); |
1669 | error = xfs_bunmapi(ntp, ip, first_unmap_block, | 1674 | error = XFS_BUNMAPI(mp, ntp, &ip->i_iocore, |
1670 | unmap_len, | 1675 | first_unmap_block, unmap_len, |
1671 | XFS_BMAPI_AFLAG(fork) | | 1676 | XFS_BMAPI_AFLAG(fork) | |
1672 | (sync ? 0 : XFS_BMAPI_ASYNC), | 1677 | (sync ? 0 : XFS_BMAPI_ASYNC), |
1673 | XFS_ITRUNC_MAX_EXTENTS, | 1678 | XFS_ITRUNC_MAX_EXTENTS, |
1674 | &first_block, &free_list, &done); | 1679 | &first_block, &free_list, |
1680 | NULL, &done); | ||
1675 | if (error) { | 1681 | if (error) { |
1676 | /* | 1682 | /* |
1677 | * If the bunmapi call encounters an error, | 1683 | * If the bunmapi call encounters an error, |
@@ -2745,13 +2751,14 @@ xfs_iunpin( | |||
2745 | * the inode to become unpinned. | 2751 | * the inode to become unpinned. |
2746 | */ | 2752 | */ |
2747 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { | 2753 | if (!(ip->i_flags & (XFS_IRECLAIM|XFS_IRECLAIMABLE))) { |
2748 | vnode_t *vp = XFS_ITOV_NULL(ip); | 2754 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); |
2749 | 2755 | ||
2750 | /* make sync come back and flush this inode */ | 2756 | /* make sync come back and flush this inode */ |
2751 | if (vp) { | 2757 | if (vp) { |
2752 | struct inode *inode = vn_to_inode(vp); | 2758 | struct inode *inode = vn_to_inode(vp); |
2753 | 2759 | ||
2754 | if (!(inode->i_state & I_NEW)) | 2760 | if (!(inode->i_state & |
2761 | (I_NEW|I_FREEING|I_CLEAR))) | ||
2755 | mark_inode_dirty_sync(inode); | 2762 | mark_inode_dirty_sync(inode); |
2756 | } | 2763 | } |
2757 | } | 2764 | } |
@@ -2916,13 +2923,6 @@ xfs_iflush_fork( | |||
2916 | ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); | 2923 | ASSERT(ifp->if_bytes <= XFS_IFORK_SIZE(ip, whichfork)); |
2917 | memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); | 2924 | memcpy(cp, ifp->if_u1.if_data, ifp->if_bytes); |
2918 | } | 2925 | } |
2919 | if (whichfork == XFS_DATA_FORK) { | ||
2920 | if (unlikely(XFS_DIR_SHORTFORM_VALIDATE_ONDISK(mp, dip))) { | ||
2921 | XFS_ERROR_REPORT("xfs_iflush_fork", | ||
2922 | XFS_ERRLEVEL_LOW, mp); | ||
2923 | return XFS_ERROR(EFSCORRUPTED); | ||
2924 | } | ||
2925 | } | ||
2926 | break; | 2926 | break; |
2927 | 2927 | ||
2928 | case XFS_DINODE_FMT_EXTENTS: | 2928 | case XFS_DINODE_FMT_EXTENTS: |
@@ -3006,7 +3006,7 @@ xfs_iflush( | |||
3006 | XFS_STATS_INC(xs_iflush_count); | 3006 | XFS_STATS_INC(xs_iflush_count); |
3007 | 3007 | ||
3008 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); | 3008 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); |
3009 | ASSERT(valusema(&ip->i_flock) <= 0); | 3009 | ASSERT(issemalocked(&(ip->i_flock))); |
3010 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || | 3010 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || |
3011 | ip->i_d.di_nextents > ip->i_df.if_ext_max); | 3011 | ip->i_d.di_nextents > ip->i_df.if_ext_max); |
3012 | 3012 | ||
@@ -3199,7 +3199,7 @@ xfs_iflush( | |||
3199 | 3199 | ||
3200 | corrupt_out: | 3200 | corrupt_out: |
3201 | xfs_buf_relse(bp); | 3201 | xfs_buf_relse(bp); |
3202 | xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); | 3202 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
3203 | xfs_iflush_abort(ip); | 3203 | xfs_iflush_abort(ip); |
3204 | /* | 3204 | /* |
3205 | * Unlocks the flush lock | 3205 | * Unlocks the flush lock |
@@ -3221,7 +3221,7 @@ cluster_corrupt_out: | |||
3221 | xfs_buf_relse(bp); | 3221 | xfs_buf_relse(bp); |
3222 | } | 3222 | } |
3223 | 3223 | ||
3224 | xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); | 3224 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
3225 | 3225 | ||
3226 | if(!bufwasdelwri) { | 3226 | if(!bufwasdelwri) { |
3227 | /* | 3227 | /* |
@@ -3264,7 +3264,7 @@ xfs_iflush_int( | |||
3264 | SPLDECL(s); | 3264 | SPLDECL(s); |
3265 | 3265 | ||
3266 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); | 3266 | ASSERT(ismrlocked(&ip->i_lock, MR_UPDATE|MR_ACCESS)); |
3267 | ASSERT(valusema(&ip->i_flock) <= 0); | 3267 | ASSERT(issemalocked(&(ip->i_flock))); |
3268 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || | 3268 | ASSERT(ip->i_d.di_format != XFS_DINODE_FMT_BTREE || |
3269 | ip->i_d.di_nextents > ip->i_df.if_ext_max); | 3269 | ip->i_d.di_nextents > ip->i_df.if_ext_max); |
3270 | 3270 | ||
@@ -3504,7 +3504,7 @@ xfs_iflush_all( | |||
3504 | xfs_mount_t *mp) | 3504 | xfs_mount_t *mp) |
3505 | { | 3505 | { |
3506 | xfs_inode_t *ip; | 3506 | xfs_inode_t *ip; |
3507 | vnode_t *vp; | 3507 | bhv_vnode_t *vp; |
3508 | 3508 | ||
3509 | again: | 3509 | again: |
3510 | XFS_MOUNT_ILOCK(mp); | 3510 | XFS_MOUNT_ILOCK(mp); |
@@ -4180,7 +4180,7 @@ xfs_iext_direct_to_inline( | |||
4180 | */ | 4180 | */ |
4181 | memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, | 4181 | memcpy(ifp->if_u2.if_inline_ext, ifp->if_u1.if_extents, |
4182 | nextents * sizeof(xfs_bmbt_rec_t)); | 4182 | nextents * sizeof(xfs_bmbt_rec_t)); |
4183 | kmem_free(ifp->if_u1.if_extents, KM_SLEEP); | 4183 | kmem_free(ifp->if_u1.if_extents, ifp->if_real_bytes); |
4184 | ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; | 4184 | ifp->if_u1.if_extents = ifp->if_u2.if_inline_ext; |
4185 | ifp->if_real_bytes = 0; | 4185 | ifp->if_real_bytes = 0; |
4186 | } | 4186 | } |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 3b544db1790b..d10b76ed1e5b 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -102,9 +102,9 @@ typedef struct xfs_ifork { | |||
102 | 102 | ||
103 | #ifdef __KERNEL__ | 103 | #ifdef __KERNEL__ |
104 | struct bhv_desc; | 104 | struct bhv_desc; |
105 | struct bhv_vnode; | ||
105 | struct cred; | 106 | struct cred; |
106 | struct ktrace; | 107 | struct ktrace; |
107 | struct vnode; | ||
108 | struct xfs_buf; | 108 | struct xfs_buf; |
109 | struct xfs_bmap_free; | 109 | struct xfs_bmap_free; |
110 | struct xfs_bmbt_irec; | 110 | struct xfs_bmbt_irec; |
@@ -400,7 +400,7 @@ void xfs_chash_init(struct xfs_mount *); | |||
400 | void xfs_chash_free(struct xfs_mount *); | 400 | void xfs_chash_free(struct xfs_mount *); |
401 | xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t, | 401 | xfs_inode_t *xfs_inode_incore(struct xfs_mount *, xfs_ino_t, |
402 | struct xfs_trans *); | 402 | struct xfs_trans *); |
403 | void xfs_inode_lock_init(xfs_inode_t *, struct vnode *); | 403 | void xfs_inode_lock_init(xfs_inode_t *, struct bhv_vnode *); |
404 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, | 404 | int xfs_iget(struct xfs_mount *, struct xfs_trans *, xfs_ino_t, |
405 | uint, uint, xfs_inode_t **, xfs_daddr_t); | 405 | uint, uint, xfs_inode_t **, xfs_daddr_t); |
406 | void xfs_iput(xfs_inode_t *, uint); | 406 | void xfs_iput(xfs_inode_t *, uint); |
@@ -461,7 +461,7 @@ void xfs_ichgtime(xfs_inode_t *, int); | |||
461 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); | 461 | xfs_fsize_t xfs_file_last_byte(xfs_inode_t *); |
462 | void xfs_lock_inodes(xfs_inode_t **, int, int, uint); | 462 | void xfs_lock_inodes(xfs_inode_t **, int, int, uint); |
463 | 463 | ||
464 | xfs_inode_t *xfs_vtoi(struct vnode *vp); | 464 | xfs_inode_t *xfs_vtoi(struct bhv_vnode *vp); |
465 | 465 | ||
466 | void xfs_synchronize_atime(xfs_inode_t *); | 466 | void xfs_synchronize_atime(xfs_inode_t *); |
467 | 467 | ||
@@ -509,7 +509,6 @@ extern struct kmem_zone *xfs_chashlist_zone; | |||
509 | extern struct kmem_zone *xfs_ifork_zone; | 509 | extern struct kmem_zone *xfs_ifork_zone; |
510 | extern struct kmem_zone *xfs_inode_zone; | 510 | extern struct kmem_zone *xfs_inode_zone; |
511 | extern struct kmem_zone *xfs_ili_zone; | 511 | extern struct kmem_zone *xfs_ili_zone; |
512 | extern struct vnodeops xfs_vnodeops; | ||
513 | 512 | ||
514 | #endif /* __KERNEL__ */ | 513 | #endif /* __KERNEL__ */ |
515 | 514 | ||
diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 7497a481b2f5..f8e80d8e7237 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "xfs_buf_item.h" | 25 | #include "xfs_buf_item.h" |
26 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
27 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
28 | #include "xfs_dir.h" | ||
29 | #include "xfs_dir2.h" | 28 | #include "xfs_dir2.h" |
30 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
31 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
@@ -33,7 +32,6 @@ | |||
33 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
39 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
@@ -794,7 +792,7 @@ xfs_inode_item_pushbuf( | |||
794 | * inode flush completed and the inode was taken off the AIL. | 792 | * inode flush completed and the inode was taken off the AIL. |
795 | * So, just get out. | 793 | * So, just get out. |
796 | */ | 794 | */ |
797 | if ((valusema(&(ip->i_flock)) > 0) || | 795 | if (!issemalocked(&(ip->i_flock)) || |
798 | ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { | 796 | ((iip->ili_item.li_flags & XFS_LI_IN_AIL) == 0)) { |
799 | iip->ili_pushbuf_flag = 0; | 797 | iip->ili_pushbuf_flag = 0; |
800 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 798 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
@@ -816,7 +814,7 @@ xfs_inode_item_pushbuf( | |||
816 | * If not, we can flush it async. | 814 | * If not, we can flush it async. |
817 | */ | 815 | */ |
818 | dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && | 816 | dopush = ((iip->ili_item.li_flags & XFS_LI_IN_AIL) && |
819 | (valusema(&(ip->i_flock)) <= 0)); | 817 | issemalocked(&(ip->i_flock))); |
820 | iip->ili_pushbuf_flag = 0; | 818 | iip->ili_pushbuf_flag = 0; |
821 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 819 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
822 | xfs_buftrace("INODE ITEM PUSH", bp); | 820 | xfs_buftrace("INODE ITEM PUSH", bp); |
@@ -864,7 +862,7 @@ xfs_inode_item_push( | |||
864 | ip = iip->ili_inode; | 862 | ip = iip->ili_inode; |
865 | 863 | ||
866 | ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS)); | 864 | ASSERT(ismrlocked(&(ip->i_lock), MR_ACCESS)); |
867 | ASSERT(valusema(&(ip->i_flock)) <= 0); | 865 | ASSERT(issemalocked(&(ip->i_flock))); |
868 | /* | 866 | /* |
869 | * Since we were able to lock the inode's flush lock and | 867 | * Since we were able to lock the inode's flush lock and |
870 | * we found it on the AIL, the inode must be dirty. This | 868 | * we found it on the AIL, the inode must be dirty. This |
@@ -1084,3 +1082,52 @@ xfs_istale_done( | |||
1084 | { | 1082 | { |
1085 | xfs_iflush_abort(iip->ili_inode); | 1083 | xfs_iflush_abort(iip->ili_inode); |
1086 | } | 1084 | } |
1085 | |||
1086 | /* | ||
1087 | * convert an xfs_inode_log_format struct from either 32 or 64 bit versions | ||
1088 | * (which can have different field alignments) to the native version | ||
1089 | */ | ||
1090 | int | ||
1091 | xfs_inode_item_format_convert( | ||
1092 | xfs_log_iovec_t *buf, | ||
1093 | xfs_inode_log_format_t *in_f) | ||
1094 | { | ||
1095 | if (buf->i_len == sizeof(xfs_inode_log_format_32_t)) { | ||
1096 | xfs_inode_log_format_32_t *in_f32; | ||
1097 | |||
1098 | in_f32 = (xfs_inode_log_format_32_t *)buf->i_addr; | ||
1099 | in_f->ilf_type = in_f32->ilf_type; | ||
1100 | in_f->ilf_size = in_f32->ilf_size; | ||
1101 | in_f->ilf_fields = in_f32->ilf_fields; | ||
1102 | in_f->ilf_asize = in_f32->ilf_asize; | ||
1103 | in_f->ilf_dsize = in_f32->ilf_dsize; | ||
1104 | in_f->ilf_ino = in_f32->ilf_ino; | ||
1105 | /* copy biggest field of ilf_u */ | ||
1106 | memcpy(in_f->ilf_u.ilfu_uuid.__u_bits, | ||
1107 | in_f32->ilf_u.ilfu_uuid.__u_bits, | ||
1108 | sizeof(uuid_t)); | ||
1109 | in_f->ilf_blkno = in_f32->ilf_blkno; | ||
1110 | in_f->ilf_len = in_f32->ilf_len; | ||
1111 | in_f->ilf_boffset = in_f32->ilf_boffset; | ||
1112 | return 0; | ||
1113 | } else if (buf->i_len == sizeof(xfs_inode_log_format_64_t)){ | ||
1114 | xfs_inode_log_format_64_t *in_f64; | ||
1115 | |||
1116 | in_f64 = (xfs_inode_log_format_64_t *)buf->i_addr; | ||
1117 | in_f->ilf_type = in_f64->ilf_type; | ||
1118 | in_f->ilf_size = in_f64->ilf_size; | ||
1119 | in_f->ilf_fields = in_f64->ilf_fields; | ||
1120 | in_f->ilf_asize = in_f64->ilf_asize; | ||
1121 | in_f->ilf_dsize = in_f64->ilf_dsize; | ||
1122 | in_f->ilf_ino = in_f64->ilf_ino; | ||
1123 | /* copy biggest field of ilf_u */ | ||
1124 | memcpy(in_f->ilf_u.ilfu_uuid.__u_bits, | ||
1125 | in_f64->ilf_u.ilfu_uuid.__u_bits, | ||
1126 | sizeof(uuid_t)); | ||
1127 | in_f->ilf_blkno = in_f64->ilf_blkno; | ||
1128 | in_f->ilf_len = in_f64->ilf_len; | ||
1129 | in_f->ilf_boffset = in_f64->ilf_boffset; | ||
1130 | return 0; | ||
1131 | } | ||
1132 | return EFSCORRUPTED; | ||
1133 | } | ||
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h index c5dbf93b6661..5db6cd1b4cf3 100644 --- a/fs/xfs/xfs_inode_item.h +++ b/fs/xfs/xfs_inode_item.h | |||
@@ -23,25 +23,6 @@ | |||
23 | * log. The size of the inline data/extents/b-tree root to be logged | 23 | * log. The size of the inline data/extents/b-tree root to be logged |
24 | * (if any) is indicated in the ilf_dsize field. Changes to this structure | 24 | * (if any) is indicated in the ilf_dsize field. Changes to this structure |
25 | * must be added on to the end. | 25 | * must be added on to the end. |
26 | * | ||
27 | * Convention for naming inode log item versions : The current version | ||
28 | * is always named XFS_LI_INODE. When an inode log item gets superseded, | ||
29 | * add the latest version of IRIX that will generate logs with that item | ||
30 | * to the version name. | ||
31 | * | ||
32 | * -Version 1 of this structure (XFS_LI_5_3_INODE) included up to the first | ||
33 | * union (ilf_u) field. This was released with IRIX 5.3-XFS. | ||
34 | * -Version 2 of this structure (XFS_LI_6_1_INODE) is currently the entire | ||
35 | * structure. This was released with IRIX 6.0.1-XFS and IRIX 6.1. | ||
36 | * -Version 3 of this structure (XFS_LI_INODE) is the same as version 2 | ||
37 | * so a new structure definition wasn't necessary. However, we had | ||
38 | * to add a new type because the inode cluster size changed from 4K | ||
39 | * to 8K and the version number had to be rev'ved to keep older kernels | ||
40 | * from trying to recover logs with the 8K buffers in them. The logging | ||
41 | * code can handle recovery on different-sized clusters now so hopefully | ||
42 | * this'll be the last time we need to change the inode log item just | ||
43 | * for a change in the inode cluster size. This new version was | ||
44 | * released with IRIX 6.2. | ||
45 | */ | 26 | */ |
46 | typedef struct xfs_inode_log_format { | 27 | typedef struct xfs_inode_log_format { |
47 | unsigned short ilf_type; /* inode log item type */ | 28 | unsigned short ilf_type; /* inode log item type */ |
@@ -59,18 +40,38 @@ typedef struct xfs_inode_log_format { | |||
59 | int ilf_boffset; /* off of inode in buffer */ | 40 | int ilf_boffset; /* off of inode in buffer */ |
60 | } xfs_inode_log_format_t; | 41 | } xfs_inode_log_format_t; |
61 | 42 | ||
62 | /* Initial version shipped with IRIX 5.3-XFS */ | 43 | typedef struct xfs_inode_log_format_32 { |
63 | typedef struct xfs_inode_log_format_v1 { | 44 | unsigned short ilf_type; /* 16: inode log item type */ |
64 | unsigned short ilf_type; /* inode log item type */ | 45 | unsigned short ilf_size; /* 16: size of this item */ |
65 | unsigned short ilf_size; /* size of this item */ | 46 | uint ilf_fields; /* 32: flags for fields logged */ |
66 | uint ilf_fields; /* flags for fields logged */ | 47 | ushort ilf_asize; /* 32: size of attr d/ext/root */ |
67 | uint ilf_dsize; /* size of data/ext/root */ | 48 | ushort ilf_dsize; /* 32: size of data/ext/root */ |
68 | xfs_ino_t ilf_ino; /* inode number */ | 49 | xfs_ino_t ilf_ino; /* 64: inode number */ |
69 | union { | 50 | union { |
70 | xfs_dev_t ilfu_rdev; /* rdev value for dev inode*/ | 51 | xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/ |
71 | uuid_t ilfu_uuid; /* mount point value */ | 52 | uuid_t ilfu_uuid; /* 128: mount point value */ |
53 | } ilf_u; | ||
54 | __int64_t ilf_blkno; /* 64: blkno of inode buffer */ | ||
55 | int ilf_len; /* 32: len of inode buffer */ | ||
56 | int ilf_boffset; /* 32: off of inode in buffer */ | ||
57 | } __attribute__((packed)) xfs_inode_log_format_32_t; | ||
58 | |||
59 | typedef struct xfs_inode_log_format_64 { | ||
60 | unsigned short ilf_type; /* 16: inode log item type */ | ||
61 | unsigned short ilf_size; /* 16: size of this item */ | ||
62 | uint ilf_fields; /* 32: flags for fields logged */ | ||
63 | ushort ilf_asize; /* 32: size of attr d/ext/root */ | ||
64 | ushort ilf_dsize; /* 32: size of data/ext/root */ | ||
65 | __uint32_t ilf_pad; /* 32: pad for 64 bit boundary */ | ||
66 | xfs_ino_t ilf_ino; /* 64: inode number */ | ||
67 | union { | ||
68 | xfs_dev_t ilfu_rdev; /* 32: rdev value for dev inode*/ | ||
69 | uuid_t ilfu_uuid; /* 128: mount point value */ | ||
72 | } ilf_u; | 70 | } ilf_u; |
73 | } xfs_inode_log_format_t_v1; | 71 | __int64_t ilf_blkno; /* 64: blkno of inode buffer */ |
72 | int ilf_len; /* 32: len of inode buffer */ | ||
73 | int ilf_boffset; /* 32: off of inode in buffer */ | ||
74 | } xfs_inode_log_format_64_t; | ||
74 | 75 | ||
75 | /* | 76 | /* |
76 | * Flags for xfs_trans_log_inode flags field. | 77 | * Flags for xfs_trans_log_inode flags field. |
@@ -172,6 +173,8 @@ extern void xfs_inode_item_destroy(struct xfs_inode *); | |||
172 | extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); | 173 | extern void xfs_iflush_done(struct xfs_buf *, xfs_inode_log_item_t *); |
173 | extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); | 174 | extern void xfs_istale_done(struct xfs_buf *, xfs_inode_log_item_t *); |
174 | extern void xfs_iflush_abort(struct xfs_inode *); | 175 | extern void xfs_iflush_abort(struct xfs_inode *); |
176 | extern int xfs_inode_item_format_convert(xfs_log_iovec_t *, | ||
177 | xfs_inode_log_format_t *); | ||
175 | 178 | ||
176 | #endif /* __KERNEL__ */ | 179 | #endif /* __KERNEL__ */ |
177 | 180 | ||
diff --git a/fs/xfs/xfs_iocore.c b/fs/xfs/xfs_iocore.c index a07815661a8c..06d710c9ce4b 100644 --- a/fs/xfs/xfs_iocore.c +++ b/fs/xfs/xfs_iocore.c | |||
@@ -24,14 +24,13 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
28 | #include "xfs_dfrag.h" | ||
29 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -58,7 +57,7 @@ xfs_size_fn( | |||
58 | 57 | ||
59 | STATIC int | 58 | STATIC int |
60 | xfs_ioinit( | 59 | xfs_ioinit( |
61 | struct vfs *vfsp, | 60 | struct bhv_vfs *vfsp, |
62 | struct xfs_mount_args *mntargs, | 61 | struct xfs_mount_args *mntargs, |
63 | int flags) | 62 | int flags) |
64 | { | 63 | { |
@@ -68,6 +67,7 @@ xfs_ioinit( | |||
68 | xfs_ioops_t xfs_iocore_xfs = { | 67 | xfs_ioops_t xfs_iocore_xfs = { |
69 | .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit, | 68 | .xfs_ioinit = (xfs_ioinit_t) xfs_ioinit, |
70 | .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi, | 69 | .xfs_bmapi_func = (xfs_bmapi_t) xfs_bmapi, |
70 | .xfs_bunmapi_func = (xfs_bunmapi_t) xfs_bunmapi, | ||
71 | .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof, | 71 | .xfs_bmap_eof_func = (xfs_bmap_eof_t) xfs_bmap_eof, |
72 | .xfs_iomap_write_direct = | 72 | .xfs_iomap_write_direct = |
73 | (xfs_iomap_write_direct_t) xfs_iomap_write_direct, | 73 | (xfs_iomap_write_direct_t) xfs_iomap_write_direct, |
@@ -84,6 +84,7 @@ xfs_ioops_t xfs_iocore_xfs = { | |||
84 | .xfs_unlock = (xfs_unlk_t) xfs_iunlock, | 84 | .xfs_unlock = (xfs_unlk_t) xfs_iunlock, |
85 | .xfs_size_func = (xfs_size_t) xfs_size_fn, | 85 | .xfs_size_func = (xfs_size_t) xfs_size_fn, |
86 | .xfs_iodone = (xfs_iodone_t) fs_noerr, | 86 | .xfs_iodone = (xfs_iodone_t) fs_noerr, |
87 | .xfs_swap_extents_func = (xfs_swap_extents_t) xfs_swap_extents, | ||
87 | }; | 88 | }; |
88 | 89 | ||
89 | void | 90 | void |
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c index d5dfedcb8922..f1949c16df15 100644 --- a/fs/xfs/xfs_iomap.c +++ b/fs/xfs/xfs_iomap.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_alloc.h" | 27 | #include "xfs_alloc.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -252,7 +250,7 @@ xfs_iomap( | |||
252 | error = XFS_BMAPI(mp, NULL, io, offset_fsb, | 250 | error = XFS_BMAPI(mp, NULL, io, offset_fsb, |
253 | (xfs_filblks_t)(end_fsb - offset_fsb), | 251 | (xfs_filblks_t)(end_fsb - offset_fsb), |
254 | bmapi_flags, NULL, 0, &imap, | 252 | bmapi_flags, NULL, 0, &imap, |
255 | &nimaps, NULL); | 253 | &nimaps, NULL, NULL); |
256 | 254 | ||
257 | if (error) | 255 | if (error) |
258 | goto out; | 256 | goto out; |
@@ -519,8 +517,8 @@ xfs_iomap_write_direct( | |||
519 | */ | 517 | */ |
520 | XFS_BMAP_INIT(&free_list, &firstfsb); | 518 | XFS_BMAP_INIT(&free_list, &firstfsb); |
521 | nimaps = 1; | 519 | nimaps = 1; |
522 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 520 | error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, bmapi_flag, |
523 | bmapi_flag, &firstfsb, 0, &imap, &nimaps, &free_list); | 521 | &firstfsb, 0, &imap, &nimaps, &free_list, NULL); |
524 | if (error) | 522 | if (error) |
525 | goto error0; | 523 | goto error0; |
526 | 524 | ||
@@ -610,8 +608,8 @@ xfs_iomap_eof_want_preallocate( | |||
610 | while (count_fsb > 0) { | 608 | while (count_fsb > 0) { |
611 | imaps = nimaps; | 609 | imaps = nimaps; |
612 | firstblock = NULLFSBLOCK; | 610 | firstblock = NULLFSBLOCK; |
613 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, | 611 | error = XFS_BMAPI(mp, NULL, io, start_fsb, count_fsb, 0, |
614 | 0, &firstblock, 0, imap, &imaps, NULL); | 612 | &firstblock, 0, imap, &imaps, NULL, NULL); |
615 | if (error) | 613 | if (error) |
616 | return error; | 614 | return error; |
617 | for (n = 0; n < imaps; n++) { | 615 | for (n = 0; n < imaps; n++) { |
@@ -695,11 +693,11 @@ retry: | |||
695 | 693 | ||
696 | nimaps = XFS_WRITE_IMAPS; | 694 | nimaps = XFS_WRITE_IMAPS; |
697 | firstblock = NULLFSBLOCK; | 695 | firstblock = NULLFSBLOCK; |
698 | error = xfs_bmapi(NULL, ip, offset_fsb, | 696 | error = XFS_BMAPI(mp, NULL, io, offset_fsb, |
699 | (xfs_filblks_t)(last_fsb - offset_fsb), | 697 | (xfs_filblks_t)(last_fsb - offset_fsb), |
700 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | | 698 | XFS_BMAPI_DELAY | XFS_BMAPI_WRITE | |
701 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, | 699 | XFS_BMAPI_ENTIRE, &firstblock, 1, imap, |
702 | &nimaps, NULL); | 700 | &nimaps, NULL, NULL); |
703 | if (error && (error != ENOSPC)) | 701 | if (error && (error != ENOSPC)) |
704 | return XFS_ERROR(error); | 702 | return XFS_ERROR(error); |
705 | 703 | ||
@@ -832,9 +830,9 @@ xfs_iomap_write_allocate( | |||
832 | } | 830 | } |
833 | 831 | ||
834 | /* Go get the actual blocks */ | 832 | /* Go get the actual blocks */ |
835 | error = xfs_bmapi(tp, ip, map_start_fsb, count_fsb, | 833 | error = XFS_BMAPI(mp, tp, io, map_start_fsb, count_fsb, |
836 | XFS_BMAPI_WRITE, &first_block, 1, | 834 | XFS_BMAPI_WRITE, &first_block, 1, |
837 | imap, &nimaps, &free_list); | 835 | imap, &nimaps, &free_list, NULL); |
838 | if (error) | 836 | if (error) |
839 | goto trans_cancel; | 837 | goto trans_cancel; |
840 | 838 | ||
@@ -955,9 +953,9 @@ xfs_iomap_write_unwritten( | |||
955 | */ | 953 | */ |
956 | XFS_BMAP_INIT(&free_list, &firstfsb); | 954 | XFS_BMAP_INIT(&free_list, &firstfsb); |
957 | nimaps = 1; | 955 | nimaps = 1; |
958 | error = xfs_bmapi(tp, ip, offset_fsb, count_fsb, | 956 | error = XFS_BMAPI(mp, tp, io, offset_fsb, count_fsb, |
959 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, | 957 | XFS_BMAPI_WRITE|XFS_BMAPI_CONVERT, &firstfsb, |
960 | 1, &imap, &nimaps, &free_list); | 958 | 1, &imap, &nimaps, &free_list, NULL); |
961 | if (error) | 959 | if (error) |
962 | goto error_on_bmapi_transaction; | 960 | goto error_on_bmapi_transaction; |
963 | 961 | ||
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index 94068d014f27..46249e4d1fea 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -41,11 +39,6 @@ | |||
41 | #include "xfs_error.h" | 39 | #include "xfs_error.h" |
42 | #include "xfs_btree.h" | 40 | #include "xfs_btree.h" |
43 | 41 | ||
44 | #ifndef HAVE_USERACC | ||
45 | #define useracc(ubuffer, size, flags, foo) (0) | ||
46 | #define unuseracc(ubuffer, size, flags) | ||
47 | #endif | ||
48 | |||
49 | STATIC int | 42 | STATIC int |
50 | xfs_bulkstat_one_iget( | 43 | xfs_bulkstat_one_iget( |
51 | xfs_mount_t *mp, /* mount point for filesystem */ | 44 | xfs_mount_t *mp, /* mount point for filesystem */ |
@@ -56,7 +49,7 @@ xfs_bulkstat_one_iget( | |||
56 | { | 49 | { |
57 | xfs_dinode_core_t *dic; /* dinode core info pointer */ | 50 | xfs_dinode_core_t *dic; /* dinode core info pointer */ |
58 | xfs_inode_t *ip; /* incore inode pointer */ | 51 | xfs_inode_t *ip; /* incore inode pointer */ |
59 | vnode_t *vp; | 52 | bhv_vnode_t *vp; |
60 | int error; | 53 | int error; |
61 | 54 | ||
62 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); | 55 | error = xfs_iget(mp, NULL, ino, 0, XFS_ILOCK_SHARED, &ip, bno); |
@@ -336,15 +329,6 @@ xfs_bulkstat( | |||
336 | nimask = ~(nicluster - 1); | 329 | nimask = ~(nicluster - 1); |
337 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; | 330 | nbcluster = nicluster >> mp->m_sb.sb_inopblog; |
338 | /* | 331 | /* |
339 | * Lock down the user's buffer. If a buffer was not sent, as in the case | ||
340 | * disk quota code calls here, we skip this. | ||
341 | */ | ||
342 | if (ubuffer && | ||
343 | (error = useracc(ubuffer, ubcount * statstruct_size, | ||
344 | (B_READ|B_PHYS), NULL))) { | ||
345 | return error; | ||
346 | } | ||
347 | /* | ||
348 | * Allocate a page-sized buffer for inode btree records. | 332 | * Allocate a page-sized buffer for inode btree records. |
349 | * We could try allocating something smaller, but for normal | 333 | * We could try allocating something smaller, but for normal |
350 | * calls we'll always (potentially) need the whole page. | 334 | * calls we'll always (potentially) need the whole page. |
@@ -650,8 +634,6 @@ xfs_bulkstat( | |||
650 | * Done, we're either out of filesystem or space to put the data. | 634 | * Done, we're either out of filesystem or space to put the data. |
651 | */ | 635 | */ |
652 | kmem_free(irbuf, NBPC); | 636 | kmem_free(irbuf, NBPC); |
653 | if (ubuffer) | ||
654 | unuseracc(ubuffer, ubcount * statstruct_size, (B_READ|B_PHYS)); | ||
655 | *ubcountp = ubelem; | 637 | *ubcountp = ubelem; |
656 | if (agno >= mp->m_sb.sb_agcount) { | 638 | if (agno >= mp->m_sb.sb_agcount) { |
657 | /* | 639 | /* |
diff --git a/fs/xfs/xfs_itable.h b/fs/xfs/xfs_itable.h index 11eb4e1b18c4..be5f12e07d22 100644 --- a/fs/xfs/xfs_itable.h +++ b/fs/xfs/xfs_itable.h | |||
@@ -45,7 +45,6 @@ typedef int (*bulkstat_one_pf)(struct xfs_mount *mp, | |||
45 | */ | 45 | */ |
46 | #define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ | 46 | #define BULKSTAT_FG_IGET 0x1 /* Go through the buffer cache */ |
47 | #define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ | 47 | #define BULKSTAT_FG_QUICK 0x2 /* No iget, walk the dinode cluster */ |
48 | #define BULKSTAT_FG_VFSLOCKED 0x4 /* Already have vfs lock */ | ||
49 | 48 | ||
50 | /* | 49 | /* |
51 | * Return stat information in bulk (by-inode) for the filesystem. | 50 | * Return stat information in bulk (by-inode) for the filesystem. |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 32e841d2f26d..d8f5d4cbe8b7 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -36,7 +35,6 @@ | |||
36 | #include "xfs_ialloc_btree.h" | 35 | #include "xfs_ialloc_btree.h" |
37 | #include "xfs_log_recover.h" | 36 | #include "xfs_log_recover.h" |
38 | #include "xfs_trans_priv.h" | 37 | #include "xfs_trans_priv.h" |
39 | #include "xfs_dir_sf.h" | ||
40 | #include "xfs_dir2_sf.h" | 38 | #include "xfs_dir2_sf.h" |
41 | #include "xfs_attr_sf.h" | 39 | #include "xfs_attr_sf.h" |
42 | #include "xfs_dinode.h" | 40 | #include "xfs_dinode.h" |
@@ -402,7 +400,7 @@ xfs_log_release_iclog(xfs_mount_t *mp, | |||
402 | xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; | 400 | xlog_in_core_t *iclog = (xlog_in_core_t *)iclog_hndl; |
403 | 401 | ||
404 | if (xlog_state_release_iclog(log, iclog)) { | 402 | if (xlog_state_release_iclog(log, iclog)) { |
405 | xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); | 403 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
406 | return EIO; | 404 | return EIO; |
407 | } | 405 | } |
408 | 406 | ||
@@ -498,9 +496,8 @@ xfs_log_mount(xfs_mount_t *mp, | |||
498 | * just worked. | 496 | * just worked. |
499 | */ | 497 | */ |
500 | if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { | 498 | if (!(mp->m_flags & XFS_MOUNT_NORECOVERY)) { |
501 | int error; | 499 | bhv_vfs_t *vfsp = XFS_MTOVFS(mp); |
502 | vfs_t *vfsp = XFS_MTOVFS(mp); | 500 | int error, readonly = (vfsp->vfs_flag & VFS_RDONLY); |
503 | int readonly = (vfsp->vfs_flag & VFS_RDONLY); | ||
504 | 501 | ||
505 | if (readonly) | 502 | if (readonly) |
506 | vfsp->vfs_flag &= ~VFS_RDONLY; | 503 | vfsp->vfs_flag &= ~VFS_RDONLY; |
@@ -726,7 +723,7 @@ xfs_log_write(xfs_mount_t * mp, | |||
726 | return XFS_ERROR(EIO); | 723 | return XFS_ERROR(EIO); |
727 | 724 | ||
728 | if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { | 725 | if ((error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0))) { |
729 | xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); | 726 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
730 | } | 727 | } |
731 | return error; | 728 | return error; |
732 | } /* xfs_log_write */ | 729 | } /* xfs_log_write */ |
@@ -816,9 +813,9 @@ xfs_log_need_covered(xfs_mount_t *mp) | |||
816 | SPLDECL(s); | 813 | SPLDECL(s); |
817 | int needed = 0, gen; | 814 | int needed = 0, gen; |
818 | xlog_t *log = mp->m_log; | 815 | xlog_t *log = mp->m_log; |
819 | vfs_t *vfsp = XFS_MTOVFS(mp); | 816 | bhv_vfs_t *vfsp = XFS_MTOVFS(mp); |
820 | 817 | ||
821 | if (fs_frozen(vfsp) || XFS_FORCED_SHUTDOWN(mp) || | 818 | if (vfs_test_for_freeze(vfsp) || XFS_FORCED_SHUTDOWN(mp) || |
822 | (vfsp->vfs_flag & VFS_RDONLY)) | 819 | (vfsp->vfs_flag & VFS_RDONLY)) |
823 | return 0; | 820 | return 0; |
824 | 821 | ||
@@ -956,7 +953,7 @@ xlog_iodone(xfs_buf_t *bp) | |||
956 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { | 953 | XFS_ERRTAG_IODONE_IOERR, XFS_RANDOM_IODONE_IOERR)) { |
957 | xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp)); | 954 | xfs_ioerror_alert("xlog_iodone", l->l_mp, bp, XFS_BUF_ADDR(bp)); |
958 | XFS_BUF_STALE(bp); | 955 | XFS_BUF_STALE(bp); |
959 | xfs_force_shutdown(l->l_mp, XFS_LOG_IO_ERROR); | 956 | xfs_force_shutdown(l->l_mp, SHUTDOWN_LOG_IO_ERROR); |
960 | /* | 957 | /* |
961 | * This flag will be propagated to the trans-committed | 958 | * This flag will be propagated to the trans-committed |
962 | * callback routines to let them know that the log-commit | 959 | * callback routines to let them know that the log-commit |
@@ -1261,7 +1258,7 @@ xlog_commit_record(xfs_mount_t *mp, | |||
1261 | ASSERT_ALWAYS(iclog); | 1258 | ASSERT_ALWAYS(iclog); |
1262 | if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, | 1259 | if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, |
1263 | iclog, XLOG_COMMIT_TRANS))) { | 1260 | iclog, XLOG_COMMIT_TRANS))) { |
1264 | xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); | 1261 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1265 | } | 1262 | } |
1266 | return error; | 1263 | return error; |
1267 | } /* xlog_commit_record */ | 1264 | } /* xlog_commit_record */ |
@@ -1790,7 +1787,7 @@ xlog_write(xfs_mount_t * mp, | |||
1790 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | 1787 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, |
1791 | "xfs_log_write: reservation ran out. Need to up reservation"); | 1788 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1792 | /* If we did not panic, shutdown the filesystem */ | 1789 | /* If we did not panic, shutdown the filesystem */ |
1793 | xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); | 1790 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
1794 | #endif | 1791 | #endif |
1795 | } else | 1792 | } else |
1796 | ticket->t_curr_res -= len; | 1793 | ticket->t_curr_res -= len; |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 1f0016b0b4ec..55b4237c2153 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_alloc_btree.h" | 32 | #include "xfs_alloc_btree.h" |
34 | #include "xfs_ialloc_btree.h" | 33 | #include "xfs_ialloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -193,14 +191,14 @@ xlog_header_check_dump( | |||
193 | { | 191 | { |
194 | int b; | 192 | int b; |
195 | 193 | ||
196 | printk("%s: SB : uuid = ", __FUNCTION__); | 194 | cmn_err(CE_DEBUG, "%s: SB : uuid = ", __FUNCTION__); |
197 | for (b = 0; b < 16; b++) | 195 | for (b = 0; b < 16; b++) |
198 | printk("%02x",((unsigned char *)&mp->m_sb.sb_uuid)[b]); | 196 | cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]); |
199 | printk(", fmt = %d\n", XLOG_FMT); | 197 | cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); |
200 | printk(" log : uuid = "); | 198 | cmn_err(CE_DEBUG, " log : uuid = "); |
201 | for (b = 0; b < 16; b++) | 199 | for (b = 0; b < 16; b++) |
202 | printk("%02x",((unsigned char *)&head->h_fs_uuid)[b]); | 200 | cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]); |
203 | printk(", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); | 201 | cmn_err(CE_DEBUG, ", fmt = %d\n", INT_GET(head->h_fmt, ARCH_CONVERT)); |
204 | } | 202 | } |
205 | #else | 203 | #else |
206 | #define xlog_header_check_dump(mp, head) | 204 | #define xlog_header_check_dump(mp, head) |
@@ -282,7 +280,7 @@ xlog_recover_iodone( | |||
282 | mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *); | 280 | mp = XFS_BUF_FSPRIVATE(bp, xfs_mount_t *); |
283 | xfs_ioerror_alert("xlog_recover_iodone", | 281 | xfs_ioerror_alert("xlog_recover_iodone", |
284 | mp, bp, XFS_BUF_ADDR(bp)); | 282 | mp, bp, XFS_BUF_ADDR(bp)); |
285 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 283 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
286 | } | 284 | } |
287 | XFS_BUF_SET_FSPRIVATE(bp, NULL); | 285 | XFS_BUF_SET_FSPRIVATE(bp, NULL); |
288 | XFS_BUF_CLR_IODONE_FUNC(bp); | 286 | XFS_BUF_CLR_IODONE_FUNC(bp); |
@@ -1889,7 +1887,7 @@ xlog_recover_do_inode_buffer( | |||
1889 | 1887 | ||
1890 | buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp, | 1888 | buffer_nextp = (xfs_agino_t *)xfs_buf_offset(bp, |
1891 | next_unlinked_offset); | 1889 | next_unlinked_offset); |
1892 | INT_SET(*buffer_nextp, ARCH_CONVERT, *logged_nextp); | 1890 | *buffer_nextp = *logged_nextp; |
1893 | } | 1891 | } |
1894 | 1892 | ||
1895 | return 0; | 1893 | return 0; |
@@ -2292,12 +2290,22 @@ xlog_recover_do_inode_trans( | |||
2292 | int attr_index; | 2290 | int attr_index; |
2293 | uint fields; | 2291 | uint fields; |
2294 | xfs_dinode_core_t *dicp; | 2292 | xfs_dinode_core_t *dicp; |
2293 | int need_free = 0; | ||
2295 | 2294 | ||
2296 | if (pass == XLOG_RECOVER_PASS1) { | 2295 | if (pass == XLOG_RECOVER_PASS1) { |
2297 | return 0; | 2296 | return 0; |
2298 | } | 2297 | } |
2299 | 2298 | ||
2300 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | 2299 | if (item->ri_buf[0].i_len == sizeof(xfs_inode_log_format_t)) { |
2300 | in_f = (xfs_inode_log_format_t *)item->ri_buf[0].i_addr; | ||
2301 | } else { | ||
2302 | in_f = (xfs_inode_log_format_t *)kmem_alloc( | ||
2303 | sizeof(xfs_inode_log_format_t), KM_SLEEP); | ||
2304 | need_free = 1; | ||
2305 | error = xfs_inode_item_format_convert(&item->ri_buf[0], in_f); | ||
2306 | if (error) | ||
2307 | goto error; | ||
2308 | } | ||
2301 | ino = in_f->ilf_ino; | 2309 | ino = in_f->ilf_ino; |
2302 | mp = log->l_mp; | 2310 | mp = log->l_mp; |
2303 | if (ITEM_TYPE(item) == XFS_LI_INODE) { | 2311 | if (ITEM_TYPE(item) == XFS_LI_INODE) { |
@@ -2323,8 +2331,10 @@ xlog_recover_do_inode_trans( | |||
2323 | * Inode buffers can be freed, look out for it, | 2331 | * Inode buffers can be freed, look out for it, |
2324 | * and do not replay the inode. | 2332 | * and do not replay the inode. |
2325 | */ | 2333 | */ |
2326 | if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) | 2334 | if (xlog_check_buffer_cancelled(log, imap.im_blkno, imap.im_len, 0)) { |
2327 | return 0; | 2335 | error = 0; |
2336 | goto error; | ||
2337 | } | ||
2328 | 2338 | ||
2329 | bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, | 2339 | bp = xfs_buf_read_flags(mp->m_ddev_targp, imap.im_blkno, imap.im_len, |
2330 | XFS_BUF_LOCK); | 2340 | XFS_BUF_LOCK); |
@@ -2333,7 +2343,7 @@ xlog_recover_do_inode_trans( | |||
2333 | bp, imap.im_blkno); | 2343 | bp, imap.im_blkno); |
2334 | error = XFS_BUF_GETERROR(bp); | 2344 | error = XFS_BUF_GETERROR(bp); |
2335 | xfs_buf_relse(bp); | 2345 | xfs_buf_relse(bp); |
2336 | return error; | 2346 | goto error; |
2337 | } | 2347 | } |
2338 | error = 0; | 2348 | error = 0; |
2339 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); | 2349 | ASSERT(in_f->ilf_fields & XFS_ILOG_CORE); |
@@ -2350,7 +2360,8 @@ xlog_recover_do_inode_trans( | |||
2350 | dip, bp, ino); | 2360 | dip, bp, ino); |
2351 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", | 2361 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(1)", |
2352 | XFS_ERRLEVEL_LOW, mp); | 2362 | XFS_ERRLEVEL_LOW, mp); |
2353 | return XFS_ERROR(EFSCORRUPTED); | 2363 | error = EFSCORRUPTED; |
2364 | goto error; | ||
2354 | } | 2365 | } |
2355 | dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); | 2366 | dicp = (xfs_dinode_core_t*)(item->ri_buf[1].i_addr); |
2356 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { | 2367 | if (unlikely(dicp->di_magic != XFS_DINODE_MAGIC)) { |
@@ -2360,7 +2371,8 @@ xlog_recover_do_inode_trans( | |||
2360 | item, ino); | 2371 | item, ino); |
2361 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", | 2372 | XFS_ERROR_REPORT("xlog_recover_do_inode_trans(2)", |
2362 | XFS_ERRLEVEL_LOW, mp); | 2373 | XFS_ERRLEVEL_LOW, mp); |
2363 | return XFS_ERROR(EFSCORRUPTED); | 2374 | error = EFSCORRUPTED; |
2375 | goto error; | ||
2364 | } | 2376 | } |
2365 | 2377 | ||
2366 | /* Skip replay when the on disk inode is newer than the log one */ | 2378 | /* Skip replay when the on disk inode is newer than the log one */ |
@@ -2376,7 +2388,8 @@ xlog_recover_do_inode_trans( | |||
2376 | /* do nothing */ | 2388 | /* do nothing */ |
2377 | } else { | 2389 | } else { |
2378 | xfs_buf_relse(bp); | 2390 | xfs_buf_relse(bp); |
2379 | return 0; | 2391 | error = 0; |
2392 | goto error; | ||
2380 | } | 2393 | } |
2381 | } | 2394 | } |
2382 | /* Take the opportunity to reset the flush iteration count */ | 2395 | /* Take the opportunity to reset the flush iteration count */ |
@@ -2391,7 +2404,8 @@ xlog_recover_do_inode_trans( | |||
2391 | xfs_fs_cmn_err(CE_ALERT, mp, | 2404 | xfs_fs_cmn_err(CE_ALERT, mp, |
2392 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2405 | "xfs_inode_recover: Bad regular inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2393 | item, dip, bp, ino); | 2406 | item, dip, bp, ino); |
2394 | return XFS_ERROR(EFSCORRUPTED); | 2407 | error = EFSCORRUPTED; |
2408 | goto error; | ||
2395 | } | 2409 | } |
2396 | } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { | 2410 | } else if (unlikely((dicp->di_mode & S_IFMT) == S_IFDIR)) { |
2397 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && | 2411 | if ((dicp->di_format != XFS_DINODE_FMT_EXTENTS) && |
@@ -2403,7 +2417,8 @@ xlog_recover_do_inode_trans( | |||
2403 | xfs_fs_cmn_err(CE_ALERT, mp, | 2417 | xfs_fs_cmn_err(CE_ALERT, mp, |
2404 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", | 2418 | "xfs_inode_recover: Bad dir inode log record, rec ptr 0x%p, ino ptr = 0x%p, ino bp = 0x%p, ino %Ld", |
2405 | item, dip, bp, ino); | 2419 | item, dip, bp, ino); |
2406 | return XFS_ERROR(EFSCORRUPTED); | 2420 | error = EFSCORRUPTED; |
2421 | goto error; | ||
2407 | } | 2422 | } |
2408 | } | 2423 | } |
2409 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ | 2424 | if (unlikely(dicp->di_nextents + dicp->di_anextents > dicp->di_nblocks)){ |
@@ -2415,7 +2430,8 @@ xlog_recover_do_inode_trans( | |||
2415 | item, dip, bp, ino, | 2430 | item, dip, bp, ino, |
2416 | dicp->di_nextents + dicp->di_anextents, | 2431 | dicp->di_nextents + dicp->di_anextents, |
2417 | dicp->di_nblocks); | 2432 | dicp->di_nblocks); |
2418 | return XFS_ERROR(EFSCORRUPTED); | 2433 | error = EFSCORRUPTED; |
2434 | goto error; | ||
2419 | } | 2435 | } |
2420 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { | 2436 | if (unlikely(dicp->di_forkoff > mp->m_sb.sb_inodesize)) { |
2421 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", | 2437 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(6)", |
@@ -2424,7 +2440,8 @@ xlog_recover_do_inode_trans( | |||
2424 | xfs_fs_cmn_err(CE_ALERT, mp, | 2440 | xfs_fs_cmn_err(CE_ALERT, mp, |
2425 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", | 2441 | "xfs_inode_recover: Bad inode log rec ptr 0x%p, dino ptr 0x%p, dino bp 0x%p, ino %Ld, forkoff 0x%x", |
2426 | item, dip, bp, ino, dicp->di_forkoff); | 2442 | item, dip, bp, ino, dicp->di_forkoff); |
2427 | return XFS_ERROR(EFSCORRUPTED); | 2443 | error = EFSCORRUPTED; |
2444 | goto error; | ||
2428 | } | 2445 | } |
2429 | if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { | 2446 | if (unlikely(item->ri_buf[1].i_len > sizeof(xfs_dinode_core_t))) { |
2430 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", | 2447 | XFS_CORRUPTION_ERROR("xlog_recover_do_inode_trans(7)", |
@@ -2433,7 +2450,8 @@ xlog_recover_do_inode_trans( | |||
2433 | xfs_fs_cmn_err(CE_ALERT, mp, | 2450 | xfs_fs_cmn_err(CE_ALERT, mp, |
2434 | "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", | 2451 | "xfs_inode_recover: Bad inode log record length %d, rec ptr 0x%p", |
2435 | item->ri_buf[1].i_len, item); | 2452 | item->ri_buf[1].i_len, item); |
2436 | return XFS_ERROR(EFSCORRUPTED); | 2453 | error = EFSCORRUPTED; |
2454 | goto error; | ||
2437 | } | 2455 | } |
2438 | 2456 | ||
2439 | /* The core is in in-core format */ | 2457 | /* The core is in in-core format */ |
@@ -2521,7 +2539,8 @@ xlog_recover_do_inode_trans( | |||
2521 | xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); | 2539 | xlog_warn("XFS: xlog_recover_do_inode_trans: Invalid flag"); |
2522 | ASSERT(0); | 2540 | ASSERT(0); |
2523 | xfs_buf_relse(bp); | 2541 | xfs_buf_relse(bp); |
2524 | return XFS_ERROR(EIO); | 2542 | error = EIO; |
2543 | goto error; | ||
2525 | } | 2544 | } |
2526 | } | 2545 | } |
2527 | 2546 | ||
@@ -2537,7 +2556,10 @@ write_inode_buffer: | |||
2537 | error = xfs_bwrite(mp, bp); | 2556 | error = xfs_bwrite(mp, bp); |
2538 | } | 2557 | } |
2539 | 2558 | ||
2540 | return (error); | 2559 | error: |
2560 | if (need_free) | ||
2561 | kmem_free(in_f, sizeof(*in_f)); | ||
2562 | return XFS_ERROR(error); | ||
2541 | } | 2563 | } |
2542 | 2564 | ||
2543 | /* | 2565 | /* |
@@ -2674,32 +2696,32 @@ xlog_recover_do_dquot_trans( | |||
2674 | * structure into it, and adds the efi to the AIL with the given | 2696 | * structure into it, and adds the efi to the AIL with the given |
2675 | * LSN. | 2697 | * LSN. |
2676 | */ | 2698 | */ |
2677 | STATIC void | 2699 | STATIC int |
2678 | xlog_recover_do_efi_trans( | 2700 | xlog_recover_do_efi_trans( |
2679 | xlog_t *log, | 2701 | xlog_t *log, |
2680 | xlog_recover_item_t *item, | 2702 | xlog_recover_item_t *item, |
2681 | xfs_lsn_t lsn, | 2703 | xfs_lsn_t lsn, |
2682 | int pass) | 2704 | int pass) |
2683 | { | 2705 | { |
2706 | int error; | ||
2684 | xfs_mount_t *mp; | 2707 | xfs_mount_t *mp; |
2685 | xfs_efi_log_item_t *efip; | 2708 | xfs_efi_log_item_t *efip; |
2686 | xfs_efi_log_format_t *efi_formatp; | 2709 | xfs_efi_log_format_t *efi_formatp; |
2687 | SPLDECL(s); | 2710 | SPLDECL(s); |
2688 | 2711 | ||
2689 | if (pass == XLOG_RECOVER_PASS1) { | 2712 | if (pass == XLOG_RECOVER_PASS1) { |
2690 | return; | 2713 | return 0; |
2691 | } | 2714 | } |
2692 | 2715 | ||
2693 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; | 2716 | efi_formatp = (xfs_efi_log_format_t *)item->ri_buf[0].i_addr; |
2694 | ASSERT(item->ri_buf[0].i_len == | ||
2695 | (sizeof(xfs_efi_log_format_t) + | ||
2696 | ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t)))); | ||
2697 | 2717 | ||
2698 | mp = log->l_mp; | 2718 | mp = log->l_mp; |
2699 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); | 2719 | efip = xfs_efi_init(mp, efi_formatp->efi_nextents); |
2700 | memcpy((char *)&(efip->efi_format), (char *)efi_formatp, | 2720 | if ((error = xfs_efi_copy_format(&(item->ri_buf[0]), |
2701 | sizeof(xfs_efi_log_format_t) + | 2721 | &(efip->efi_format)))) { |
2702 | ((efi_formatp->efi_nextents - 1) * sizeof(xfs_extent_t))); | 2722 | xfs_efi_item_free(efip); |
2723 | return error; | ||
2724 | } | ||
2703 | efip->efi_next_extent = efi_formatp->efi_nextents; | 2725 | efip->efi_next_extent = efi_formatp->efi_nextents; |
2704 | efip->efi_flags |= XFS_EFI_COMMITTED; | 2726 | efip->efi_flags |= XFS_EFI_COMMITTED; |
2705 | 2727 | ||
@@ -2708,6 +2730,7 @@ xlog_recover_do_efi_trans( | |||
2708 | * xfs_trans_update_ail() drops the AIL lock. | 2730 | * xfs_trans_update_ail() drops the AIL lock. |
2709 | */ | 2731 | */ |
2710 | xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); | 2732 | xfs_trans_update_ail(mp, (xfs_log_item_t *)efip, lsn, s); |
2733 | return 0; | ||
2711 | } | 2734 | } |
2712 | 2735 | ||
2713 | 2736 | ||
@@ -2738,9 +2761,10 @@ xlog_recover_do_efd_trans( | |||
2738 | } | 2761 | } |
2739 | 2762 | ||
2740 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; | 2763 | efd_formatp = (xfs_efd_log_format_t *)item->ri_buf[0].i_addr; |
2741 | ASSERT(item->ri_buf[0].i_len == | 2764 | ASSERT((item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_32_t) + |
2742 | (sizeof(xfs_efd_log_format_t) + | 2765 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_32_t)))) || |
2743 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_t)))); | 2766 | (item->ri_buf[0].i_len == (sizeof(xfs_efd_log_format_64_t) + |
2767 | ((efd_formatp->efd_nextents - 1) * sizeof(xfs_extent_64_t))))); | ||
2744 | efi_id = efd_formatp->efd_efi_id; | 2768 | efi_id = efd_formatp->efd_efi_id; |
2745 | 2769 | ||
2746 | /* | 2770 | /* |
@@ -2810,15 +2834,14 @@ xlog_recover_do_trans( | |||
2810 | if ((error = xlog_recover_do_buffer_trans(log, item, | 2834 | if ((error = xlog_recover_do_buffer_trans(log, item, |
2811 | pass))) | 2835 | pass))) |
2812 | break; | 2836 | break; |
2813 | } else if ((ITEM_TYPE(item) == XFS_LI_INODE) || | 2837 | } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) { |
2814 | (ITEM_TYPE(item) == XFS_LI_6_1_INODE) || | ||
2815 | (ITEM_TYPE(item) == XFS_LI_5_3_INODE)) { | ||
2816 | if ((error = xlog_recover_do_inode_trans(log, item, | 2838 | if ((error = xlog_recover_do_inode_trans(log, item, |
2817 | pass))) | 2839 | pass))) |
2818 | break; | 2840 | break; |
2819 | } else if (ITEM_TYPE(item) == XFS_LI_EFI) { | 2841 | } else if (ITEM_TYPE(item) == XFS_LI_EFI) { |
2820 | xlog_recover_do_efi_trans(log, item, trans->r_lsn, | 2842 | if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn, |
2821 | pass); | 2843 | pass))) |
2844 | break; | ||
2822 | } else if (ITEM_TYPE(item) == XFS_LI_EFD) { | 2845 | } else if (ITEM_TYPE(item) == XFS_LI_EFD) { |
2823 | xlog_recover_do_efd_trans(log, item, pass); | 2846 | xlog_recover_do_efd_trans(log, item, pass); |
2824 | } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { | 2847 | } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { |
@@ -3419,13 +3442,13 @@ xlog_unpack_data_checksum( | |||
3419 | if (rhead->h_chksum || | 3442 | if (rhead->h_chksum || |
3420 | ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) { | 3443 | ((log->l_flags & XLOG_CHKSUM_MISMATCH) == 0)) { |
3421 | cmn_err(CE_DEBUG, | 3444 | cmn_err(CE_DEBUG, |
3422 | "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)", | 3445 | "XFS: LogR chksum mismatch: was (0x%x) is (0x%x)\n", |
3423 | INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum); | 3446 | INT_GET(rhead->h_chksum, ARCH_CONVERT), chksum); |
3424 | cmn_err(CE_DEBUG, | 3447 | cmn_err(CE_DEBUG, |
3425 | "XFS: Disregard message if filesystem was created with non-DEBUG kernel"); | 3448 | "XFS: Disregard message if filesystem was created with non-DEBUG kernel"); |
3426 | if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { | 3449 | if (XFS_SB_VERSION_HASLOGV2(&log->l_mp->m_sb)) { |
3427 | cmn_err(CE_DEBUG, | 3450 | cmn_err(CE_DEBUG, |
3428 | "XFS: LogR this is a LogV2 filesystem"); | 3451 | "XFS: LogR this is a LogV2 filesystem\n"); |
3429 | } | 3452 | } |
3430 | log->l_flags |= XLOG_CHKSUM_MISMATCH; | 3453 | log->l_flags |= XLOG_CHKSUM_MISMATCH; |
3431 | } | 3454 | } |
@@ -3798,7 +3821,7 @@ xlog_do_log_recovery( | |||
3798 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, | 3821 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, |
3799 | XLOG_RECOVER_PASS2); | 3822 | XLOG_RECOVER_PASS2); |
3800 | #ifdef DEBUG | 3823 | #ifdef DEBUG |
3801 | { | 3824 | if (!error) { |
3802 | int i; | 3825 | int i; |
3803 | 3826 | ||
3804 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | 3827 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) |
@@ -3974,7 +3997,7 @@ xlog_recover_finish( | |||
3974 | log->l_flags &= ~XLOG_RECOVERY_NEEDED; | 3997 | log->l_flags &= ~XLOG_RECOVERY_NEEDED; |
3975 | } else { | 3998 | } else { |
3976 | cmn_err(CE_DEBUG, | 3999 | cmn_err(CE_DEBUG, |
3977 | "!Ending clean XFS mount for filesystem: %s", | 4000 | "!Ending clean XFS mount for filesystem: %s\n", |
3978 | log->l_mp->m_fsname); | 4001 | log->l_mp->m_fsname); |
3979 | } | 4002 | } |
3980 | return 0; | 4003 | return 0; |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index c0b1c2906880..10dbf203c62f 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -196,7 +194,7 @@ xfs_mount_free( | |||
196 | kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); | 194 | kmem_free(mp->m_logname, strlen(mp->m_logname) + 1); |
197 | 195 | ||
198 | if (remove_bhv) { | 196 | if (remove_bhv) { |
199 | struct vfs *vfsp = XFS_MTOVFS(mp); | 197 | struct bhv_vfs *vfsp = XFS_MTOVFS(mp); |
200 | 198 | ||
201 | bhv_remove_all_vfsops(vfsp, 0); | 199 | bhv_remove_all_vfsops(vfsp, 0); |
202 | VFS_REMOVEBHV(vfsp, &mp->m_bhv); | 200 | VFS_REMOVEBHV(vfsp, &mp->m_bhv); |
@@ -337,7 +335,7 @@ xfs_mount_validate_sb( | |||
337 | 335 | ||
338 | xfs_agnumber_t | 336 | xfs_agnumber_t |
339 | xfs_initialize_perag( | 337 | xfs_initialize_perag( |
340 | struct vfs *vfs, | 338 | bhv_vfs_t *vfs, |
341 | xfs_mount_t *mp, | 339 | xfs_mount_t *mp, |
342 | xfs_agnumber_t agcount) | 340 | xfs_agnumber_t agcount) |
343 | { | 341 | { |
@@ -651,14 +649,14 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) | |||
651 | */ | 649 | */ |
652 | int | 650 | int |
653 | xfs_mountfs( | 651 | xfs_mountfs( |
654 | vfs_t *vfsp, | 652 | bhv_vfs_t *vfsp, |
655 | xfs_mount_t *mp, | 653 | xfs_mount_t *mp, |
656 | int mfsi_flags) | 654 | int mfsi_flags) |
657 | { | 655 | { |
658 | xfs_buf_t *bp; | 656 | xfs_buf_t *bp; |
659 | xfs_sb_t *sbp = &(mp->m_sb); | 657 | xfs_sb_t *sbp = &(mp->m_sb); |
660 | xfs_inode_t *rip; | 658 | xfs_inode_t *rip; |
661 | vnode_t *rvp = NULL; | 659 | bhv_vnode_t *rvp = NULL; |
662 | int readio_log, writeio_log; | 660 | int readio_log, writeio_log; |
663 | xfs_daddr_t d; | 661 | xfs_daddr_t d; |
664 | __uint64_t ret64; | 662 | __uint64_t ret64; |
@@ -934,18 +932,7 @@ xfs_mountfs( | |||
934 | vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; | 932 | vfsp->vfs_altfsid = (xfs_fsid_t *)mp->m_fixedfsid; |
935 | mp->m_dmevmask = 0; /* not persistent; set after each mount */ | 933 | mp->m_dmevmask = 0; /* not persistent; set after each mount */ |
936 | 934 | ||
937 | /* | 935 | xfs_dir_mount(mp); |
938 | * Select the right directory manager. | ||
939 | */ | ||
940 | mp->m_dirops = | ||
941 | XFS_SB_VERSION_HASDIRV2(&mp->m_sb) ? | ||
942 | xfsv2_dirops : | ||
943 | xfsv1_dirops; | ||
944 | |||
945 | /* | ||
946 | * Initialize directory manager's entries. | ||
947 | */ | ||
948 | XFS_DIR_MOUNT(mp); | ||
949 | 936 | ||
950 | /* | 937 | /* |
951 | * Initialize the attribute manager's entries. | 938 | * Initialize the attribute manager's entries. |
@@ -1006,8 +993,9 @@ xfs_mountfs( | |||
1006 | 993 | ||
1007 | if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { | 994 | if (unlikely((rip->i_d.di_mode & S_IFMT) != S_IFDIR)) { |
1008 | cmn_err(CE_WARN, "XFS: corrupted root inode"); | 995 | cmn_err(CE_WARN, "XFS: corrupted root inode"); |
1009 | prdev("Root inode %llu is not a directory", | 996 | cmn_err(CE_WARN, "Device %s - root %llu is not a directory", |
1010 | mp->m_ddev_targp, (unsigned long long)rip->i_ino); | 997 | XFS_BUFTARG_NAME(mp->m_ddev_targp), |
998 | (unsigned long long)rip->i_ino); | ||
1011 | xfs_iunlock(rip, XFS_ILOCK_EXCL); | 999 | xfs_iunlock(rip, XFS_ILOCK_EXCL); |
1012 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, | 1000 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, |
1013 | mp); | 1001 | mp); |
@@ -1094,7 +1082,7 @@ xfs_mountfs( | |||
1094 | int | 1082 | int |
1095 | xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) | 1083 | xfs_unmountfs(xfs_mount_t *mp, struct cred *cr) |
1096 | { | 1084 | { |
1097 | struct vfs *vfsp = XFS_MTOVFS(mp); | 1085 | struct bhv_vfs *vfsp = XFS_MTOVFS(mp); |
1098 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) | 1086 | #if defined(DEBUG) || defined(INDUCE_IO_ERROR) |
1099 | int64_t fsid; | 1087 | int64_t fsid; |
1100 | #endif | 1088 | #endif |
@@ -1254,6 +1242,26 @@ xfs_mod_sb(xfs_trans_t *tp, __int64_t fields) | |||
1254 | 1242 | ||
1255 | xfs_trans_log_buf(tp, bp, first, last); | 1243 | xfs_trans_log_buf(tp, bp, first, last); |
1256 | } | 1244 | } |
1245 | |||
1246 | /* | ||
1247 | * In order to avoid ENOSPC-related deadlock caused by | ||
1248 | * out-of-order locking of AGF buffer (PV 947395), we place | ||
1249 | * constraints on the relationship among actual allocations for | ||
1250 | * data blocks, freelist blocks, and potential file data bmap | ||
1251 | * btree blocks. However, these restrictions may result in no | ||
1252 | * actual space allocated for a delayed extent, for example, a data | ||
1253 | * block in a certain AG is allocated but there is no additional | ||
1254 | * block for the additional bmap btree block due to a split of the | ||
1255 | * bmap btree of the file. The result of this may lead to an | ||
1256 | * infinite loop in xfssyncd when the file gets flushed to disk and | ||
1257 | * all delayed extents need to be actually allocated. To get around | ||
1258 | * this, we explicitly set aside a few blocks which will not be | ||
1259 | * reserved in delayed allocation. Considering the minimum number of | ||
1260 | * needed freelist blocks is 4 fsbs, a potential split of file's bmap | ||
1261 | * btree requires 1 fsb, so we set the number of set-aside blocks to 8. | ||
1262 | */ | ||
1263 | #define SET_ASIDE_BLOCKS 8 | ||
1264 | |||
1257 | /* | 1265 | /* |
1258 | * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply | 1266 | * xfs_mod_incore_sb_unlocked() is a utility routine common used to apply |
1259 | * a delta to a specified field in the in-core superblock. Simply | 1267 | * a delta to a specified field in the in-core superblock. Simply |
@@ -1298,7 +1306,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, | |||
1298 | return 0; | 1306 | return 0; |
1299 | case XFS_SBS_FDBLOCKS: | 1307 | case XFS_SBS_FDBLOCKS: |
1300 | 1308 | ||
1301 | lcounter = (long long)mp->m_sb.sb_fdblocks; | 1309 | lcounter = (long long)mp->m_sb.sb_fdblocks - SET_ASIDE_BLOCKS; |
1302 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); | 1310 | res_used = (long long)(mp->m_resblks - mp->m_resblks_avail); |
1303 | 1311 | ||
1304 | if (delta > 0) { /* Putting blocks back */ | 1312 | if (delta > 0) { /* Putting blocks back */ |
@@ -1332,7 +1340,7 @@ xfs_mod_incore_sb_unlocked(xfs_mount_t *mp, xfs_sb_field_t field, | |||
1332 | } | 1340 | } |
1333 | } | 1341 | } |
1334 | 1342 | ||
1335 | mp->m_sb.sb_fdblocks = lcounter; | 1343 | mp->m_sb.sb_fdblocks = lcounter + SET_ASIDE_BLOCKS; |
1336 | return 0; | 1344 | return 0; |
1337 | case XFS_SBS_FREXTENTS: | 1345 | case XFS_SBS_FREXTENTS: |
1338 | lcounter = (long long)mp->m_sb.sb_frextents; | 1346 | lcounter = (long long)mp->m_sb.sb_frextents; |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 668ad23fd37c..b2bd4be4200a 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -53,8 +53,8 @@ typedef struct xfs_trans_reservations { | |||
53 | #else | 53 | #else |
54 | struct cred; | 54 | struct cred; |
55 | struct log; | 55 | struct log; |
56 | struct vfs; | 56 | struct bhv_vfs; |
57 | struct vnode; | 57 | struct bhv_vnode; |
58 | struct xfs_mount_args; | 58 | struct xfs_mount_args; |
59 | struct xfs_ihash; | 59 | struct xfs_ihash; |
60 | struct xfs_chash; | 60 | struct xfs_chash; |
@@ -63,9 +63,11 @@ struct xfs_perag; | |||
63 | struct xfs_iocore; | 63 | struct xfs_iocore; |
64 | struct xfs_bmbt_irec; | 64 | struct xfs_bmbt_irec; |
65 | struct xfs_bmap_free; | 65 | struct xfs_bmap_free; |
66 | struct xfs_extdelta; | ||
67 | struct xfs_swapext; | ||
66 | 68 | ||
67 | extern struct vfsops xfs_vfsops; | 69 | extern struct bhv_vfsops xfs_vfsops; |
68 | extern struct vnodeops xfs_vnodeops; | 70 | extern struct bhv_vnodeops xfs_vnodeops; |
69 | 71 | ||
70 | #define AIL_LOCK_T lock_t | 72 | #define AIL_LOCK_T lock_t |
71 | #define AIL_LOCKINIT(x,y) spinlock_init(x,y) | 73 | #define AIL_LOCKINIT(x,y) spinlock_init(x,y) |
@@ -78,15 +80,15 @@ extern struct vnodeops xfs_vnodeops; | |||
78 | * Prototypes and functions for the Data Migration subsystem. | 80 | * Prototypes and functions for the Data Migration subsystem. |
79 | */ | 81 | */ |
80 | 82 | ||
81 | typedef int (*xfs_send_data_t)(int, struct vnode *, | 83 | typedef int (*xfs_send_data_t)(int, struct bhv_vnode *, |
82 | xfs_off_t, size_t, int, vrwlock_t *); | 84 | xfs_off_t, size_t, int, bhv_vrwlock_t *); |
83 | typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); | 85 | typedef int (*xfs_send_mmap_t)(struct vm_area_struct *, uint); |
84 | typedef int (*xfs_send_destroy_t)(struct vnode *, dm_right_t); | 86 | typedef int (*xfs_send_destroy_t)(struct bhv_vnode *, dm_right_t); |
85 | typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct vfs *, | 87 | typedef int (*xfs_send_namesp_t)(dm_eventtype_t, struct bhv_vfs *, |
86 | struct vnode *, | 88 | struct bhv_vnode *, |
87 | dm_right_t, struct vnode *, dm_right_t, | 89 | dm_right_t, struct bhv_vnode *, dm_right_t, |
88 | char *, char *, mode_t, int, int); | 90 | char *, char *, mode_t, int, int); |
89 | typedef void (*xfs_send_unmount_t)(struct vfs *, struct vnode *, | 91 | typedef void (*xfs_send_unmount_t)(struct bhv_vfs *, struct bhv_vnode *, |
90 | dm_right_t, mode_t, int, int); | 92 | dm_right_t, mode_t, int, int); |
91 | 93 | ||
92 | typedef struct xfs_dmops { | 94 | typedef struct xfs_dmops { |
@@ -188,13 +190,18 @@ typedef struct xfs_qmops { | |||
188 | * Prototypes and functions for I/O core modularization. | 190 | * Prototypes and functions for I/O core modularization. |
189 | */ | 191 | */ |
190 | 192 | ||
191 | typedef int (*xfs_ioinit_t)(struct vfs *, | 193 | typedef int (*xfs_ioinit_t)(struct bhv_vfs *, |
192 | struct xfs_mount_args *, int); | 194 | struct xfs_mount_args *, int); |
193 | typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, | 195 | typedef int (*xfs_bmapi_t)(struct xfs_trans *, void *, |
194 | xfs_fileoff_t, xfs_filblks_t, int, | 196 | xfs_fileoff_t, xfs_filblks_t, int, |
195 | xfs_fsblock_t *, xfs_extlen_t, | 197 | xfs_fsblock_t *, xfs_extlen_t, |
196 | struct xfs_bmbt_irec *, int *, | 198 | struct xfs_bmbt_irec *, int *, |
197 | struct xfs_bmap_free *); | 199 | struct xfs_bmap_free *, struct xfs_extdelta *); |
200 | typedef int (*xfs_bunmapi_t)(struct xfs_trans *, | ||
201 | void *, xfs_fileoff_t, | ||
202 | xfs_filblks_t, int, xfs_extnum_t, | ||
203 | xfs_fsblock_t *, struct xfs_bmap_free *, | ||
204 | struct xfs_extdelta *, int *); | ||
198 | typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); | 205 | typedef int (*xfs_bmap_eof_t)(void *, xfs_fileoff_t, int, int *); |
199 | typedef int (*xfs_iomap_write_direct_t)( | 206 | typedef int (*xfs_iomap_write_direct_t)( |
200 | void *, xfs_off_t, size_t, int, | 207 | void *, xfs_off_t, size_t, int, |
@@ -213,11 +220,14 @@ typedef void (*xfs_lock_demote_t)(void *, uint); | |||
213 | typedef int (*xfs_lock_nowait_t)(void *, uint); | 220 | typedef int (*xfs_lock_nowait_t)(void *, uint); |
214 | typedef void (*xfs_unlk_t)(void *, unsigned int); | 221 | typedef void (*xfs_unlk_t)(void *, unsigned int); |
215 | typedef xfs_fsize_t (*xfs_size_t)(void *); | 222 | typedef xfs_fsize_t (*xfs_size_t)(void *); |
216 | typedef xfs_fsize_t (*xfs_iodone_t)(struct vfs *); | 223 | typedef xfs_fsize_t (*xfs_iodone_t)(struct bhv_vfs *); |
224 | typedef int (*xfs_swap_extents_t)(void *, void *, | ||
225 | struct xfs_swapext*); | ||
217 | 226 | ||
218 | typedef struct xfs_ioops { | 227 | typedef struct xfs_ioops { |
219 | xfs_ioinit_t xfs_ioinit; | 228 | xfs_ioinit_t xfs_ioinit; |
220 | xfs_bmapi_t xfs_bmapi_func; | 229 | xfs_bmapi_t xfs_bmapi_func; |
230 | xfs_bunmapi_t xfs_bunmapi_func; | ||
221 | xfs_bmap_eof_t xfs_bmap_eof_func; | 231 | xfs_bmap_eof_t xfs_bmap_eof_func; |
222 | xfs_iomap_write_direct_t xfs_iomap_write_direct; | 232 | xfs_iomap_write_direct_t xfs_iomap_write_direct; |
223 | xfs_iomap_write_delay_t xfs_iomap_write_delay; | 233 | xfs_iomap_write_delay_t xfs_iomap_write_delay; |
@@ -230,13 +240,17 @@ typedef struct xfs_ioops { | |||
230 | xfs_unlk_t xfs_unlock; | 240 | xfs_unlk_t xfs_unlock; |
231 | xfs_size_t xfs_size_func; | 241 | xfs_size_t xfs_size_func; |
232 | xfs_iodone_t xfs_iodone; | 242 | xfs_iodone_t xfs_iodone; |
243 | xfs_swap_extents_t xfs_swap_extents_func; | ||
233 | } xfs_ioops_t; | 244 | } xfs_ioops_t; |
234 | 245 | ||
235 | #define XFS_IOINIT(vfsp, args, flags) \ | 246 | #define XFS_IOINIT(vfsp, args, flags) \ |
236 | (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags) | 247 | (*(mp)->m_io_ops.xfs_ioinit)(vfsp, args, flags) |
237 | #define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist) \ | 248 | #define XFS_BMAPI(mp, trans,io,bno,len,f,first,tot,mval,nmap,flist,delta) \ |
238 | (*(mp)->m_io_ops.xfs_bmapi_func) \ | 249 | (*(mp)->m_io_ops.xfs_bmapi_func) \ |
239 | (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist) | 250 | (trans,(io)->io_obj,bno,len,f,first,tot,mval,nmap,flist,delta) |
251 | #define XFS_BUNMAPI(mp, trans,io,bno,len,f,nexts,first,flist,delta,done) \ | ||
252 | (*(mp)->m_io_ops.xfs_bunmapi_func) \ | ||
253 | (trans,(io)->io_obj,bno,len,f,nexts,first,flist,delta,done) | ||
240 | #define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \ | 254 | #define XFS_BMAP_EOF(mp, io, endoff, whichfork, eof) \ |
241 | (*(mp)->m_io_ops.xfs_bmap_eof_func) \ | 255 | (*(mp)->m_io_ops.xfs_bmap_eof_func) \ |
242 | ((io)->io_obj, endoff, whichfork, eof) | 256 | ((io)->io_obj, endoff, whichfork, eof) |
@@ -266,6 +280,9 @@ typedef struct xfs_ioops { | |||
266 | (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj) | 280 | (*(mp)->m_io_ops.xfs_size_func)((io)->io_obj) |
267 | #define XFS_IODONE(vfsp) \ | 281 | #define XFS_IODONE(vfsp) \ |
268 | (*(mp)->m_io_ops.xfs_iodone)(vfsp) | 282 | (*(mp)->m_io_ops.xfs_iodone)(vfsp) |
283 | #define XFS_SWAP_EXTENTS(mp, io, tio, sxp) \ | ||
284 | (*(mp)->m_io_ops.xfs_swap_extents_func) \ | ||
285 | ((io)->io_obj, (tio)->io_obj, sxp) | ||
269 | 286 | ||
270 | #ifdef HAVE_PERCPU_SB | 287 | #ifdef HAVE_PERCPU_SB |
271 | 288 | ||
@@ -386,8 +403,6 @@ typedef struct xfs_mount { | |||
386 | __uint8_t m_inode_quiesce;/* call quiesce on new inodes. | 403 | __uint8_t m_inode_quiesce;/* call quiesce on new inodes. |
387 | field governed by m_ilock */ | 404 | field governed by m_ilock */ |
388 | __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ | 405 | __uint8_t m_sectbb_log; /* sectlog - BBSHIFT */ |
389 | __uint8_t m_dirversion; /* 1 or 2 */ | ||
390 | xfs_dirops_t m_dirops; /* table of dir funcs */ | ||
391 | int m_dirblksize; /* directory block sz--bytes */ | 406 | int m_dirblksize; /* directory block sz--bytes */ |
392 | int m_dirblkfsbs; /* directory block sz--fsbs */ | 407 | int m_dirblkfsbs; /* directory block sz--fsbs */ |
393 | xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ | 408 | xfs_dablk_t m_dirdatablk; /* blockno of dir data v2 */ |
@@ -494,16 +509,7 @@ xfs_preferred_iosize(xfs_mount_t *mp) | |||
494 | 509 | ||
495 | #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) | 510 | #define XFS_FORCED_SHUTDOWN(mp) ((mp)->m_flags & XFS_MOUNT_FS_SHUTDOWN) |
496 | #define xfs_force_shutdown(m,f) \ | 511 | #define xfs_force_shutdown(m,f) \ |
497 | VFS_FORCE_SHUTDOWN((XFS_MTOVFS(m)), f, __FILE__, __LINE__) | 512 | bhv_vfs_force_shutdown((XFS_MTOVFS(m)), f, __FILE__, __LINE__) |
498 | |||
499 | /* | ||
500 | * Flags sent to xfs_force_shutdown. | ||
501 | */ | ||
502 | #define XFS_METADATA_IO_ERROR 0x1 | ||
503 | #define XFS_LOG_IO_ERROR 0x2 | ||
504 | #define XFS_FORCE_UMOUNT 0x4 | ||
505 | #define XFS_CORRUPT_INCORE 0x8 /* Corrupt in-memory data structures */ | ||
506 | #define XFS_SHUTDOWN_REMOTE_REQ 0x10 /* Shutdown came from remote cell */ | ||
507 | 513 | ||
508 | /* | 514 | /* |
509 | * Flags for xfs_mountfs | 515 | * Flags for xfs_mountfs |
@@ -521,7 +527,7 @@ xfs_preferred_iosize(xfs_mount_t *mp) | |||
521 | * Macros for getting from mount to vfs and back. | 527 | * Macros for getting from mount to vfs and back. |
522 | */ | 528 | */ |
523 | #define XFS_MTOVFS(mp) xfs_mtovfs(mp) | 529 | #define XFS_MTOVFS(mp) xfs_mtovfs(mp) |
524 | static inline struct vfs *xfs_mtovfs(xfs_mount_t *mp) | 530 | static inline struct bhv_vfs *xfs_mtovfs(xfs_mount_t *mp) |
525 | { | 531 | { |
526 | return bhvtovfs(&mp->m_bhv); | 532 | return bhvtovfs(&mp->m_bhv); |
527 | } | 533 | } |
@@ -533,7 +539,7 @@ static inline xfs_mount_t *xfs_bhvtom(bhv_desc_t *bdp) | |||
533 | } | 539 | } |
534 | 540 | ||
535 | #define XFS_VFSTOM(vfs) xfs_vfstom(vfs) | 541 | #define XFS_VFSTOM(vfs) xfs_vfstom(vfs) |
536 | static inline xfs_mount_t *xfs_vfstom(vfs_t *vfs) | 542 | static inline xfs_mount_t *xfs_vfstom(bhv_vfs_t *vfs) |
537 | { | 543 | { |
538 | return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops)); | 544 | return XFS_BHVTOM(bhv_lookup(VFS_BHVHEAD(vfs), &xfs_vfsops)); |
539 | } | 545 | } |
@@ -571,7 +577,7 @@ typedef struct xfs_mod_sb { | |||
571 | extern xfs_mount_t *xfs_mount_init(void); | 577 | extern xfs_mount_t *xfs_mount_init(void); |
572 | extern void xfs_mod_sb(xfs_trans_t *, __int64_t); | 578 | extern void xfs_mod_sb(xfs_trans_t *, __int64_t); |
573 | extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); | 579 | extern void xfs_mount_free(xfs_mount_t *mp, int remove_bhv); |
574 | extern int xfs_mountfs(struct vfs *, xfs_mount_t *mp, int); | 580 | extern int xfs_mountfs(struct bhv_vfs *, xfs_mount_t *mp, int); |
575 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); | 581 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); |
576 | 582 | ||
577 | extern int xfs_unmountfs(xfs_mount_t *, struct cred *); | 583 | extern int xfs_unmountfs(xfs_mount_t *, struct cred *); |
@@ -589,7 +595,7 @@ extern void xfs_freesb(xfs_mount_t *); | |||
589 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); | 595 | extern void xfs_do_force_shutdown(bhv_desc_t *, int, char *, int); |
590 | extern int xfs_syncsub(xfs_mount_t *, int, int, int *); | 596 | extern int xfs_syncsub(xfs_mount_t *, int, int, int *); |
591 | extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *); | 597 | extern int xfs_sync_inodes(xfs_mount_t *, int, int, int *); |
592 | extern xfs_agnumber_t xfs_initialize_perag(struct vfs *, xfs_mount_t *, | 598 | extern xfs_agnumber_t xfs_initialize_perag(struct bhv_vfs *, xfs_mount_t *, |
593 | xfs_agnumber_t); | 599 | xfs_agnumber_t); |
594 | extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); | 600 | extern void xfs_xlatesb(void *, struct xfs_sb *, int, __int64_t); |
595 | 601 | ||
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c index 1408a32eef88..320d63ff9ca2 100644 --- a/fs/xfs/xfs_qmops.c +++ b/fs/xfs/xfs_qmops.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_ag.h" | 25 | #include "xfs_ag.h" |
26 | #include "xfs_dir.h" | ||
27 | #include "xfs_dir2.h" | 26 | #include "xfs_dir2.h" |
28 | #include "xfs_dmapi.h" | 27 | #include "xfs_dmapi.h" |
29 | #include "xfs_mount.h" | 28 | #include "xfs_mount.h" |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 7fbef974bce6..acb853b33ebb 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -365,7 +365,7 @@ typedef struct xfs_dqtrxops { | |||
365 | extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); | 365 | extern int xfs_qm_dqcheck(xfs_disk_dquot_t *, xfs_dqid_t, uint, uint, char *); |
366 | extern int xfs_mount_reset_sbqflags(struct xfs_mount *); | 366 | extern int xfs_mount_reset_sbqflags(struct xfs_mount *); |
367 | 367 | ||
368 | extern struct bhv_vfsops xfs_qmops; | 368 | extern struct bhv_module_vfsops xfs_qmops; |
369 | 369 | ||
370 | #endif /* __KERNEL__ */ | 370 | #endif /* __KERNEL__ */ |
371 | 371 | ||
diff --git a/fs/xfs/xfs_rename.c b/fs/xfs/xfs_rename.c index 1f148762eb28..d98171deaa1c 100644 --- a/fs/xfs/xfs_rename.c +++ b/fs/xfs/xfs_rename.c | |||
@@ -22,13 +22,11 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dir2.h" | 25 | #include "xfs_dir2.h" |
27 | #include "xfs_dmapi.h" | 26 | #include "xfs_dmapi.h" |
28 | #include "xfs_mount.h" | 27 | #include "xfs_mount.h" |
29 | #include "xfs_da_btree.h" | 28 | #include "xfs_da_btree.h" |
30 | #include "xfs_bmap_btree.h" | 29 | #include "xfs_bmap_btree.h" |
31 | #include "xfs_dir_sf.h" | ||
32 | #include "xfs_dir2_sf.h" | 30 | #include "xfs_dir2_sf.h" |
33 | #include "xfs_attr_sf.h" | 31 | #include "xfs_attr_sf.h" |
34 | #include "xfs_dinode.h" | 32 | #include "xfs_dinode.h" |
@@ -40,7 +38,6 @@ | |||
40 | #include "xfs_refcache.h" | 38 | #include "xfs_refcache.h" |
41 | #include "xfs_utils.h" | 39 | #include "xfs_utils.h" |
42 | #include "xfs_trans_space.h" | 40 | #include "xfs_trans_space.h" |
43 | #include "xfs_dir_leaf.h" | ||
44 | 41 | ||
45 | 42 | ||
46 | /* | 43 | /* |
@@ -87,8 +84,8 @@ STATIC int | |||
87 | xfs_lock_for_rename( | 84 | xfs_lock_for_rename( |
88 | xfs_inode_t *dp1, /* old (source) directory inode */ | 85 | xfs_inode_t *dp1, /* old (source) directory inode */ |
89 | xfs_inode_t *dp2, /* new (target) directory inode */ | 86 | xfs_inode_t *dp2, /* new (target) directory inode */ |
90 | vname_t *vname1,/* old entry name */ | 87 | bhv_vname_t *vname1,/* old entry name */ |
91 | vname_t *vname2,/* new entry name */ | 88 | bhv_vname_t *vname2,/* new entry name */ |
92 | xfs_inode_t **ipp1, /* inode of old entry */ | 89 | xfs_inode_t **ipp1, /* inode of old entry */ |
93 | xfs_inode_t **ipp2, /* inode of new entry, if it | 90 | xfs_inode_t **ipp2, /* inode of new entry, if it |
94 | already exists, NULL otherwise. */ | 91 | already exists, NULL otherwise. */ |
@@ -225,9 +222,9 @@ xfs_lock_for_rename( | |||
225 | int | 222 | int |
226 | xfs_rename( | 223 | xfs_rename( |
227 | bhv_desc_t *src_dir_bdp, | 224 | bhv_desc_t *src_dir_bdp, |
228 | vname_t *src_vname, | 225 | bhv_vname_t *src_vname, |
229 | vnode_t *target_dir_vp, | 226 | bhv_vnode_t *target_dir_vp, |
230 | vname_t *target_vname, | 227 | bhv_vname_t *target_vname, |
231 | cred_t *credp) | 228 | cred_t *credp) |
232 | { | 229 | { |
233 | xfs_trans_t *tp; | 230 | xfs_trans_t *tp; |
@@ -242,7 +239,7 @@ xfs_rename( | |||
242 | int committed; | 239 | int committed; |
243 | xfs_inode_t *inodes[4]; | 240 | xfs_inode_t *inodes[4]; |
244 | int target_ip_dropped = 0; /* dropped target_ip link? */ | 241 | int target_ip_dropped = 0; /* dropped target_ip link? */ |
245 | vnode_t *src_dir_vp; | 242 | bhv_vnode_t *src_dir_vp; |
246 | int spaceres; | 243 | int spaceres; |
247 | int target_link_zero = 0; | 244 | int target_link_zero = 0; |
248 | int num_inodes; | 245 | int num_inodes; |
@@ -398,34 +395,29 @@ xfs_rename( | |||
398 | * fit before actually inserting it. | 395 | * fit before actually inserting it. |
399 | */ | 396 | */ |
400 | if (spaceres == 0 && | 397 | if (spaceres == 0 && |
401 | (error = XFS_DIR_CANENTER(mp, tp, target_dp, target_name, | 398 | (error = xfs_dir_canenter(tp, target_dp, target_name, |
402 | target_namelen))) { | 399 | target_namelen))) |
403 | goto error_return; | 400 | goto error_return; |
404 | } | ||
405 | /* | 401 | /* |
406 | * If target does not exist and the rename crosses | 402 | * If target does not exist and the rename crosses |
407 | * directories, adjust the target directory link count | 403 | * directories, adjust the target directory link count |
408 | * to account for the ".." reference from the new entry. | 404 | * to account for the ".." reference from the new entry. |
409 | */ | 405 | */ |
410 | error = XFS_DIR_CREATENAME(mp, tp, target_dp, target_name, | 406 | error = xfs_dir_createname(tp, target_dp, target_name, |
411 | target_namelen, src_ip->i_ino, | 407 | target_namelen, src_ip->i_ino, |
412 | &first_block, &free_list, spaceres); | 408 | &first_block, &free_list, spaceres); |
413 | if (error == ENOSPC) { | 409 | if (error == ENOSPC) |
414 | goto error_return; | 410 | goto error_return; |
415 | } | 411 | if (error) |
416 | if (error) { | ||
417 | goto abort_return; | 412 | goto abort_return; |
418 | } | ||
419 | xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 413 | xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
420 | 414 | ||
421 | if (new_parent && src_is_directory) { | 415 | if (new_parent && src_is_directory) { |
422 | error = xfs_bumplink(tp, target_dp); | 416 | error = xfs_bumplink(tp, target_dp); |
423 | if (error) { | 417 | if (error) |
424 | goto abort_return; | 418 | goto abort_return; |
425 | } | ||
426 | } | 419 | } |
427 | } else { /* target_ip != NULL */ | 420 | } else { /* target_ip != NULL */ |
428 | |||
429 | /* | 421 | /* |
430 | * If target exists and it's a directory, check that both | 422 | * If target exists and it's a directory, check that both |
431 | * target and source are directories and that target can be | 423 | * target and source are directories and that target can be |
@@ -435,7 +427,7 @@ xfs_rename( | |||
435 | /* | 427 | /* |
436 | * Make sure target dir is empty. | 428 | * Make sure target dir is empty. |
437 | */ | 429 | */ |
438 | if (!(XFS_DIR_ISEMPTY(target_ip->i_mount, target_ip)) || | 430 | if (!(xfs_dir_isempty(target_ip)) || |
439 | (target_ip->i_d.di_nlink > 2)) { | 431 | (target_ip->i_d.di_nlink > 2)) { |
440 | error = XFS_ERROR(EEXIST); | 432 | error = XFS_ERROR(EEXIST); |
441 | goto error_return; | 433 | goto error_return; |
@@ -451,12 +443,11 @@ xfs_rename( | |||
451 | * In case there is already an entry with the same | 443 | * In case there is already an entry with the same |
452 | * name at the destination directory, remove it first. | 444 | * name at the destination directory, remove it first. |
453 | */ | 445 | */ |
454 | error = XFS_DIR_REPLACE(mp, tp, target_dp, target_name, | 446 | error = xfs_dir_replace(tp, target_dp, target_name, |
455 | target_namelen, src_ip->i_ino, &first_block, | 447 | target_namelen, src_ip->i_ino, |
456 | &free_list, spaceres); | 448 | &first_block, &free_list, spaceres); |
457 | if (error) { | 449 | if (error) |
458 | goto abort_return; | 450 | goto abort_return; |
459 | } | ||
460 | xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 451 | xfs_ichgtime(target_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
461 | 452 | ||
462 | /* | 453 | /* |
@@ -464,9 +455,8 @@ xfs_rename( | |||
464 | * dir no longer points to it. | 455 | * dir no longer points to it. |
465 | */ | 456 | */ |
466 | error = xfs_droplink(tp, target_ip); | 457 | error = xfs_droplink(tp, target_ip); |
467 | if (error) { | 458 | if (error) |
468 | goto abort_return; | 459 | goto abort_return; |
469 | } | ||
470 | target_ip_dropped = 1; | 460 | target_ip_dropped = 1; |
471 | 461 | ||
472 | if (src_is_directory) { | 462 | if (src_is_directory) { |
@@ -474,9 +464,8 @@ xfs_rename( | |||
474 | * Drop the link from the old "." entry. | 464 | * Drop the link from the old "." entry. |
475 | */ | 465 | */ |
476 | error = xfs_droplink(tp, target_ip); | 466 | error = xfs_droplink(tp, target_ip); |
477 | if (error) { | 467 | if (error) |
478 | goto abort_return; | 468 | goto abort_return; |
479 | } | ||
480 | } | 469 | } |
481 | 470 | ||
482 | /* Do this test while we still hold the locks */ | 471 | /* Do this test while we still hold the locks */ |
@@ -488,18 +477,15 @@ xfs_rename( | |||
488 | * Remove the source. | 477 | * Remove the source. |
489 | */ | 478 | */ |
490 | if (new_parent && src_is_directory) { | 479 | if (new_parent && src_is_directory) { |
491 | |||
492 | /* | 480 | /* |
493 | * Rewrite the ".." entry to point to the new | 481 | * Rewrite the ".." entry to point to the new |
494 | * directory. | 482 | * directory. |
495 | */ | 483 | */ |
496 | error = XFS_DIR_REPLACE(mp, tp, src_ip, "..", 2, | 484 | error = xfs_dir_replace(tp, src_ip, "..", 2, target_dp->i_ino, |
497 | target_dp->i_ino, &first_block, | 485 | &first_block, &free_list, spaceres); |
498 | &free_list, spaceres); | ||
499 | ASSERT(error != EEXIST); | 486 | ASSERT(error != EEXIST); |
500 | if (error) { | 487 | if (error) |
501 | goto abort_return; | 488 | goto abort_return; |
502 | } | ||
503 | xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 489 | xfs_ichgtime(src_ip, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
504 | 490 | ||
505 | } else { | 491 | } else { |
@@ -527,16 +513,14 @@ xfs_rename( | |||
527 | * entry that's moved no longer points to it. | 513 | * entry that's moved no longer points to it. |
528 | */ | 514 | */ |
529 | error = xfs_droplink(tp, src_dp); | 515 | error = xfs_droplink(tp, src_dp); |
530 | if (error) { | 516 | if (error) |
531 | goto abort_return; | 517 | goto abort_return; |
532 | } | ||
533 | } | 518 | } |
534 | 519 | ||
535 | error = XFS_DIR_REMOVENAME(mp, tp, src_dp, src_name, src_namelen, | 520 | error = xfs_dir_removename(tp, src_dp, src_name, src_namelen, |
536 | src_ip->i_ino, &first_block, &free_list, spaceres); | 521 | src_ip->i_ino, &first_block, &free_list, spaceres); |
537 | if (error) { | 522 | if (error) |
538 | goto abort_return; | 523 | goto abort_return; |
539 | } | ||
540 | xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 524 | xfs_ichgtime(src_dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
541 | 525 | ||
542 | /* | 526 | /* |
@@ -609,7 +593,7 @@ xfs_rename( | |||
609 | * Let interposed file systems know about removed links. | 593 | * Let interposed file systems know about removed links. |
610 | */ | 594 | */ |
611 | if (target_ip_dropped) { | 595 | if (target_ip_dropped) { |
612 | VOP_LINK_REMOVED(XFS_ITOV(target_ip), target_dir_vp, | 596 | bhv_vop_link_removed(XFS_ITOV(target_ip), target_dir_vp, |
613 | target_link_zero); | 597 | target_link_zero); |
614 | IRELE(target_ip); | 598 | IRELE(target_ip); |
615 | } | 599 | } |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index 5b413946b1c5..0c1e42b037ef 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -141,7 +139,7 @@ xfs_growfs_rt_alloc( | |||
141 | cancelflags |= XFS_TRANS_ABORT; | 139 | cancelflags |= XFS_TRANS_ABORT; |
142 | error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, | 140 | error = xfs_bmapi(tp, ip, oblocks, nblocks - oblocks, |
143 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, | 141 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, &firstblock, |
144 | resblks, &map, &nmap, &flist); | 142 | resblks, &map, &nmap, &flist, NULL); |
145 | if (!error && nmap < 1) | 143 | if (!error && nmap < 1) |
146 | error = XFS_ERROR(ENOSPC); | 144 | error = XFS_ERROR(ENOSPC); |
147 | if (error) | 145 | if (error) |
@@ -2404,10 +2402,10 @@ xfs_rtprint_range( | |||
2404 | { | 2402 | { |
2405 | xfs_extlen_t i; /* block number in the extent */ | 2403 | xfs_extlen_t i; /* block number in the extent */ |
2406 | 2404 | ||
2407 | printk("%Ld: ", (long long)start); | 2405 | cmn_err(CE_DEBUG, "%Ld: ", (long long)start); |
2408 | for (i = 0; i < len; i++) | 2406 | for (i = 0; i < len; i++) |
2409 | printk("%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); | 2407 | cmn_err(CE_DEBUG, "%d", xfs_rtcheck_bit(mp, tp, start + i, 1)); |
2410 | printk("\n"); | 2408 | cmn_err(CE_DEBUG, "\n"); |
2411 | } | 2409 | } |
2412 | 2410 | ||
2413 | /* | 2411 | /* |
@@ -2431,17 +2429,17 @@ xfs_rtprint_summary( | |||
2431 | (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c); | 2429 | (void)xfs_rtget_summary(mp, tp, l, i, &sumbp, &sb, &c); |
2432 | if (c) { | 2430 | if (c) { |
2433 | if (!p) { | 2431 | if (!p) { |
2434 | printk("%Ld-%Ld:", 1LL << l, | 2432 | cmn_err(CE_DEBUG, "%Ld-%Ld:", 1LL << l, |
2435 | XFS_RTMIN((1LL << l) + | 2433 | XFS_RTMIN((1LL << l) + |
2436 | ((1LL << l) - 1LL), | 2434 | ((1LL << l) - 1LL), |
2437 | mp->m_sb.sb_rextents)); | 2435 | mp->m_sb.sb_rextents)); |
2438 | p = 1; | 2436 | p = 1; |
2439 | } | 2437 | } |
2440 | printk(" %Ld:%d", (long long)i, c); | 2438 | cmn_err(CE_DEBUG, " %Ld:%d", (long long)i, c); |
2441 | } | 2439 | } |
2442 | } | 2440 | } |
2443 | if (p) | 2441 | if (p) |
2444 | printk("\n"); | 2442 | cmn_err(CE_DEBUG, "\n"); |
2445 | } | 2443 | } |
2446 | if (sumbp) | 2444 | if (sumbp) |
2447 | xfs_trans_brelse(tp, sumbp); | 2445 | xfs_trans_brelse(tp, sumbp); |
diff --git a/fs/xfs/xfs_rw.c b/fs/xfs/xfs_rw.c index a59c102cf214..defb2febaaf5 100644 --- a/fs/xfs/xfs_rw.c +++ b/fs/xfs/xfs_rw.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -92,6 +90,90 @@ xfs_write_clear_setuid( | |||
92 | } | 90 | } |
93 | 91 | ||
94 | /* | 92 | /* |
93 | * Handle logging requirements of various synchronous types of write. | ||
94 | */ | ||
95 | int | ||
96 | xfs_write_sync_logforce( | ||
97 | xfs_mount_t *mp, | ||
98 | xfs_inode_t *ip) | ||
99 | { | ||
100 | int error = 0; | ||
101 | |||
102 | /* | ||
103 | * If we're treating this as O_DSYNC and we have not updated the | ||
104 | * size, force the log. | ||
105 | */ | ||
106 | if (!(mp->m_flags & XFS_MOUNT_OSYNCISOSYNC) && | ||
107 | !(ip->i_update_size)) { | ||
108 | xfs_inode_log_item_t *iip = ip->i_itemp; | ||
109 | |||
110 | /* | ||
111 | * If an allocation transaction occurred | ||
112 | * without extending the size, then we have to force | ||
113 | * the log up the proper point to ensure that the | ||
114 | * allocation is permanent. We can't count on | ||
115 | * the fact that buffered writes lock out direct I/O | ||
116 | * writes - the direct I/O write could have extended | ||
117 | * the size nontransactionally, then finished before | ||
118 | * we started. xfs_write_file will think that the file | ||
119 | * didn't grow but the update isn't safe unless the | ||
120 | * size change is logged. | ||
121 | * | ||
122 | * Force the log if we've committed a transaction | ||
123 | * against the inode or if someone else has and | ||
124 | * the commit record hasn't gone to disk (e.g. | ||
125 | * the inode is pinned). This guarantees that | ||
126 | * all changes affecting the inode are permanent | ||
127 | * when we return. | ||
128 | */ | ||
129 | if (iip && iip->ili_last_lsn) { | ||
130 | xfs_log_force(mp, iip->ili_last_lsn, | ||
131 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
132 | } else if (xfs_ipincount(ip) > 0) { | ||
133 | xfs_log_force(mp, (xfs_lsn_t)0, | ||
134 | XFS_LOG_FORCE | XFS_LOG_SYNC); | ||
135 | } | ||
136 | |||
137 | } else { | ||
138 | xfs_trans_t *tp; | ||
139 | |||
140 | /* | ||
141 | * O_SYNC or O_DSYNC _with_ a size update are handled | ||
142 | * the same way. | ||
143 | * | ||
144 | * If the write was synchronous then we need to make | ||
145 | * sure that the inode modification time is permanent. | ||
146 | * We'll have updated the timestamp above, so here | ||
147 | * we use a synchronous transaction to log the inode. | ||
148 | * It's not fast, but it's necessary. | ||
149 | * | ||
150 | * If this a dsync write and the size got changed | ||
151 | * non-transactionally, then we need to ensure that | ||
152 | * the size change gets logged in a synchronous | ||
153 | * transaction. | ||
154 | */ | ||
155 | tp = xfs_trans_alloc(mp, XFS_TRANS_WRITE_SYNC); | ||
156 | if ((error = xfs_trans_reserve(tp, 0, | ||
157 | XFS_SWRITE_LOG_RES(mp), | ||
158 | 0, 0, 0))) { | ||
159 | /* Transaction reserve failed */ | ||
160 | xfs_trans_cancel(tp, 0); | ||
161 | } else { | ||
162 | /* Transaction reserve successful */ | ||
163 | xfs_ilock(ip, XFS_ILOCK_EXCL); | ||
164 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL); | ||
165 | xfs_trans_ihold(tp, ip); | ||
166 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
167 | xfs_trans_set_sync(tp); | ||
168 | error = xfs_trans_commit(tp, 0, NULL); | ||
169 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | ||
170 | } | ||
171 | } | ||
172 | |||
173 | return error; | ||
174 | } | ||
175 | |||
176 | /* | ||
95 | * Force a shutdown of the filesystem instantly while keeping | 177 | * Force a shutdown of the filesystem instantly while keeping |
96 | * the filesystem consistent. We don't do an unmount here; just shutdown | 178 | * the filesystem consistent. We don't do an unmount here; just shutdown |
97 | * the shop, make sure that absolutely nothing persistent happens to | 179 | * the shop, make sure that absolutely nothing persistent happens to |
@@ -109,12 +191,12 @@ xfs_do_force_shutdown( | |||
109 | xfs_mount_t *mp; | 191 | xfs_mount_t *mp; |
110 | 192 | ||
111 | mp = XFS_BHVTOM(bdp); | 193 | mp = XFS_BHVTOM(bdp); |
112 | logerror = flags & XFS_LOG_IO_ERROR; | 194 | logerror = flags & SHUTDOWN_LOG_IO_ERROR; |
113 | 195 | ||
114 | if (!(flags & XFS_FORCE_UMOUNT)) { | 196 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
115 | cmn_err(CE_NOTE, | 197 | cmn_err(CE_NOTE, "xfs_force_shutdown(%s,0x%x) called from " |
116 | "xfs_force_shutdown(%s,0x%x) called from line %d of file %s. Return address = 0x%p", | 198 | "line %d of file %s. Return address = 0x%p", |
117 | mp->m_fsname,flags,lnnum,fname,__return_address); | 199 | mp->m_fsname, flags, lnnum, fname, __return_address); |
118 | } | 200 | } |
119 | /* | 201 | /* |
120 | * No need to duplicate efforts. | 202 | * No need to duplicate efforts. |
@@ -125,33 +207,37 @@ xfs_do_force_shutdown( | |||
125 | /* | 207 | /* |
126 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't | 208 | * This flags XFS_MOUNT_FS_SHUTDOWN, makes sure that we don't |
127 | * queue up anybody new on the log reservations, and wakes up | 209 | * queue up anybody new on the log reservations, and wakes up |
128 | * everybody who's sleeping on log reservations and tells | 210 | * everybody who's sleeping on log reservations to tell them |
129 | * them the bad news. | 211 | * the bad news. |
130 | */ | 212 | */ |
131 | if (xfs_log_force_umount(mp, logerror)) | 213 | if (xfs_log_force_umount(mp, logerror)) |
132 | return; | 214 | return; |
133 | 215 | ||
134 | if (flags & XFS_CORRUPT_INCORE) { | 216 | if (flags & SHUTDOWN_CORRUPT_INCORE) { |
135 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, | 217 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_CORRUPT, CE_ALERT, mp, |
136 | "Corruption of in-memory data detected. Shutting down filesystem: %s", | 218 | "Corruption of in-memory data detected. Shutting down filesystem: %s", |
137 | mp->m_fsname); | 219 | mp->m_fsname); |
138 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { | 220 | if (XFS_ERRLEVEL_HIGH <= xfs_error_level) { |
139 | xfs_stack_trace(); | 221 | xfs_stack_trace(); |
140 | } | 222 | } |
141 | } else if (!(flags & XFS_FORCE_UMOUNT)) { | 223 | } else if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
142 | if (logerror) { | 224 | if (logerror) { |
143 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, | 225 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_LOGERROR, CE_ALERT, mp, |
144 | "Log I/O Error Detected. Shutting down filesystem: %s", | 226 | "Log I/O Error Detected. Shutting down filesystem: %s", |
227 | mp->m_fsname); | ||
228 | } else if (flags & SHUTDOWN_DEVICE_REQ) { | ||
229 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | ||
230 | "All device paths lost. Shutting down filesystem: %s", | ||
145 | mp->m_fsname); | 231 | mp->m_fsname); |
146 | } else if (!(flags & XFS_SHUTDOWN_REMOTE_REQ)) { | 232 | } else if (!(flags & SHUTDOWN_REMOTE_REQ)) { |
147 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, | 233 | xfs_cmn_err(XFS_PTAG_SHUTDOWN_IOERROR, CE_ALERT, mp, |
148 | "I/O Error Detected. Shutting down filesystem: %s", | 234 | "I/O Error Detected. Shutting down filesystem: %s", |
149 | mp->m_fsname); | 235 | mp->m_fsname); |
150 | } | 236 | } |
151 | } | 237 | } |
152 | if (!(flags & XFS_FORCE_UMOUNT)) { | 238 | if (!(flags & SHUTDOWN_FORCE_UMOUNT)) { |
153 | cmn_err(CE_ALERT, | 239 | cmn_err(CE_ALERT, "Please umount the filesystem, " |
154 | "Please umount the filesystem, and rectify the problem(s)"); | 240 | "and rectify the problem(s)"); |
155 | } | 241 | } |
156 | } | 242 | } |
157 | 243 | ||
@@ -335,7 +421,7 @@ xfs_bwrite( | |||
335 | * from bwrite and we could be tracing a buffer that has | 421 | * from bwrite and we could be tracing a buffer that has |
336 | * been reused. | 422 | * been reused. |
337 | */ | 423 | */ |
338 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 424 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
339 | } | 425 | } |
340 | return (error); | 426 | return (error); |
341 | } | 427 | } |
diff --git a/fs/xfs/xfs_rw.h b/fs/xfs/xfs_rw.h index e63795644478..188b296ff50c 100644 --- a/fs/xfs/xfs_rw.h +++ b/fs/xfs/xfs_rw.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -75,6 +75,7 @@ xfs_fsb_to_db_io(struct xfs_iocore *io, xfs_fsblock_t fsb) | |||
75 | * Prototypes for functions in xfs_rw.c. | 75 | * Prototypes for functions in xfs_rw.c. |
76 | */ | 76 | */ |
77 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); | 77 | extern int xfs_write_clear_setuid(struct xfs_inode *ip); |
78 | extern int xfs_write_sync_logforce(struct xfs_mount *mp, struct xfs_inode *ip); | ||
78 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); | 79 | extern int xfs_bwrite(struct xfs_mount *mp, struct xfs_buf *bp); |
79 | extern int xfs_bioerror(struct xfs_buf *bp); | 80 | extern int xfs_bioerror(struct xfs_buf *bp); |
80 | extern int xfs_bioerror_relse(struct xfs_buf *bp); | 81 | extern int xfs_bioerror_relse(struct xfs_buf *bp); |
@@ -87,9 +88,10 @@ extern void xfs_ioerror_alert(char *func, struct xfs_mount *mp, | |||
87 | /* | 88 | /* |
88 | * Prototypes for functions in xfs_vnodeops.c. | 89 | * Prototypes for functions in xfs_vnodeops.c. |
89 | */ | 90 | */ |
90 | extern int xfs_rwlock(bhv_desc_t *bdp, vrwlock_t write_lock); | 91 | extern int xfs_rwlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock); |
91 | extern void xfs_rwunlock(bhv_desc_t *bdp, vrwlock_t write_lock); | 92 | extern void xfs_rwunlock(bhv_desc_t *bdp, bhv_vrwlock_t write_lock); |
92 | extern int xfs_setattr(bhv_desc_t *bdp, vattr_t *vap, int flags, cred_t *credp); | 93 | extern int xfs_setattr(bhv_desc_t *, bhv_vattr_t *vap, int flags, |
94 | cred_t *credp); | ||
93 | extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf, | 95 | extern int xfs_change_file_space(bhv_desc_t *bdp, int cmd, xfs_flock64_t *bf, |
94 | xfs_off_t offset, cred_t *credp, int flags); | 96 | xfs_off_t offset, cred_t *credp, int flags); |
95 | extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state, | 97 | extern int xfs_set_dmattrs(bhv_desc_t *bdp, u_int evmask, u_int16_t state, |
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c index 8d056cef5d1f..ee2721e0de4d 100644 --- a/fs/xfs/xfs_trans.c +++ b/fs/xfs/xfs_trans.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -33,7 +32,6 @@ | |||
33 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
36 | #include "xfs_dir_sf.h" | ||
37 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
38 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
39 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
@@ -236,11 +234,8 @@ xfs_trans_alloc( | |||
236 | xfs_mount_t *mp, | 234 | xfs_mount_t *mp, |
237 | uint type) | 235 | uint type) |
238 | { | 236 | { |
239 | fs_check_frozen(XFS_MTOVFS(mp), SB_FREEZE_TRANS); | 237 | vfs_wait_for_freeze(XFS_MTOVFS(mp), SB_FREEZE_TRANS); |
240 | atomic_inc(&mp->m_active_trans); | 238 | return _xfs_trans_alloc(mp, type); |
241 | |||
242 | return (_xfs_trans_alloc(mp, type)); | ||
243 | |||
244 | } | 239 | } |
245 | 240 | ||
246 | xfs_trans_t * | 241 | xfs_trans_t * |
@@ -250,12 +245,9 @@ _xfs_trans_alloc( | |||
250 | { | 245 | { |
251 | xfs_trans_t *tp; | 246 | xfs_trans_t *tp; |
252 | 247 | ||
253 | ASSERT(xfs_trans_zone != NULL); | 248 | atomic_inc(&mp->m_active_trans); |
254 | tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); | ||
255 | 249 | ||
256 | /* | 250 | tp = kmem_zone_zalloc(xfs_trans_zone, KM_SLEEP); |
257 | * Initialize the transaction structure. | ||
258 | */ | ||
259 | tp->t_magic = XFS_TRANS_MAGIC; | 251 | tp->t_magic = XFS_TRANS_MAGIC; |
260 | tp->t_type = type; | 252 | tp->t_type = type; |
261 | tp->t_mountp = mp; | 253 | tp->t_mountp = mp; |
@@ -263,8 +255,7 @@ _xfs_trans_alloc( | |||
263 | tp->t_busy_free = XFS_LBC_NUM_SLOTS; | 255 | tp->t_busy_free = XFS_LBC_NUM_SLOTS; |
264 | XFS_LIC_INIT(&(tp->t_items)); | 256 | XFS_LIC_INIT(&(tp->t_items)); |
265 | XFS_LBC_INIT(&(tp->t_busy)); | 257 | XFS_LBC_INIT(&(tp->t_busy)); |
266 | 258 | return tp; | |
267 | return (tp); | ||
268 | } | 259 | } |
269 | 260 | ||
270 | /* | 261 | /* |
@@ -303,7 +294,7 @@ xfs_trans_dup( | |||
303 | tp->t_blk_res = tp->t_blk_res_used; | 294 | tp->t_blk_res = tp->t_blk_res_used; |
304 | ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; | 295 | ntp->t_rtx_res = tp->t_rtx_res - tp->t_rtx_res_used; |
305 | tp->t_rtx_res = tp->t_rtx_res_used; | 296 | tp->t_rtx_res = tp->t_rtx_res_used; |
306 | PFLAGS_DUP(&tp->t_pflags, &ntp->t_pflags); | 297 | ntp->t_pflags = tp->t_pflags; |
307 | 298 | ||
308 | XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); | 299 | XFS_TRANS_DUP_DQINFO(tp->t_mountp, tp, ntp); |
309 | 300 | ||
@@ -335,14 +326,11 @@ xfs_trans_reserve( | |||
335 | uint logcount) | 326 | uint logcount) |
336 | { | 327 | { |
337 | int log_flags; | 328 | int log_flags; |
338 | int error; | 329 | int error = 0; |
339 | int rsvd; | 330 | int rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; |
340 | |||
341 | error = 0; | ||
342 | rsvd = (tp->t_flags & XFS_TRANS_RESERVE) != 0; | ||
343 | 331 | ||
344 | /* Mark this thread as being in a transaction */ | 332 | /* Mark this thread as being in a transaction */ |
345 | PFLAGS_SET_FSTRANS(&tp->t_pflags); | 333 | current_set_flags_nested(&tp->t_pflags, PF_FSTRANS); |
346 | 334 | ||
347 | /* | 335 | /* |
348 | * Attempt to reserve the needed disk blocks by decrementing | 336 | * Attempt to reserve the needed disk blocks by decrementing |
@@ -353,7 +341,7 @@ xfs_trans_reserve( | |||
353 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, | 341 | error = xfs_mod_incore_sb(tp->t_mountp, XFS_SBS_FDBLOCKS, |
354 | -blocks, rsvd); | 342 | -blocks, rsvd); |
355 | if (error != 0) { | 343 | if (error != 0) { |
356 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 344 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
357 | return (XFS_ERROR(ENOSPC)); | 345 | return (XFS_ERROR(ENOSPC)); |
358 | } | 346 | } |
359 | tp->t_blk_res += blocks; | 347 | tp->t_blk_res += blocks; |
@@ -426,9 +414,9 @@ undo_blocks: | |||
426 | tp->t_blk_res = 0; | 414 | tp->t_blk_res = 0; |
427 | } | 415 | } |
428 | 416 | ||
429 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 417 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
430 | 418 | ||
431 | return (error); | 419 | return error; |
432 | } | 420 | } |
433 | 421 | ||
434 | 422 | ||
@@ -819,7 +807,7 @@ shut_us_down: | |||
819 | if (commit_lsn == -1 && !shutdown) | 807 | if (commit_lsn == -1 && !shutdown) |
820 | shutdown = XFS_ERROR(EIO); | 808 | shutdown = XFS_ERROR(EIO); |
821 | } | 809 | } |
822 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 810 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
823 | xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); | 811 | xfs_trans_free_items(tp, shutdown? XFS_TRANS_ABORT : 0); |
824 | xfs_trans_free_busy(tp); | 812 | xfs_trans_free_busy(tp); |
825 | xfs_trans_free(tp); | 813 | xfs_trans_free(tp); |
@@ -846,7 +834,7 @@ shut_us_down: | |||
846 | */ | 834 | */ |
847 | nvec = xfs_trans_count_vecs(tp); | 835 | nvec = xfs_trans_count_vecs(tp); |
848 | if (nvec == 0) { | 836 | if (nvec == 0) { |
849 | xfs_force_shutdown(mp, XFS_LOG_IO_ERROR); | 837 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
850 | goto shut_us_down; | 838 | goto shut_us_down; |
851 | } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { | 839 | } else if (nvec <= XFS_TRANS_LOGVEC_COUNT) { |
852 | log_vector = log_vector_fast; | 840 | log_vector = log_vector_fast; |
@@ -884,7 +872,7 @@ shut_us_down: | |||
884 | * had pinned, clean up, free trans structure, and return error. | 872 | * had pinned, clean up, free trans structure, and return error. |
885 | */ | 873 | */ |
886 | if (error || commit_lsn == -1) { | 874 | if (error || commit_lsn == -1) { |
887 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 875 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
888 | xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); | 876 | xfs_trans_uncommit(tp, flags|XFS_TRANS_ABORT); |
889 | return XFS_ERROR(EIO); | 877 | return XFS_ERROR(EIO); |
890 | } | 878 | } |
@@ -926,7 +914,7 @@ shut_us_down: | |||
926 | /* | 914 | /* |
927 | * Mark this thread as no longer being in a transaction | 915 | * Mark this thread as no longer being in a transaction |
928 | */ | 916 | */ |
929 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 917 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
930 | 918 | ||
931 | /* | 919 | /* |
932 | * Once all the items of the transaction have been copied | 920 | * Once all the items of the transaction have been copied |
@@ -1148,7 +1136,7 @@ xfs_trans_cancel( | |||
1148 | */ | 1136 | */ |
1149 | if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { | 1137 | if ((tp->t_flags & XFS_TRANS_DIRTY) && !XFS_FORCED_SHUTDOWN(mp)) { |
1150 | XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); | 1138 | XFS_ERROR_REPORT("xfs_trans_cancel", XFS_ERRLEVEL_LOW, mp); |
1151 | xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); | 1139 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
1152 | } | 1140 | } |
1153 | #ifdef DEBUG | 1141 | #ifdef DEBUG |
1154 | if (!(flags & XFS_TRANS_ABORT)) { | 1142 | if (!(flags & XFS_TRANS_ABORT)) { |
@@ -1182,7 +1170,7 @@ xfs_trans_cancel( | |||
1182 | } | 1170 | } |
1183 | 1171 | ||
1184 | /* mark this thread as no longer being in a transaction */ | 1172 | /* mark this thread as no longer being in a transaction */ |
1185 | PFLAGS_RESTORE_FSTRANS(&tp->t_pflags); | 1173 | current_restore_flags_nested(&tp->t_pflags, PF_FSTRANS); |
1186 | 1174 | ||
1187 | xfs_trans_free_items(tp, flags); | 1175 | xfs_trans_free_items(tp, flags); |
1188 | xfs_trans_free_busy(tp); | 1176 | xfs_trans_free_busy(tp); |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index 100d9a4b38ee..cb65c3a603f5 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -805,12 +805,9 @@ typedef struct xfs_trans { | |||
805 | ((mp)->m_sb.sb_inodesize + \ | 805 | ((mp)->m_sb.sb_inodesize + \ |
806 | (mp)->m_sb.sb_sectsize * 2 + \ | 806 | (mp)->m_sb.sb_sectsize * 2 + \ |
807 | (mp)->m_dirblksize + \ | 807 | (mp)->m_dirblksize + \ |
808 | (XFS_DIR_IS_V1(mp) ? 0 : \ | 808 | XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1)) + \ |
809 | XFS_FSB_TO_B(mp, (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1))) + \ | ||
810 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ | 809 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ |
811 | (128 * (4 + \ | 810 | (128 * (4 + (XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \ |
812 | (XFS_DIR_IS_V1(mp) ? 0 : \ | ||
813 | XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK) + 1) + \ | ||
814 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) | 811 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) |
815 | 812 | ||
816 | #define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork) | 813 | #define XFS_ADDAFORK_LOG_RES(mp) ((mp)->m_reservations.tr_addafork) |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 19ab24af1c1c..558c87ff0c41 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dmapi.h" | 25 | #include "xfs_dmapi.h" |
27 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
28 | #include "xfs_trans_priv.h" | 27 | #include "xfs_trans_priv.h" |
@@ -363,9 +362,10 @@ xfs_trans_delete_ail( | |||
363 | AIL_UNLOCK(mp, s); | 362 | AIL_UNLOCK(mp, s); |
364 | else { | 363 | else { |
365 | xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, | 364 | xfs_cmn_err(XFS_PTAG_AILDELETE, CE_ALERT, mp, |
366 | "xfs_trans_delete_ail: attempting to delete a log item that is not in the AIL"); | 365 | "%s: attempting to delete a log item that is not in the AIL", |
366 | __FUNCTION__); | ||
367 | AIL_UNLOCK(mp, s); | 367 | AIL_UNLOCK(mp, s); |
368 | xfs_force_shutdown(mp, XFS_CORRUPT_INCORE); | 368 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); |
369 | } | 369 | } |
370 | } | 370 | } |
371 | } | 371 | } |
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c index c74c31ebc81c..60b6b898022b 100644 --- a/fs/xfs/xfs_trans_buf.c +++ b/fs/xfs/xfs_trans_buf.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
@@ -320,7 +318,7 @@ xfs_trans_read_buf( | |||
320 | if (xfs_error_target == target) { | 318 | if (xfs_error_target == target) { |
321 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | 319 | if (((xfs_req_num++) % xfs_error_mod) == 0) { |
322 | xfs_buf_relse(bp); | 320 | xfs_buf_relse(bp); |
323 | printk("Returning error!\n"); | 321 | cmn_err(CE_DEBUG, "Returning error!\n"); |
324 | return XFS_ERROR(EIO); | 322 | return XFS_ERROR(EIO); |
325 | } | 323 | } |
326 | } | 324 | } |
@@ -369,7 +367,7 @@ xfs_trans_read_buf( | |||
369 | */ | 367 | */ |
370 | if (tp->t_flags & XFS_TRANS_DIRTY) | 368 | if (tp->t_flags & XFS_TRANS_DIRTY) |
371 | xfs_force_shutdown(tp->t_mountp, | 369 | xfs_force_shutdown(tp->t_mountp, |
372 | XFS_METADATA_IO_ERROR); | 370 | SHUTDOWN_META_IO_ERROR); |
373 | return error; | 371 | return error; |
374 | } | 372 | } |
375 | } | 373 | } |
@@ -414,7 +412,7 @@ xfs_trans_read_buf( | |||
414 | xfs_ioerror_alert("xfs_trans_read_buf", mp, | 412 | xfs_ioerror_alert("xfs_trans_read_buf", mp, |
415 | bp, blkno); | 413 | bp, blkno); |
416 | if (tp->t_flags & XFS_TRANS_DIRTY) | 414 | if (tp->t_flags & XFS_TRANS_DIRTY) |
417 | xfs_force_shutdown(tp->t_mountp, XFS_METADATA_IO_ERROR); | 415 | xfs_force_shutdown(tp->t_mountp, SHUTDOWN_META_IO_ERROR); |
418 | xfs_buf_relse(bp); | 416 | xfs_buf_relse(bp); |
419 | return error; | 417 | return error; |
420 | } | 418 | } |
@@ -423,9 +421,9 @@ xfs_trans_read_buf( | |||
423 | if (xfs_error_target == target) { | 421 | if (xfs_error_target == target) { |
424 | if (((xfs_req_num++) % xfs_error_mod) == 0) { | 422 | if (((xfs_req_num++) % xfs_error_mod) == 0) { |
425 | xfs_force_shutdown(tp->t_mountp, | 423 | xfs_force_shutdown(tp->t_mountp, |
426 | XFS_METADATA_IO_ERROR); | 424 | SHUTDOWN_META_IO_ERROR); |
427 | xfs_buf_relse(bp); | 425 | xfs_buf_relse(bp); |
428 | printk("Returning error in trans!\n"); | 426 | cmn_err(CE_DEBUG, "Returning trans error!\n"); |
429 | return XFS_ERROR(EIO); | 427 | return XFS_ERROR(EIO); |
430 | } | 428 | } |
431 | } | 429 | } |
diff --git a/fs/xfs/xfs_trans_extfree.c b/fs/xfs/xfs_trans_extfree.c index 7d7d627f25df..b290270dd4a6 100644 --- a/fs/xfs/xfs_trans_extfree.c +++ b/fs/xfs/xfs_trans_extfree.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_sb.h" | 24 | #include "xfs_sb.h" |
25 | #include "xfs_dir.h" | ||
26 | #include "xfs_dmapi.h" | 25 | #include "xfs_dmapi.h" |
27 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
28 | #include "xfs_trans_priv.h" | 27 | #include "xfs_trans_priv.h" |
diff --git a/fs/xfs/xfs_trans_inode.c b/fs/xfs/xfs_trans_inode.c index 7c5894d59f81..b8db1d5cde5a 100644 --- a/fs/xfs/xfs_trans_inode.c +++ b/fs/xfs/xfs_trans_inode.c | |||
@@ -24,14 +24,12 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_alloc_btree.h" | 31 | #include "xfs_alloc_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_dir_sf.h" | ||
35 | #include "xfs_dir2_sf.h" | 33 | #include "xfs_dir2_sf.h" |
36 | #include "xfs_attr_sf.h" | 34 | #include "xfs_attr_sf.h" |
37 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c index 1117d600d741..2912aac07c7b 100644 --- a/fs/xfs/xfs_trans_item.c +++ b/fs/xfs/xfs_trans_item.c | |||
@@ -493,7 +493,7 @@ xfs_trans_add_busy(xfs_trans_t *tp, xfs_agnumber_t ag, xfs_extlen_t idx) | |||
493 | break; | 493 | break; |
494 | } else { | 494 | } else { |
495 | /* out-of-order vacancy */ | 495 | /* out-of-order vacancy */ |
496 | printk("OOO vacancy lbcp 0x%p\n", lbcp); | 496 | cmn_err(CE_DEBUG, "OOO vacancy lbcp 0x%p\n", lbcp); |
497 | ASSERT(0); | 497 | ASSERT(0); |
498 | } | 498 | } |
499 | } | 499 | } |
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h index 7fe3792b18df..4ea2e5074bdd 100644 --- a/fs/xfs/xfs_trans_space.h +++ b/fs/xfs/xfs_trans_space.h | |||
@@ -30,8 +30,7 @@ | |||
30 | XFS_EXTENTADD_SPACE_RES(mp,w)) | 30 | XFS_EXTENTADD_SPACE_RES(mp,w)) |
31 | #define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) | 31 | #define XFS_DAENTER_1B(mp,w) ((w) == XFS_DATA_FORK ? (mp)->m_dirblkfsbs : 1) |
32 | #define XFS_DAENTER_DBS(mp,w) \ | 32 | #define XFS_DAENTER_DBS(mp,w) \ |
33 | (XFS_DA_NODE_MAXDEPTH + \ | 33 | (XFS_DA_NODE_MAXDEPTH + (((w) == XFS_DATA_FORK) ? 2 : 0)) |
34 | ((XFS_DIR_IS_V2(mp) && (w) == XFS_DATA_FORK) ? 2 : 0)) | ||
35 | #define XFS_DAENTER_BLOCKS(mp,w) \ | 34 | #define XFS_DAENTER_BLOCKS(mp,w) \ |
36 | (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) | 35 | (XFS_DAENTER_1B(mp,w) * XFS_DAENTER_DBS(mp,w)) |
37 | #define XFS_DAENTER_BMAP1B(mp,w) \ | 36 | #define XFS_DAENTER_BMAP1B(mp,w) \ |
@@ -41,10 +40,7 @@ | |||
41 | #define XFS_DAENTER_SPACE_RES(mp,w) \ | 40 | #define XFS_DAENTER_SPACE_RES(mp,w) \ |
42 | (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) | 41 | (XFS_DAENTER_BLOCKS(mp,w) + XFS_DAENTER_BMAPS(mp,w)) |
43 | #define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) | 42 | #define XFS_DAREMOVE_SPACE_RES(mp,w) XFS_DAENTER_BMAPS(mp,w) |
44 | #define XFS_DIRENTER_MAX_SPLIT(mp,nl) \ | 43 | #define XFS_DIRENTER_MAX_SPLIT(mp,nl) 1 |
45 | (((mp)->m_sb.sb_blocksize == 512 && \ | ||
46 | XFS_DIR_IS_V1(mp) && \ | ||
47 | (nl) >= XFS_DIR_LEAF_CAN_DOUBLE_SPLIT_LEN) ? 2 : 1) | ||
48 | #define XFS_DIRENTER_SPACE_RES(mp,nl) \ | 44 | #define XFS_DIRENTER_SPACE_RES(mp,nl) \ |
49 | (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ | 45 | (XFS_DAENTER_SPACE_RES(mp, XFS_DATA_FORK) * \ |
50 | XFS_DIRENTER_MAX_SPLIT(mp,nl)) | 46 | XFS_DIRENTER_MAX_SPLIT(mp,nl)) |
@@ -57,8 +53,7 @@ | |||
57 | * Space reservation values for various transactions. | 53 | * Space reservation values for various transactions. |
58 | */ | 54 | */ |
59 | #define XFS_ADDAFORK_SPACE_RES(mp) \ | 55 | #define XFS_ADDAFORK_SPACE_RES(mp) \ |
60 | ((mp)->m_dirblkfsbs + \ | 56 | ((mp)->m_dirblkfsbs + XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK)) |
61 | (XFS_DIR_IS_V1(mp) ? 0 : XFS_DAENTER_BMAP1B(mp, XFS_DATA_FORK))) | ||
62 | #define XFS_ATTRRM_SPACE_RES(mp) \ | 57 | #define XFS_ATTRRM_SPACE_RES(mp) \ |
63 | XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) | 58 | XFS_DAREMOVE_SPACE_RES(mp, XFS_ATTR_FORK) |
64 | /* This macro is not used - see inline code in xfs_attr_set */ | 59 | /* This macro is not used - see inline code in xfs_attr_set */ |
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index 34654ec6ae10..9014d7e44488 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c | |||
@@ -24,12 +24,10 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
31 | #include "xfs_bmap_btree.h" | 30 | #include "xfs_bmap_btree.h" |
32 | #include "xfs_dir_sf.h" | ||
33 | #include "xfs_dir2_sf.h" | 31 | #include "xfs_dir2_sf.h" |
34 | #include "xfs_attr_sf.h" | 32 | #include "xfs_attr_sf.h" |
35 | #include "xfs_dinode.h" | 33 | #include "xfs_dinode.h" |
@@ -51,10 +49,10 @@ | |||
51 | */ | 49 | */ |
52 | int | 50 | int |
53 | xfs_get_dir_entry( | 51 | xfs_get_dir_entry( |
54 | vname_t *dentry, | 52 | bhv_vname_t *dentry, |
55 | xfs_inode_t **ipp) | 53 | xfs_inode_t **ipp) |
56 | { | 54 | { |
57 | vnode_t *vp; | 55 | bhv_vnode_t *vp; |
58 | 56 | ||
59 | vp = VNAME_TO_VNODE(dentry); | 57 | vp = VNAME_TO_VNODE(dentry); |
60 | 58 | ||
@@ -69,11 +67,11 @@ int | |||
69 | xfs_dir_lookup_int( | 67 | xfs_dir_lookup_int( |
70 | bhv_desc_t *dir_bdp, | 68 | bhv_desc_t *dir_bdp, |
71 | uint lock_mode, | 69 | uint lock_mode, |
72 | vname_t *dentry, | 70 | bhv_vname_t *dentry, |
73 | xfs_ino_t *inum, | 71 | xfs_ino_t *inum, |
74 | xfs_inode_t **ipp) | 72 | xfs_inode_t **ipp) |
75 | { | 73 | { |
76 | vnode_t *dir_vp; | 74 | bhv_vnode_t *dir_vp; |
77 | xfs_inode_t *dp; | 75 | xfs_inode_t *dp; |
78 | int error; | 76 | int error; |
79 | 77 | ||
@@ -82,8 +80,7 @@ xfs_dir_lookup_int( | |||
82 | 80 | ||
83 | dp = XFS_BHVTOI(dir_bdp); | 81 | dp = XFS_BHVTOI(dir_bdp); |
84 | 82 | ||
85 | error = XFS_DIR_LOOKUP(dp->i_mount, NULL, dp, | 83 | error = xfs_dir_lookup(NULL, dp, VNAME(dentry), VNAMELEN(dentry), inum); |
86 | VNAME(dentry), VNAMELEN(dentry), inum); | ||
87 | if (!error) { | 84 | if (!error) { |
88 | /* | 85 | /* |
89 | * Unlock the directory. We do this because we can't | 86 | * Unlock the directory. We do this because we can't |
diff --git a/fs/xfs/xfs_utils.h b/fs/xfs/xfs_utils.h index 472661a3b6d8..fe953e98afa7 100644 --- a/fs/xfs/xfs_utils.h +++ b/fs/xfs/xfs_utils.h | |||
@@ -23,9 +23,10 @@ | |||
23 | #define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \ | 23 | #define ITRACE(ip) vn_trace_ref(XFS_ITOV(ip), __FILE__, __LINE__, \ |
24 | (inst_t *)__return_address) | 24 | (inst_t *)__return_address) |
25 | 25 | ||
26 | extern int xfs_rename (bhv_desc_t *, vname_t *, vnode_t *, vname_t *, cred_t *); | 26 | extern int xfs_rename (bhv_desc_t *, bhv_vname_t *, bhv_vnode_t *, |
27 | extern int xfs_get_dir_entry (vname_t *, xfs_inode_t **); | 27 | bhv_vname_t *, cred_t *); |
28 | extern int xfs_dir_lookup_int (bhv_desc_t *, uint, vname_t *, xfs_ino_t *, | 28 | extern int xfs_get_dir_entry (bhv_vname_t *, xfs_inode_t **); |
29 | extern int xfs_dir_lookup_int (bhv_desc_t *, uint, bhv_vname_t *, xfs_ino_t *, | ||
29 | xfs_inode_t **); | 30 | xfs_inode_t **); |
30 | extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); | 31 | extern int xfs_truncate_file (xfs_mount_t *, xfs_inode_t *); |
31 | extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, | 32 | extern int xfs_dir_ialloc (xfs_trans_t **, xfs_inode_t *, mode_t, xfs_nlink_t, |
diff --git a/fs/xfs/xfs_vfsops.c b/fs/xfs/xfs_vfsops.c index 36ea1b2094f2..6c96391f3f1a 100644 --- a/fs/xfs/xfs_vfsops.c +++ b/fs/xfs/xfs_vfsops.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include "xfs_trans.h" | 24 | #include "xfs_trans.h" |
25 | #include "xfs_sb.h" | 25 | #include "xfs_sb.h" |
26 | #include "xfs_ag.h" | 26 | #include "xfs_ag.h" |
27 | #include "xfs_dir.h" | ||
28 | #include "xfs_dir2.h" | 27 | #include "xfs_dir2.h" |
29 | #include "xfs_dmapi.h" | 28 | #include "xfs_dmapi.h" |
30 | #include "xfs_mount.h" | 29 | #include "xfs_mount.h" |
@@ -32,7 +31,6 @@ | |||
32 | #include "xfs_bmap_btree.h" | 31 | #include "xfs_bmap_btree.h" |
33 | #include "xfs_ialloc_btree.h" | 32 | #include "xfs_ialloc_btree.h" |
34 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
35 | #include "xfs_dir_sf.h" | ||
36 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
37 | #include "xfs_attr_sf.h" | 35 | #include "xfs_attr_sf.h" |
38 | #include "xfs_dinode.h" | 36 | #include "xfs_dinode.h" |
@@ -131,9 +129,6 @@ xfs_init(void) | |||
131 | #ifdef XFS_BMBT_TRACE | 129 | #ifdef XFS_BMBT_TRACE |
132 | xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP); | 130 | xfs_bmbt_trace_buf = ktrace_alloc(XFS_BMBT_TRACE_SIZE, KM_SLEEP); |
133 | #endif | 131 | #endif |
134 | #ifdef XFS_DIR_TRACE | ||
135 | xfs_dir_trace_buf = ktrace_alloc(XFS_DIR_TRACE_SIZE, KM_SLEEP); | ||
136 | #endif | ||
137 | #ifdef XFS_ATTR_TRACE | 132 | #ifdef XFS_ATTR_TRACE |
138 | xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP); | 133 | xfs_attr_trace_buf = ktrace_alloc(XFS_ATTR_TRACE_SIZE, KM_SLEEP); |
139 | #endif | 134 | #endif |
@@ -177,9 +172,6 @@ xfs_cleanup(void) | |||
177 | #ifdef XFS_ATTR_TRACE | 172 | #ifdef XFS_ATTR_TRACE |
178 | ktrace_free(xfs_attr_trace_buf); | 173 | ktrace_free(xfs_attr_trace_buf); |
179 | #endif | 174 | #endif |
180 | #ifdef XFS_DIR_TRACE | ||
181 | ktrace_free(xfs_dir_trace_buf); | ||
182 | #endif | ||
183 | #ifdef XFS_BMBT_TRACE | 175 | #ifdef XFS_BMBT_TRACE |
184 | ktrace_free(xfs_bmbt_trace_buf); | 176 | ktrace_free(xfs_bmbt_trace_buf); |
185 | #endif | 177 | #endif |
@@ -212,7 +204,7 @@ xfs_cleanup(void) | |||
212 | */ | 204 | */ |
213 | STATIC int | 205 | STATIC int |
214 | xfs_start_flags( | 206 | xfs_start_flags( |
215 | struct vfs *vfs, | 207 | struct bhv_vfs *vfs, |
216 | struct xfs_mount_args *ap, | 208 | struct xfs_mount_args *ap, |
217 | struct xfs_mount *mp) | 209 | struct xfs_mount *mp) |
218 | { | 210 | { |
@@ -337,7 +329,7 @@ xfs_start_flags( | |||
337 | */ | 329 | */ |
338 | STATIC int | 330 | STATIC int |
339 | xfs_finish_flags( | 331 | xfs_finish_flags( |
340 | struct vfs *vfs, | 332 | struct bhv_vfs *vfs, |
341 | struct xfs_mount_args *ap, | 333 | struct xfs_mount_args *ap, |
342 | struct xfs_mount *mp) | 334 | struct xfs_mount *mp) |
343 | { | 335 | { |
@@ -423,7 +415,7 @@ xfs_mount( | |||
423 | struct xfs_mount_args *args, | 415 | struct xfs_mount_args *args, |
424 | cred_t *credp) | 416 | cred_t *credp) |
425 | { | 417 | { |
426 | struct vfs *vfsp = bhvtovfs(bhvp); | 418 | struct bhv_vfs *vfsp = bhvtovfs(bhvp); |
427 | struct bhv_desc *p; | 419 | struct bhv_desc *p; |
428 | struct xfs_mount *mp = XFS_BHVTOM(bhvp); | 420 | struct xfs_mount *mp = XFS_BHVTOM(bhvp); |
429 | struct block_device *ddev, *logdev, *rtdev; | 421 | struct block_device *ddev, *logdev, *rtdev; |
@@ -552,10 +544,10 @@ xfs_unmount( | |||
552 | int flags, | 544 | int flags, |
553 | cred_t *credp) | 545 | cred_t *credp) |
554 | { | 546 | { |
555 | struct vfs *vfsp = bhvtovfs(bdp); | 547 | bhv_vfs_t *vfsp = bhvtovfs(bdp); |
556 | xfs_mount_t *mp = XFS_BHVTOM(bdp); | 548 | xfs_mount_t *mp = XFS_BHVTOM(bdp); |
557 | xfs_inode_t *rip; | 549 | xfs_inode_t *rip; |
558 | vnode_t *rvp; | 550 | bhv_vnode_t *rvp; |
559 | int unmount_event_wanted = 0; | 551 | int unmount_event_wanted = 0; |
560 | int unmount_event_flags = 0; | 552 | int unmount_event_flags = 0; |
561 | int xfs_unmountfs_needed = 0; | 553 | int xfs_unmountfs_needed = 0; |
@@ -665,9 +657,8 @@ xfs_mntupdate( | |||
665 | int *flags, | 657 | int *flags, |
666 | struct xfs_mount_args *args) | 658 | struct xfs_mount_args *args) |
667 | { | 659 | { |
668 | struct vfs *vfsp = bhvtovfs(bdp); | 660 | bhv_vfs_t *vfsp = bhvtovfs(bdp); |
669 | xfs_mount_t *mp = XFS_BHVTOM(bdp); | 661 | xfs_mount_t *mp = XFS_BHVTOM(bdp); |
670 | int error; | ||
671 | 662 | ||
672 | if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */ | 663 | if (!(*flags & MS_RDONLY)) { /* rw/ro -> rw */ |
673 | if (vfsp->vfs_flag & VFS_RDONLY) | 664 | if (vfsp->vfs_flag & VFS_RDONLY) |
@@ -679,7 +670,7 @@ xfs_mntupdate( | |||
679 | mp->m_flags &= ~XFS_MOUNT_BARRIER; | 670 | mp->m_flags &= ~XFS_MOUNT_BARRIER; |
680 | } | 671 | } |
681 | } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */ | 672 | } else if (!(vfsp->vfs_flag & VFS_RDONLY)) { /* rw -> ro */ |
682 | VFS_SYNC(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL, error); | 673 | bhv_vfs_sync(vfsp, SYNC_FSDATA|SYNC_BDFLUSH|SYNC_ATTR, NULL); |
683 | xfs_quiesce_fs(mp); | 674 | xfs_quiesce_fs(mp); |
684 | xfs_log_unmount_write(mp); | 675 | xfs_log_unmount_write(mp); |
685 | xfs_unmountfs_writesb(mp); | 676 | xfs_unmountfs_writesb(mp); |
@@ -702,7 +693,7 @@ xfs_unmount_flush( | |||
702 | xfs_inode_t *rip = mp->m_rootip; | 693 | xfs_inode_t *rip = mp->m_rootip; |
703 | xfs_inode_t *rbmip; | 694 | xfs_inode_t *rbmip; |
704 | xfs_inode_t *rsumip = NULL; | 695 | xfs_inode_t *rsumip = NULL; |
705 | vnode_t *rvp = XFS_ITOV(rip); | 696 | bhv_vnode_t *rvp = XFS_ITOV(rip); |
706 | int error; | 697 | int error; |
707 | 698 | ||
708 | xfs_ilock(rip, XFS_ILOCK_EXCL); | 699 | xfs_ilock(rip, XFS_ILOCK_EXCL); |
@@ -781,9 +772,9 @@ fscorrupt_out2: | |||
781 | STATIC int | 772 | STATIC int |
782 | xfs_root( | 773 | xfs_root( |
783 | bhv_desc_t *bdp, | 774 | bhv_desc_t *bdp, |
784 | vnode_t **vpp) | 775 | bhv_vnode_t **vpp) |
785 | { | 776 | { |
786 | vnode_t *vp; | 777 | bhv_vnode_t *vp; |
787 | 778 | ||
788 | vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); | 779 | vp = XFS_ITOV((XFS_BHVTOM(bdp))->m_rootip); |
789 | VN_HOLD(vp); | 780 | VN_HOLD(vp); |
@@ -801,8 +792,8 @@ xfs_root( | |||
801 | STATIC int | 792 | STATIC int |
802 | xfs_statvfs( | 793 | xfs_statvfs( |
803 | bhv_desc_t *bdp, | 794 | bhv_desc_t *bdp, |
804 | xfs_statfs_t *statp, | 795 | bhv_statvfs_t *statp, |
805 | vnode_t *vp) | 796 | bhv_vnode_t *vp) |
806 | { | 797 | { |
807 | __uint64_t fakeinos; | 798 | __uint64_t fakeinos; |
808 | xfs_extlen_t lsize; | 799 | xfs_extlen_t lsize; |
@@ -900,7 +891,7 @@ xfs_sync( | |||
900 | /* | 891 | /* |
901 | * xfs sync routine for internal use | 892 | * xfs sync routine for internal use |
902 | * | 893 | * |
903 | * This routine supports all of the flags defined for the generic VFS_SYNC | 894 | * This routine supports all of the flags defined for the generic vfs_sync |
904 | * interface as explained above under xfs_sync. In the interests of not | 895 | * interface as explained above under xfs_sync. In the interests of not |
905 | * changing interfaces within the 6.5 family, additional internally- | 896 | * changing interfaces within the 6.5 family, additional internally- |
906 | * required functions are specified within a separate xflags parameter, | 897 | * required functions are specified within a separate xflags parameter, |
@@ -917,7 +908,7 @@ xfs_sync_inodes( | |||
917 | xfs_inode_t *ip = NULL; | 908 | xfs_inode_t *ip = NULL; |
918 | xfs_inode_t *ip_next; | 909 | xfs_inode_t *ip_next; |
919 | xfs_buf_t *bp; | 910 | xfs_buf_t *bp; |
920 | vnode_t *vp = NULL; | 911 | bhv_vnode_t *vp = NULL; |
921 | int error; | 912 | int error; |
922 | int last_error; | 913 | int last_error; |
923 | uint64_t fflag; | 914 | uint64_t fflag; |
@@ -1156,9 +1147,9 @@ xfs_sync_inodes( | |||
1156 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1147 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
1157 | 1148 | ||
1158 | if (XFS_FORCED_SHUTDOWN(mp)) { | 1149 | if (XFS_FORCED_SHUTDOWN(mp)) { |
1159 | VOP_TOSS_PAGES(vp, 0, -1, FI_REMAPF); | 1150 | bhv_vop_toss_pages(vp, 0, -1, FI_REMAPF); |
1160 | } else { | 1151 | } else { |
1161 | VOP_FLUSHINVAL_PAGES(vp, 0, -1, FI_REMAPF); | 1152 | bhv_vop_flushinval_pages(vp, 0, -1, FI_REMAPF); |
1162 | } | 1153 | } |
1163 | 1154 | ||
1164 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 1155 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
@@ -1178,8 +1169,8 @@ xfs_sync_inodes( | |||
1178 | * across calls to the buffer cache. | 1169 | * across calls to the buffer cache. |
1179 | */ | 1170 | */ |
1180 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1171 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
1181 | VOP_FLUSH_PAGES(vp, (xfs_off_t)0, -1, | 1172 | error = bhv_vop_flush_pages(vp, (xfs_off_t)0, |
1182 | fflag, FI_NONE, error); | 1173 | -1, fflag, FI_NONE); |
1183 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 1174 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
1184 | } | 1175 | } |
1185 | 1176 | ||
@@ -1231,9 +1222,7 @@ xfs_sync_inodes( | |||
1231 | * marker and free it. | 1222 | * marker and free it. |
1232 | */ | 1223 | */ |
1233 | XFS_MOUNT_ILOCK(mp); | 1224 | XFS_MOUNT_ILOCK(mp); |
1234 | |||
1235 | IPOINTER_REMOVE(ip, mp); | 1225 | IPOINTER_REMOVE(ip, mp); |
1236 | |||
1237 | XFS_MOUNT_IUNLOCK(mp); | 1226 | XFS_MOUNT_IUNLOCK(mp); |
1238 | 1227 | ||
1239 | ASSERT(!(lock_flags & | 1228 | ASSERT(!(lock_flags & |
@@ -1421,7 +1410,7 @@ xfs_sync_inodes( | |||
1421 | /* | 1410 | /* |
1422 | * xfs sync routine for internal use | 1411 | * xfs sync routine for internal use |
1423 | * | 1412 | * |
1424 | * This routine supports all of the flags defined for the generic VFS_SYNC | 1413 | * This routine supports all of the flags defined for the generic vfs_sync |
1425 | * interface as explained above under xfs_sync. In the interests of not | 1414 | * interface as explained above under xfs_sync. In the interests of not |
1426 | * changing interfaces within the 6.5 family, additional internally- | 1415 | * changing interfaces within the 6.5 family, additional internally- |
1427 | * required functions are specified within a separate xflags parameter, | 1416 | * required functions are specified within a separate xflags parameter, |
@@ -1574,7 +1563,7 @@ xfs_syncsub( | |||
1574 | STATIC int | 1563 | STATIC int |
1575 | xfs_vget( | 1564 | xfs_vget( |
1576 | bhv_desc_t *bdp, | 1565 | bhv_desc_t *bdp, |
1577 | vnode_t **vpp, | 1566 | bhv_vnode_t **vpp, |
1578 | fid_t *fidp) | 1567 | fid_t *fidp) |
1579 | { | 1568 | { |
1580 | xfs_mount_t *mp = XFS_BHVTOM(bdp); | 1569 | xfs_mount_t *mp = XFS_BHVTOM(bdp); |
@@ -1657,10 +1646,10 @@ xfs_vget( | |||
1657 | #define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ | 1646 | #define MNTOPT_NOATTR2 "noattr2" /* do not use attr2 attribute format */ |
1658 | 1647 | ||
1659 | STATIC unsigned long | 1648 | STATIC unsigned long |
1660 | suffix_strtoul(const char *cp, char **endp, unsigned int base) | 1649 | suffix_strtoul(char *s, char **endp, unsigned int base) |
1661 | { | 1650 | { |
1662 | int last, shift_left_factor = 0; | 1651 | int last, shift_left_factor = 0; |
1663 | char *value = (char *)cp; | 1652 | char *value = s; |
1664 | 1653 | ||
1665 | last = strlen(value) - 1; | 1654 | last = strlen(value) - 1; |
1666 | if (value[last] == 'K' || value[last] == 'k') { | 1655 | if (value[last] == 'K' || value[last] == 'k') { |
@@ -1676,7 +1665,7 @@ suffix_strtoul(const char *cp, char **endp, unsigned int base) | |||
1676 | value[last] = '\0'; | 1665 | value[last] = '\0'; |
1677 | } | 1666 | } |
1678 | 1667 | ||
1679 | return simple_strtoul(cp, endp, base) << shift_left_factor; | 1668 | return simple_strtoul((const char *)s, endp, base) << shift_left_factor; |
1680 | } | 1669 | } |
1681 | 1670 | ||
1682 | STATIC int | 1671 | STATIC int |
@@ -1686,7 +1675,7 @@ xfs_parseargs( | |||
1686 | struct xfs_mount_args *args, | 1675 | struct xfs_mount_args *args, |
1687 | int update) | 1676 | int update) |
1688 | { | 1677 | { |
1689 | struct vfs *vfsp = bhvtovfs(bhv); | 1678 | bhv_vfs_t *vfsp = bhvtovfs(bhv); |
1690 | char *this_char, *value, *eov; | 1679 | char *this_char, *value, *eov; |
1691 | int dsunit, dswidth, vol_dsunit, vol_dswidth; | 1680 | int dsunit, dswidth, vol_dsunit, vol_dswidth; |
1692 | int iosize; | 1681 | int iosize; |
@@ -1708,42 +1697,48 @@ xfs_parseargs( | |||
1708 | 1697 | ||
1709 | if (!strcmp(this_char, MNTOPT_LOGBUFS)) { | 1698 | if (!strcmp(this_char, MNTOPT_LOGBUFS)) { |
1710 | if (!value || !*value) { | 1699 | if (!value || !*value) { |
1711 | printk("XFS: %s option requires an argument\n", | 1700 | cmn_err(CE_WARN, |
1701 | "XFS: %s option requires an argument", | ||
1712 | this_char); | 1702 | this_char); |
1713 | return EINVAL; | 1703 | return EINVAL; |
1714 | } | 1704 | } |
1715 | args->logbufs = simple_strtoul(value, &eov, 10); | 1705 | args->logbufs = simple_strtoul(value, &eov, 10); |
1716 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { | 1706 | } else if (!strcmp(this_char, MNTOPT_LOGBSIZE)) { |
1717 | if (!value || !*value) { | 1707 | if (!value || !*value) { |
1718 | printk("XFS: %s option requires an argument\n", | 1708 | cmn_err(CE_WARN, |
1709 | "XFS: %s option requires an argument", | ||
1719 | this_char); | 1710 | this_char); |
1720 | return EINVAL; | 1711 | return EINVAL; |
1721 | } | 1712 | } |
1722 | args->logbufsize = suffix_strtoul(value, &eov, 10); | 1713 | args->logbufsize = suffix_strtoul(value, &eov, 10); |
1723 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { | 1714 | } else if (!strcmp(this_char, MNTOPT_LOGDEV)) { |
1724 | if (!value || !*value) { | 1715 | if (!value || !*value) { |
1725 | printk("XFS: %s option requires an argument\n", | 1716 | cmn_err(CE_WARN, |
1717 | "XFS: %s option requires an argument", | ||
1726 | this_char); | 1718 | this_char); |
1727 | return EINVAL; | 1719 | return EINVAL; |
1728 | } | 1720 | } |
1729 | strncpy(args->logname, value, MAXNAMELEN); | 1721 | strncpy(args->logname, value, MAXNAMELEN); |
1730 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { | 1722 | } else if (!strcmp(this_char, MNTOPT_MTPT)) { |
1731 | if (!value || !*value) { | 1723 | if (!value || !*value) { |
1732 | printk("XFS: %s option requires an argument\n", | 1724 | cmn_err(CE_WARN, |
1725 | "XFS: %s option requires an argument", | ||
1733 | this_char); | 1726 | this_char); |
1734 | return EINVAL; | 1727 | return EINVAL; |
1735 | } | 1728 | } |
1736 | strncpy(args->mtpt, value, MAXNAMELEN); | 1729 | strncpy(args->mtpt, value, MAXNAMELEN); |
1737 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { | 1730 | } else if (!strcmp(this_char, MNTOPT_RTDEV)) { |
1738 | if (!value || !*value) { | 1731 | if (!value || !*value) { |
1739 | printk("XFS: %s option requires an argument\n", | 1732 | cmn_err(CE_WARN, |
1733 | "XFS: %s option requires an argument", | ||
1740 | this_char); | 1734 | this_char); |
1741 | return EINVAL; | 1735 | return EINVAL; |
1742 | } | 1736 | } |
1743 | strncpy(args->rtname, value, MAXNAMELEN); | 1737 | strncpy(args->rtname, value, MAXNAMELEN); |
1744 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { | 1738 | } else if (!strcmp(this_char, MNTOPT_BIOSIZE)) { |
1745 | if (!value || !*value) { | 1739 | if (!value || !*value) { |
1746 | printk("XFS: %s option requires an argument\n", | 1740 | cmn_err(CE_WARN, |
1741 | "XFS: %s option requires an argument", | ||
1747 | this_char); | 1742 | this_char); |
1748 | return EINVAL; | 1743 | return EINVAL; |
1749 | } | 1744 | } |
@@ -1752,7 +1747,8 @@ xfs_parseargs( | |||
1752 | args->iosizelog = (uint8_t) iosize; | 1747 | args->iosizelog = (uint8_t) iosize; |
1753 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { | 1748 | } else if (!strcmp(this_char, MNTOPT_ALLOCSIZE)) { |
1754 | if (!value || !*value) { | 1749 | if (!value || !*value) { |
1755 | printk("XFS: %s option requires an argument\n", | 1750 | cmn_err(CE_WARN, |
1751 | "XFS: %s option requires an argument", | ||
1756 | this_char); | 1752 | this_char); |
1757 | return EINVAL; | 1753 | return EINVAL; |
1758 | } | 1754 | } |
@@ -1761,7 +1757,8 @@ xfs_parseargs( | |||
1761 | args->iosizelog = ffs(iosize) - 1; | 1757 | args->iosizelog = ffs(iosize) - 1; |
1762 | } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { | 1758 | } else if (!strcmp(this_char, MNTOPT_IHASHSIZE)) { |
1763 | if (!value || !*value) { | 1759 | if (!value || !*value) { |
1764 | printk("XFS: %s option requires an argument\n", | 1760 | cmn_err(CE_WARN, |
1761 | "XFS: %s option requires an argument", | ||
1765 | this_char); | 1762 | this_char); |
1766 | return EINVAL; | 1763 | return EINVAL; |
1767 | } | 1764 | } |
@@ -1782,7 +1779,8 @@ xfs_parseargs( | |||
1782 | } else if (!strcmp(this_char, MNTOPT_INO64)) { | 1779 | } else if (!strcmp(this_char, MNTOPT_INO64)) { |
1783 | args->flags |= XFSMNT_INO64; | 1780 | args->flags |= XFSMNT_INO64; |
1784 | #if !XFS_BIG_INUMS | 1781 | #if !XFS_BIG_INUMS |
1785 | printk("XFS: %s option not allowed on this system\n", | 1782 | cmn_err(CE_WARN, |
1783 | "XFS: %s option not allowed on this system", | ||
1786 | this_char); | 1784 | this_char); |
1787 | return EINVAL; | 1785 | return EINVAL; |
1788 | #endif | 1786 | #endif |
@@ -1792,14 +1790,16 @@ xfs_parseargs( | |||
1792 | args->flags |= XFSMNT_SWALLOC; | 1790 | args->flags |= XFSMNT_SWALLOC; |
1793 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { | 1791 | } else if (!strcmp(this_char, MNTOPT_SUNIT)) { |
1794 | if (!value || !*value) { | 1792 | if (!value || !*value) { |
1795 | printk("XFS: %s option requires an argument\n", | 1793 | cmn_err(CE_WARN, |
1794 | "XFS: %s option requires an argument", | ||
1796 | this_char); | 1795 | this_char); |
1797 | return EINVAL; | 1796 | return EINVAL; |
1798 | } | 1797 | } |
1799 | dsunit = simple_strtoul(value, &eov, 10); | 1798 | dsunit = simple_strtoul(value, &eov, 10); |
1800 | } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { | 1799 | } else if (!strcmp(this_char, MNTOPT_SWIDTH)) { |
1801 | if (!value || !*value) { | 1800 | if (!value || !*value) { |
1802 | printk("XFS: %s option requires an argument\n", | 1801 | cmn_err(CE_WARN, |
1802 | "XFS: %s option requires an argument", | ||
1803 | this_char); | 1803 | this_char); |
1804 | return EINVAL; | 1804 | return EINVAL; |
1805 | } | 1805 | } |
@@ -1807,7 +1807,8 @@ xfs_parseargs( | |||
1807 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { | 1807 | } else if (!strcmp(this_char, MNTOPT_64BITINODE)) { |
1808 | args->flags &= ~XFSMNT_32BITINODES; | 1808 | args->flags &= ~XFSMNT_32BITINODES; |
1809 | #if !XFS_BIG_INUMS | 1809 | #if !XFS_BIG_INUMS |
1810 | printk("XFS: %s option not allowed on this system\n", | 1810 | cmn_err(CE_WARN, |
1811 | "XFS: %s option not allowed on this system", | ||
1811 | this_char); | 1812 | this_char); |
1812 | return EINVAL; | 1813 | return EINVAL; |
1813 | #endif | 1814 | #endif |
@@ -1831,36 +1832,41 @@ xfs_parseargs( | |||
1831 | args->flags &= ~XFSMNT_ATTR2; | 1832 | args->flags &= ~XFSMNT_ATTR2; |
1832 | } else if (!strcmp(this_char, "osyncisdsync")) { | 1833 | } else if (!strcmp(this_char, "osyncisdsync")) { |
1833 | /* no-op, this is now the default */ | 1834 | /* no-op, this is now the default */ |
1834 | printk("XFS: osyncisdsync is now the default, option is deprecated.\n"); | 1835 | cmn_err(CE_WARN, |
1836 | "XFS: osyncisdsync is now the default, option is deprecated."); | ||
1835 | } else if (!strcmp(this_char, "irixsgid")) { | 1837 | } else if (!strcmp(this_char, "irixsgid")) { |
1836 | printk("XFS: irixsgid is now a sysctl(2) variable, option is deprecated.\n"); | 1838 | cmn_err(CE_WARN, |
1839 | "XFS: irixsgid is now a sysctl(2) variable, option is deprecated."); | ||
1837 | } else { | 1840 | } else { |
1838 | printk("XFS: unknown mount option [%s].\n", this_char); | 1841 | cmn_err(CE_WARN, |
1842 | "XFS: unknown mount option [%s].", this_char); | ||
1839 | return EINVAL; | 1843 | return EINVAL; |
1840 | } | 1844 | } |
1841 | } | 1845 | } |
1842 | 1846 | ||
1843 | if (args->flags & XFSMNT_NORECOVERY) { | 1847 | if (args->flags & XFSMNT_NORECOVERY) { |
1844 | if ((vfsp->vfs_flag & VFS_RDONLY) == 0) { | 1848 | if ((vfsp->vfs_flag & VFS_RDONLY) == 0) { |
1845 | printk("XFS: no-recovery mounts must be read-only.\n"); | 1849 | cmn_err(CE_WARN, |
1850 | "XFS: no-recovery mounts must be read-only."); | ||
1846 | return EINVAL; | 1851 | return EINVAL; |
1847 | } | 1852 | } |
1848 | } | 1853 | } |
1849 | 1854 | ||
1850 | if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { | 1855 | if ((args->flags & XFSMNT_NOALIGN) && (dsunit || dswidth)) { |
1851 | printk( | 1856 | cmn_err(CE_WARN, |
1852 | "XFS: sunit and swidth options incompatible with the noalign option\n"); | 1857 | "XFS: sunit and swidth options incompatible with the noalign option"); |
1853 | return EINVAL; | 1858 | return EINVAL; |
1854 | } | 1859 | } |
1855 | 1860 | ||
1856 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { | 1861 | if ((dsunit && !dswidth) || (!dsunit && dswidth)) { |
1857 | printk("XFS: sunit and swidth must be specified together\n"); | 1862 | cmn_err(CE_WARN, |
1863 | "XFS: sunit and swidth must be specified together"); | ||
1858 | return EINVAL; | 1864 | return EINVAL; |
1859 | } | 1865 | } |
1860 | 1866 | ||
1861 | if (dsunit && (dswidth % dsunit != 0)) { | 1867 | if (dsunit && (dswidth % dsunit != 0)) { |
1862 | printk( | 1868 | cmn_err(CE_WARN, |
1863 | "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)\n", | 1869 | "XFS: stripe width (%d) must be a multiple of the stripe unit (%d)", |
1864 | dswidth, dsunit); | 1870 | dswidth, dsunit); |
1865 | return EINVAL; | 1871 | return EINVAL; |
1866 | } | 1872 | } |
@@ -1907,7 +1913,7 @@ xfs_showargs( | |||
1907 | }; | 1913 | }; |
1908 | struct proc_xfs_info *xfs_infop; | 1914 | struct proc_xfs_info *xfs_infop; |
1909 | struct xfs_mount *mp = XFS_BHVTOM(bhv); | 1915 | struct xfs_mount *mp = XFS_BHVTOM(bhv); |
1910 | struct vfs *vfsp = XFS_MTOVFS(mp); | 1916 | struct bhv_vfs *vfsp = XFS_MTOVFS(mp); |
1911 | 1917 | ||
1912 | for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) { | 1918 | for (xfs_infop = xfs_info; xfs_infop->flag; xfs_infop++) { |
1913 | if (mp->m_flags & xfs_infop->flag) | 1919 | if (mp->m_flags & xfs_infop->flag) |
@@ -1967,7 +1973,7 @@ xfs_freeze( | |||
1967 | } | 1973 | } |
1968 | 1974 | ||
1969 | 1975 | ||
1970 | vfsops_t xfs_vfsops = { | 1976 | bhv_vfsops_t xfs_vfsops = { |
1971 | BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), | 1977 | BHV_IDENTITY_INIT(VFS_BHV_XFS,VFS_POSITION_XFS), |
1972 | .vfs_parseargs = xfs_parseargs, | 1978 | .vfs_parseargs = xfs_parseargs, |
1973 | .vfs_showargs = xfs_showargs, | 1979 | .vfs_showargs = xfs_showargs, |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 7027ae68ee38..00a6b7dc24a0 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2000-2005 Silicon Graphics, Inc. | 2 | * Copyright (c) 2000-2006 Silicon Graphics, Inc. |
3 | * All Rights Reserved. | 3 | * All Rights Reserved. |
4 | * | 4 | * |
5 | * This program is free software; you can redistribute it and/or | 5 | * This program is free software; you can redistribute it and/or |
@@ -16,8 +16,6 @@ | |||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | 16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/capability.h> | ||
20 | |||
21 | #include "xfs.h" | 19 | #include "xfs.h" |
22 | #include "xfs_fs.h" | 20 | #include "xfs_fs.h" |
23 | #include "xfs_types.h" | 21 | #include "xfs_types.h" |
@@ -27,7 +25,6 @@ | |||
27 | #include "xfs_trans.h" | 25 | #include "xfs_trans.h" |
28 | #include "xfs_sb.h" | 26 | #include "xfs_sb.h" |
29 | #include "xfs_ag.h" | 27 | #include "xfs_ag.h" |
30 | #include "xfs_dir.h" | ||
31 | #include "xfs_dir2.h" | 28 | #include "xfs_dir2.h" |
32 | #include "xfs_dmapi.h" | 29 | #include "xfs_dmapi.h" |
33 | #include "xfs_mount.h" | 30 | #include "xfs_mount.h" |
@@ -35,13 +32,11 @@ | |||
35 | #include "xfs_bmap_btree.h" | 32 | #include "xfs_bmap_btree.h" |
36 | #include "xfs_alloc_btree.h" | 33 | #include "xfs_alloc_btree.h" |
37 | #include "xfs_ialloc_btree.h" | 34 | #include "xfs_ialloc_btree.h" |
38 | #include "xfs_dir_sf.h" | ||
39 | #include "xfs_dir2_sf.h" | 35 | #include "xfs_dir2_sf.h" |
40 | #include "xfs_attr_sf.h" | 36 | #include "xfs_attr_sf.h" |
41 | #include "xfs_dinode.h" | 37 | #include "xfs_dinode.h" |
42 | #include "xfs_inode.h" | 38 | #include "xfs_inode.h" |
43 | #include "xfs_inode_item.h" | 39 | #include "xfs_inode_item.h" |
44 | #include "xfs_dir_leaf.h" | ||
45 | #include "xfs_itable.h" | 40 | #include "xfs_itable.h" |
46 | #include "xfs_btree.h" | 41 | #include "xfs_btree.h" |
47 | #include "xfs_ialloc.h" | 42 | #include "xfs_ialloc.h" |
@@ -58,32 +53,14 @@ | |||
58 | #include "xfs_log_priv.h" | 53 | #include "xfs_log_priv.h" |
59 | #include "xfs_mac.h" | 54 | #include "xfs_mac.h" |
60 | 55 | ||
61 | |||
62 | /* | ||
63 | * The maximum pathlen is 1024 bytes. Since the minimum file system | ||
64 | * blocksize is 512 bytes, we can get a max of 2 extents back from | ||
65 | * bmapi. | ||
66 | */ | ||
67 | #define SYMLINK_MAPS 2 | ||
68 | |||
69 | /* | ||
70 | * For xfs, we check that the file isn't too big to be opened by this kernel. | ||
71 | * No other open action is required for regular files. Devices are handled | ||
72 | * through the specfs file system, pipes through fifofs. Device and | ||
73 | * fifo vnodes are "wrapped" by specfs and fifofs vnodes, respectively, | ||
74 | * when a new vnode is first looked up or created. | ||
75 | */ | ||
76 | STATIC int | 56 | STATIC int |
77 | xfs_open( | 57 | xfs_open( |
78 | bhv_desc_t *bdp, | 58 | bhv_desc_t *bdp, |
79 | cred_t *credp) | 59 | cred_t *credp) |
80 | { | 60 | { |
81 | int mode; | 61 | int mode; |
82 | vnode_t *vp; | 62 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); |
83 | xfs_inode_t *ip; | 63 | xfs_inode_t *ip = XFS_BHVTOI(bdp); |
84 | |||
85 | vp = BHV_TO_VNODE(bdp); | ||
86 | ip = XFS_BHVTOI(bdp); | ||
87 | 64 | ||
88 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | 65 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) |
89 | return XFS_ERROR(EIO); | 66 | return XFS_ERROR(EIO); |
@@ -101,6 +78,35 @@ xfs_open( | |||
101 | return 0; | 78 | return 0; |
102 | } | 79 | } |
103 | 80 | ||
81 | STATIC int | ||
82 | xfs_close( | ||
83 | bhv_desc_t *bdp, | ||
84 | int flags, | ||
85 | lastclose_t lastclose, | ||
86 | cred_t *credp) | ||
87 | { | ||
88 | bhv_vnode_t *vp = BHV_TO_VNODE(bdp); | ||
89 | xfs_inode_t *ip = XFS_BHVTOI(bdp); | ||
90 | |||
91 | if (XFS_FORCED_SHUTDOWN(ip->i_mount)) | ||
92 | return XFS_ERROR(EIO); | ||
93 | |||
94 | if (lastclose != L_TRUE || !VN_ISREG(vp)) | ||
95 | return 0; | ||
96 | |||
97 | /* | ||
98 | * If we previously truncated this file and removed old data in | ||
99 | * the process, we want to initiate "early" writeout on the last | ||
100 | * close. This is an attempt to combat the notorious NULL files | ||
101 | * problem which is particularly noticable from a truncate down, | ||
102 | * buffered (re-)write (delalloc), followed by a crash. What we | ||
103 | * are effectively doing here is significantly reducing the time | ||
104 | * window where we'd otherwise be exposed to that problem. | ||
105 | */ | ||
106 | if (VUNTRUNCATE(vp) && VN_DIRTY(vp) && ip->i_delayed_blks > 0) | ||
107 | return bhv_vop_flush_pages(vp, 0, -1, XFS_B_ASYNC, FI_NONE); | ||
108 | return 0; | ||
109 | } | ||
104 | 110 | ||
105 | /* | 111 | /* |
106 | * xfs_getattr | 112 | * xfs_getattr |
@@ -108,13 +114,13 @@ xfs_open( | |||
108 | STATIC int | 114 | STATIC int |
109 | xfs_getattr( | 115 | xfs_getattr( |
110 | bhv_desc_t *bdp, | 116 | bhv_desc_t *bdp, |
111 | vattr_t *vap, | 117 | bhv_vattr_t *vap, |
112 | int flags, | 118 | int flags, |
113 | cred_t *credp) | 119 | cred_t *credp) |
114 | { | 120 | { |
115 | xfs_inode_t *ip; | 121 | xfs_inode_t *ip; |
116 | xfs_mount_t *mp; | 122 | xfs_mount_t *mp; |
117 | vnode_t *vp; | 123 | bhv_vnode_t *vp; |
118 | 124 | ||
119 | vp = BHV_TO_VNODE(bdp); | 125 | vp = BHV_TO_VNODE(bdp); |
120 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 126 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
@@ -241,7 +247,7 @@ xfs_getattr( | |||
241 | int | 247 | int |
242 | xfs_setattr( | 248 | xfs_setattr( |
243 | bhv_desc_t *bdp, | 249 | bhv_desc_t *bdp, |
244 | vattr_t *vap, | 250 | bhv_vattr_t *vap, |
245 | int flags, | 251 | int flags, |
246 | cred_t *credp) | 252 | cred_t *credp) |
247 | { | 253 | { |
@@ -255,7 +261,7 @@ xfs_setattr( | |||
255 | uid_t uid=0, iuid=0; | 261 | uid_t uid=0, iuid=0; |
256 | gid_t gid=0, igid=0; | 262 | gid_t gid=0, igid=0; |
257 | int timeflags = 0; | 263 | int timeflags = 0; |
258 | vnode_t *vp; | 264 | bhv_vnode_t *vp; |
259 | xfs_prid_t projid=0, iprojid=0; | 265 | xfs_prid_t projid=0, iprojid=0; |
260 | int mandlock_before, mandlock_after; | 266 | int mandlock_before, mandlock_after; |
261 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; | 267 | struct xfs_dquot *udqp, *gdqp, *olddquot1, *olddquot2; |
@@ -347,7 +353,6 @@ xfs_setattr( | |||
347 | */ | 353 | */ |
348 | tp = NULL; | 354 | tp = NULL; |
349 | lock_flags = XFS_ILOCK_EXCL; | 355 | lock_flags = XFS_ILOCK_EXCL; |
350 | ASSERT(flags & ATTR_NOLOCK ? flags & ATTR_DMI : 1); | ||
351 | if (flags & ATTR_NOLOCK) | 356 | if (flags & ATTR_NOLOCK) |
352 | need_iolock = 0; | 357 | need_iolock = 0; |
353 | if (!(mask & XFS_AT_SIZE)) { | 358 | if (!(mask & XFS_AT_SIZE)) { |
@@ -666,9 +671,17 @@ xfs_setattr( | |||
666 | ((ip->i_d.di_nlink != 0 || | 671 | ((ip->i_d.di_nlink != 0 || |
667 | !(mp->m_flags & XFS_MOUNT_WSYNC)) | 672 | !(mp->m_flags & XFS_MOUNT_WSYNC)) |
668 | ? 1 : 0)); | 673 | ? 1 : 0)); |
669 | if (code) { | 674 | if (code) |
670 | goto abort_return; | 675 | goto abort_return; |
671 | } | 676 | /* |
677 | * Truncated "down", so we're removing references | ||
678 | * to old data here - if we now delay flushing for | ||
679 | * a long time, we expose ourselves unduly to the | ||
680 | * notorious NULL files problem. So, we mark this | ||
681 | * vnode and flush it when the file is closed, and | ||
682 | * do not wait the usual (long) time for writeout. | ||
683 | */ | ||
684 | VTRUNCATE(vp); | ||
672 | } | 685 | } |
673 | /* | 686 | /* |
674 | * Have to do this even if the file's size doesn't change. | 687 | * Have to do this even if the file's size doesn't change. |
@@ -800,6 +813,8 @@ xfs_setattr( | |||
800 | di_flags |= XFS_DIFLAG_NODUMP; | 813 | di_flags |= XFS_DIFLAG_NODUMP; |
801 | if (vap->va_xflags & XFS_XFLAG_PROJINHERIT) | 814 | if (vap->va_xflags & XFS_XFLAG_PROJINHERIT) |
802 | di_flags |= XFS_DIFLAG_PROJINHERIT; | 815 | di_flags |= XFS_DIFLAG_PROJINHERIT; |
816 | if (vap->va_xflags & XFS_XFLAG_NODEFRAG) | ||
817 | di_flags |= XFS_DIFLAG_NODEFRAG; | ||
803 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { | 818 | if ((ip->i_d.di_mode & S_IFMT) == S_IFDIR) { |
804 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) | 819 | if (vap->va_xflags & XFS_XFLAG_RTINHERIT) |
805 | di_flags |= XFS_DIFLAG_RTINHERIT; | 820 | di_flags |= XFS_DIFLAG_RTINHERIT; |
@@ -869,7 +884,7 @@ xfs_setattr( | |||
869 | */ | 884 | */ |
870 | mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); | 885 | mandlock_after = MANDLOCK(vp, ip->i_d.di_mode); |
871 | if (mandlock_before != mandlock_after) { | 886 | if (mandlock_before != mandlock_after) { |
872 | VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_ENF_LOCKING, | 887 | bhv_vop_vnode_change(vp, VCHANGE_FLAGS_ENF_LOCKING, |
873 | mandlock_after); | 888 | mandlock_after); |
874 | } | 889 | } |
875 | 890 | ||
@@ -936,6 +951,13 @@ xfs_access( | |||
936 | 951 | ||
937 | 952 | ||
938 | /* | 953 | /* |
954 | * The maximum pathlen is 1024 bytes. Since the minimum file system | ||
955 | * blocksize is 512 bytes, we can get a max of 2 extents back from | ||
956 | * bmapi. | ||
957 | */ | ||
958 | #define SYMLINK_MAPS 2 | ||
959 | |||
960 | /* | ||
939 | * xfs_readlink | 961 | * xfs_readlink |
940 | * | 962 | * |
941 | */ | 963 | */ |
@@ -950,7 +972,7 @@ xfs_readlink( | |||
950 | int count; | 972 | int count; |
951 | xfs_off_t offset; | 973 | xfs_off_t offset; |
952 | int pathlen; | 974 | int pathlen; |
953 | vnode_t *vp; | 975 | bhv_vnode_t *vp; |
954 | int error = 0; | 976 | int error = 0; |
955 | xfs_mount_t *mp; | 977 | xfs_mount_t *mp; |
956 | int nmaps; | 978 | int nmaps; |
@@ -1000,7 +1022,7 @@ xfs_readlink( | |||
1000 | nmaps = SYMLINK_MAPS; | 1022 | nmaps = SYMLINK_MAPS; |
1001 | 1023 | ||
1002 | error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), | 1024 | error = xfs_bmapi(NULL, ip, 0, XFS_B_TO_FSB(mp, pathlen), |
1003 | 0, NULL, 0, mval, &nmaps, NULL); | 1025 | 0, NULL, 0, mval, &nmaps, NULL, NULL); |
1004 | 1026 | ||
1005 | if (error) { | 1027 | if (error) { |
1006 | goto error_return; | 1028 | goto error_return; |
@@ -1208,8 +1230,8 @@ xfs_inactive_free_eofblocks( | |||
1208 | 1230 | ||
1209 | nimaps = 1; | 1231 | nimaps = 1; |
1210 | xfs_ilock(ip, XFS_ILOCK_SHARED); | 1232 | xfs_ilock(ip, XFS_ILOCK_SHARED); |
1211 | error = xfs_bmapi(NULL, ip, end_fsb, map_len, 0, | 1233 | error = XFS_BMAPI(mp, NULL, &ip->i_iocore, end_fsb, map_len, 0, |
1212 | NULL, 0, &imap, &nimaps, NULL); | 1234 | NULL, 0, &imap, &nimaps, NULL, NULL); |
1213 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | 1235 | xfs_iunlock(ip, XFS_ILOCK_SHARED); |
1214 | 1236 | ||
1215 | if (!error && (nimaps != 0) && | 1237 | if (!error && (nimaps != 0) && |
@@ -1338,7 +1360,7 @@ xfs_inactive_symlink_rmt( | |||
1338 | nmaps = ARRAY_SIZE(mval); | 1360 | nmaps = ARRAY_SIZE(mval); |
1339 | if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), | 1361 | if ((error = xfs_bmapi(tp, ip, 0, XFS_B_TO_FSB(mp, size), |
1340 | XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, | 1362 | XFS_BMAPI_METADATA, &first_block, 0, mval, &nmaps, |
1341 | &free_list))) | 1363 | &free_list, NULL))) |
1342 | goto error0; | 1364 | goto error0; |
1343 | /* | 1365 | /* |
1344 | * Invalidate the block(s). | 1366 | * Invalidate the block(s). |
@@ -1353,7 +1375,7 @@ xfs_inactive_symlink_rmt( | |||
1353 | * Unmap the dead block(s) to the free_list. | 1375 | * Unmap the dead block(s) to the free_list. |
1354 | */ | 1376 | */ |
1355 | if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, | 1377 | if ((error = xfs_bunmapi(tp, ip, 0, size, XFS_BMAPI_METADATA, nmaps, |
1356 | &first_block, &free_list, &done))) | 1378 | &first_block, &free_list, NULL, &done))) |
1357 | goto error1; | 1379 | goto error1; |
1358 | ASSERT(done); | 1380 | ASSERT(done); |
1359 | /* | 1381 | /* |
@@ -1469,9 +1491,6 @@ xfs_inactive_symlink_local( | |||
1469 | return 0; | 1491 | return 0; |
1470 | } | 1492 | } |
1471 | 1493 | ||
1472 | /* | ||
1473 | * | ||
1474 | */ | ||
1475 | STATIC int | 1494 | STATIC int |
1476 | xfs_inactive_attrs( | 1495 | xfs_inactive_attrs( |
1477 | xfs_inode_t *ip, | 1496 | xfs_inode_t *ip, |
@@ -1524,16 +1543,16 @@ xfs_release( | |||
1524 | bhv_desc_t *bdp) | 1543 | bhv_desc_t *bdp) |
1525 | { | 1544 | { |
1526 | xfs_inode_t *ip; | 1545 | xfs_inode_t *ip; |
1527 | vnode_t *vp; | 1546 | bhv_vnode_t *vp; |
1528 | xfs_mount_t *mp; | 1547 | xfs_mount_t *mp; |
1529 | int error; | 1548 | int error; |
1530 | 1549 | ||
1531 | vp = BHV_TO_VNODE(bdp); | 1550 | vp = BHV_TO_VNODE(bdp); |
1532 | ip = XFS_BHVTOI(bdp); | 1551 | ip = XFS_BHVTOI(bdp); |
1552 | mp = ip->i_mount; | ||
1533 | 1553 | ||
1534 | if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) { | 1554 | if (!VN_ISREG(vp) || (ip->i_d.di_mode == 0)) |
1535 | return 0; | 1555 | return 0; |
1536 | } | ||
1537 | 1556 | ||
1538 | /* If this is a read-only mount, don't do this (would generate I/O) */ | 1557 | /* If this is a read-only mount, don't do this (would generate I/O) */ |
1539 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) | 1558 | if (vp->v_vfsp->vfs_flag & VFS_RDONLY) |
@@ -1545,8 +1564,6 @@ xfs_release( | |||
1545 | return 0; | 1564 | return 0; |
1546 | #endif | 1565 | #endif |
1547 | 1566 | ||
1548 | mp = ip->i_mount; | ||
1549 | |||
1550 | if (ip->i_d.di_nlink != 0) { | 1567 | if (ip->i_d.di_nlink != 0) { |
1551 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && | 1568 | if ((((ip->i_d.di_mode & S_IFMT) == S_IFREG) && |
1552 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || | 1569 | ((ip->i_d.di_size > 0) || (VN_CACHED(vp) > 0 || |
@@ -1579,8 +1596,8 @@ xfs_inactive( | |||
1579 | cred_t *credp) | 1596 | cred_t *credp) |
1580 | { | 1597 | { |
1581 | xfs_inode_t *ip; | 1598 | xfs_inode_t *ip; |
1582 | vnode_t *vp; | 1599 | bhv_vnode_t *vp; |
1583 | xfs_bmap_free_t free_list; | 1600 | xfs_bmap_free_t free_list; |
1584 | xfs_fsblock_t first_block; | 1601 | xfs_fsblock_t first_block; |
1585 | int committed; | 1602 | int committed; |
1586 | xfs_trans_t *tp; | 1603 | xfs_trans_t *tp; |
@@ -1760,7 +1777,7 @@ xfs_inactive( | |||
1760 | cmn_err(CE_NOTE, | 1777 | cmn_err(CE_NOTE, |
1761 | "xfs_inactive: xfs_ifree() returned an error = %d on %s", | 1778 | "xfs_inactive: xfs_ifree() returned an error = %d on %s", |
1762 | error, mp->m_fsname); | 1779 | error, mp->m_fsname); |
1763 | xfs_force_shutdown(mp, XFS_METADATA_IO_ERROR); | 1780 | xfs_force_shutdown(mp, SHUTDOWN_META_IO_ERROR); |
1764 | } | 1781 | } |
1765 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); | 1782 | xfs_trans_cancel(tp, XFS_TRANS_RELEASE_LOG_RES|XFS_TRANS_ABORT); |
1766 | } else { | 1783 | } else { |
@@ -1795,17 +1812,17 @@ xfs_inactive( | |||
1795 | STATIC int | 1812 | STATIC int |
1796 | xfs_lookup( | 1813 | xfs_lookup( |
1797 | bhv_desc_t *dir_bdp, | 1814 | bhv_desc_t *dir_bdp, |
1798 | vname_t *dentry, | 1815 | bhv_vname_t *dentry, |
1799 | vnode_t **vpp, | 1816 | bhv_vnode_t **vpp, |
1800 | int flags, | 1817 | int flags, |
1801 | vnode_t *rdir, | 1818 | bhv_vnode_t *rdir, |
1802 | cred_t *credp) | 1819 | cred_t *credp) |
1803 | { | 1820 | { |
1804 | xfs_inode_t *dp, *ip; | 1821 | xfs_inode_t *dp, *ip; |
1805 | xfs_ino_t e_inum; | 1822 | xfs_ino_t e_inum; |
1806 | int error; | 1823 | int error; |
1807 | uint lock_mode; | 1824 | uint lock_mode; |
1808 | vnode_t *dir_vp; | 1825 | bhv_vnode_t *dir_vp; |
1809 | 1826 | ||
1810 | dir_vp = BHV_TO_VNODE(dir_bdp); | 1827 | dir_vp = BHV_TO_VNODE(dir_bdp); |
1811 | vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); | 1828 | vn_trace_entry(dir_vp, __FUNCTION__, (inst_t *)__return_address); |
@@ -1832,15 +1849,15 @@ xfs_lookup( | |||
1832 | STATIC int | 1849 | STATIC int |
1833 | xfs_create( | 1850 | xfs_create( |
1834 | bhv_desc_t *dir_bdp, | 1851 | bhv_desc_t *dir_bdp, |
1835 | vname_t *dentry, | 1852 | bhv_vname_t *dentry, |
1836 | vattr_t *vap, | 1853 | bhv_vattr_t *vap, |
1837 | vnode_t **vpp, | 1854 | bhv_vnode_t **vpp, |
1838 | cred_t *credp) | 1855 | cred_t *credp) |
1839 | { | 1856 | { |
1840 | char *name = VNAME(dentry); | 1857 | char *name = VNAME(dentry); |
1841 | vnode_t *dir_vp; | 1858 | bhv_vnode_t *dir_vp; |
1842 | xfs_inode_t *dp, *ip; | 1859 | xfs_inode_t *dp, *ip; |
1843 | vnode_t *vp=NULL; | 1860 | bhv_vnode_t *vp = NULL; |
1844 | xfs_trans_t *tp; | 1861 | xfs_trans_t *tp; |
1845 | xfs_mount_t *mp; | 1862 | xfs_mount_t *mp; |
1846 | xfs_dev_t rdev; | 1863 | xfs_dev_t rdev; |
@@ -1938,8 +1955,7 @@ xfs_create( | |||
1938 | if (error) | 1955 | if (error) |
1939 | goto error_return; | 1956 | goto error_return; |
1940 | 1957 | ||
1941 | if (resblks == 0 && | 1958 | if (resblks == 0 && (error = xfs_dir_canenter(tp, dp, name, namelen))) |
1942 | (error = XFS_DIR_CANENTER(mp, tp, dp, name, namelen))) | ||
1943 | goto error_return; | 1959 | goto error_return; |
1944 | rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; | 1960 | rdev = (vap->va_mask & XFS_AT_RDEV) ? vap->va_rdev : 0; |
1945 | error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, | 1961 | error = xfs_dir_ialloc(&tp, dp, vap->va_mode, 1, |
@@ -1970,9 +1986,9 @@ xfs_create( | |||
1970 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | 1986 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); |
1971 | dp_joined_to_trans = B_TRUE; | 1987 | dp_joined_to_trans = B_TRUE; |
1972 | 1988 | ||
1973 | error = XFS_DIR_CREATENAME(mp, tp, dp, name, namelen, ip->i_ino, | 1989 | error = xfs_dir_createname(tp, dp, name, namelen, ip->i_ino, |
1974 | &first_block, &free_list, | 1990 | &first_block, &free_list, resblks ? |
1975 | resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); | 1991 | resblks - XFS_IALLOC_SPACE_RES(mp) : 0); |
1976 | if (error) { | 1992 | if (error) { |
1977 | ASSERT(error != ENOSPC); | 1993 | ASSERT(error != ENOSPC); |
1978 | goto abort_return; | 1994 | goto abort_return; |
@@ -2026,7 +2042,7 @@ xfs_create( | |||
2026 | * Propagate the fact that the vnode changed after the | 2042 | * Propagate the fact that the vnode changed after the |
2027 | * xfs_inode locks have been released. | 2043 | * xfs_inode locks have been released. |
2028 | */ | 2044 | */ |
2029 | VOP_VNODE_CHANGE(vp, VCHANGE_FLAGS_TRUNCATED, 3); | 2045 | bhv_vop_vnode_change(vp, VCHANGE_FLAGS_TRUNCATED, 3); |
2030 | 2046 | ||
2031 | *vpp = vp; | 2047 | *vpp = vp; |
2032 | 2048 | ||
@@ -2107,7 +2123,7 @@ int xfs_rm_attempts; | |||
2107 | STATIC int | 2123 | STATIC int |
2108 | xfs_lock_dir_and_entry( | 2124 | xfs_lock_dir_and_entry( |
2109 | xfs_inode_t *dp, | 2125 | xfs_inode_t *dp, |
2110 | vname_t *dentry, | 2126 | bhv_vname_t *dentry, |
2111 | xfs_inode_t *ip) /* inode of entry 'name' */ | 2127 | xfs_inode_t *ip) /* inode of entry 'name' */ |
2112 | { | 2128 | { |
2113 | int attempts; | 2129 | int attempts; |
@@ -2321,10 +2337,10 @@ int remove_which_error_return = 0; | |||
2321 | STATIC int | 2337 | STATIC int |
2322 | xfs_remove( | 2338 | xfs_remove( |
2323 | bhv_desc_t *dir_bdp, | 2339 | bhv_desc_t *dir_bdp, |
2324 | vname_t *dentry, | 2340 | bhv_vname_t *dentry, |
2325 | cred_t *credp) | 2341 | cred_t *credp) |
2326 | { | 2342 | { |
2327 | vnode_t *dir_vp; | 2343 | bhv_vnode_t *dir_vp; |
2328 | char *name = VNAME(dentry); | 2344 | char *name = VNAME(dentry); |
2329 | xfs_inode_t *dp, *ip; | 2345 | xfs_inode_t *dp, *ip; |
2330 | xfs_trans_t *tp = NULL; | 2346 | xfs_trans_t *tp = NULL; |
@@ -2448,8 +2464,8 @@ xfs_remove( | |||
2448 | * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. | 2464 | * Entry must exist since we did a lookup in xfs_lock_dir_and_entry. |
2449 | */ | 2465 | */ |
2450 | XFS_BMAP_INIT(&free_list, &first_block); | 2466 | XFS_BMAP_INIT(&free_list, &first_block); |
2451 | error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, ip->i_ino, | 2467 | error = xfs_dir_removename(tp, dp, name, namelen, ip->i_ino, |
2452 | &first_block, &free_list, 0); | 2468 | &first_block, &free_list, 0); |
2453 | if (error) { | 2469 | if (error) { |
2454 | ASSERT(error != ENOENT); | 2470 | ASSERT(error != ENOENT); |
2455 | REMOVE_DEBUG_TRACE(__LINE__); | 2471 | REMOVE_DEBUG_TRACE(__LINE__); |
@@ -2511,7 +2527,7 @@ xfs_remove( | |||
2511 | /* | 2527 | /* |
2512 | * Let interposed file systems know about removed links. | 2528 | * Let interposed file systems know about removed links. |
2513 | */ | 2529 | */ |
2514 | VOP_LINK_REMOVED(XFS_ITOV(ip), dir_vp, link_zero); | 2530 | bhv_vop_link_removed(XFS_ITOV(ip), dir_vp, link_zero); |
2515 | 2531 | ||
2516 | IRELE(ip); | 2532 | IRELE(ip); |
2517 | 2533 | ||
@@ -2564,8 +2580,8 @@ xfs_remove( | |||
2564 | STATIC int | 2580 | STATIC int |
2565 | xfs_link( | 2581 | xfs_link( |
2566 | bhv_desc_t *target_dir_bdp, | 2582 | bhv_desc_t *target_dir_bdp, |
2567 | vnode_t *src_vp, | 2583 | bhv_vnode_t *src_vp, |
2568 | vname_t *dentry, | 2584 | bhv_vname_t *dentry, |
2569 | cred_t *credp) | 2585 | cred_t *credp) |
2570 | { | 2586 | { |
2571 | xfs_inode_t *tdp, *sip; | 2587 | xfs_inode_t *tdp, *sip; |
@@ -2577,7 +2593,7 @@ xfs_link( | |||
2577 | xfs_fsblock_t first_block; | 2593 | xfs_fsblock_t first_block; |
2578 | int cancel_flags; | 2594 | int cancel_flags; |
2579 | int committed; | 2595 | int committed; |
2580 | vnode_t *target_dir_vp; | 2596 | bhv_vnode_t *target_dir_vp; |
2581 | int resblks; | 2597 | int resblks; |
2582 | char *target_name = VNAME(dentry); | 2598 | char *target_name = VNAME(dentry); |
2583 | int target_namelen; | 2599 | int target_namelen; |
@@ -2668,13 +2684,12 @@ xfs_link( | |||
2668 | } | 2684 | } |
2669 | 2685 | ||
2670 | if (resblks == 0 && | 2686 | if (resblks == 0 && |
2671 | (error = XFS_DIR_CANENTER(mp, tp, tdp, target_name, | 2687 | (error = xfs_dir_canenter(tp, tdp, target_name, target_namelen))) |
2672 | target_namelen))) | ||
2673 | goto error_return; | 2688 | goto error_return; |
2674 | 2689 | ||
2675 | XFS_BMAP_INIT(&free_list, &first_block); | 2690 | XFS_BMAP_INIT(&free_list, &first_block); |
2676 | 2691 | ||
2677 | error = XFS_DIR_CREATENAME(mp, tp, tdp, target_name, target_namelen, | 2692 | error = xfs_dir_createname(tp, tdp, target_name, target_namelen, |
2678 | sip->i_ino, &first_block, &free_list, | 2693 | sip->i_ino, &first_block, &free_list, |
2679 | resblks); | 2694 | resblks); |
2680 | if (error) | 2695 | if (error) |
@@ -2734,15 +2749,15 @@ std_return: | |||
2734 | STATIC int | 2749 | STATIC int |
2735 | xfs_mkdir( | 2750 | xfs_mkdir( |
2736 | bhv_desc_t *dir_bdp, | 2751 | bhv_desc_t *dir_bdp, |
2737 | vname_t *dentry, | 2752 | bhv_vname_t *dentry, |
2738 | vattr_t *vap, | 2753 | bhv_vattr_t *vap, |
2739 | vnode_t **vpp, | 2754 | bhv_vnode_t **vpp, |
2740 | cred_t *credp) | 2755 | cred_t *credp) |
2741 | { | 2756 | { |
2742 | char *dir_name = VNAME(dentry); | 2757 | char *dir_name = VNAME(dentry); |
2743 | xfs_inode_t *dp; | 2758 | xfs_inode_t *dp; |
2744 | xfs_inode_t *cdp; /* inode of created dir */ | 2759 | xfs_inode_t *cdp; /* inode of created dir */ |
2745 | vnode_t *cvp; /* vnode of created dir */ | 2760 | bhv_vnode_t *cvp; /* vnode of created dir */ |
2746 | xfs_trans_t *tp; | 2761 | xfs_trans_t *tp; |
2747 | xfs_mount_t *mp; | 2762 | xfs_mount_t *mp; |
2748 | int cancel_flags; | 2763 | int cancel_flags; |
@@ -2750,7 +2765,7 @@ xfs_mkdir( | |||
2750 | int committed; | 2765 | int committed; |
2751 | xfs_bmap_free_t free_list; | 2766 | xfs_bmap_free_t free_list; |
2752 | xfs_fsblock_t first_block; | 2767 | xfs_fsblock_t first_block; |
2753 | vnode_t *dir_vp; | 2768 | bhv_vnode_t *dir_vp; |
2754 | boolean_t dp_joined_to_trans; | 2769 | boolean_t dp_joined_to_trans; |
2755 | boolean_t created = B_FALSE; | 2770 | boolean_t created = B_FALSE; |
2756 | int dm_event_sent = 0; | 2771 | int dm_event_sent = 0; |
@@ -2840,7 +2855,7 @@ xfs_mkdir( | |||
2840 | goto error_return; | 2855 | goto error_return; |
2841 | 2856 | ||
2842 | if (resblks == 0 && | 2857 | if (resblks == 0 && |
2843 | (error = XFS_DIR_CANENTER(mp, tp, dp, dir_name, dir_namelen))) | 2858 | (error = xfs_dir_canenter(tp, dp, dir_name, dir_namelen))) |
2844 | goto error_return; | 2859 | goto error_return; |
2845 | /* | 2860 | /* |
2846 | * create the directory inode. | 2861 | * create the directory inode. |
@@ -2867,9 +2882,9 @@ xfs_mkdir( | |||
2867 | 2882 | ||
2868 | XFS_BMAP_INIT(&free_list, &first_block); | 2883 | XFS_BMAP_INIT(&free_list, &first_block); |
2869 | 2884 | ||
2870 | error = XFS_DIR_CREATENAME(mp, tp, dp, dir_name, dir_namelen, | 2885 | error = xfs_dir_createname(tp, dp, dir_name, dir_namelen, cdp->i_ino, |
2871 | cdp->i_ino, &first_block, &free_list, | 2886 | &first_block, &free_list, resblks ? |
2872 | resblks ? resblks - XFS_IALLOC_SPACE_RES(mp) : 0); | 2887 | resblks - XFS_IALLOC_SPACE_RES(mp) : 0); |
2873 | if (error) { | 2888 | if (error) { |
2874 | ASSERT(error != ENOSPC); | 2889 | ASSERT(error != ENOSPC); |
2875 | goto error1; | 2890 | goto error1; |
@@ -2883,16 +2898,14 @@ xfs_mkdir( | |||
2883 | */ | 2898 | */ |
2884 | dp->i_gen++; | 2899 | dp->i_gen++; |
2885 | 2900 | ||
2886 | error = XFS_DIR_INIT(mp, tp, cdp, dp); | 2901 | error = xfs_dir_init(tp, cdp, dp); |
2887 | if (error) { | 2902 | if (error) |
2888 | goto error2; | 2903 | goto error2; |
2889 | } | ||
2890 | 2904 | ||
2891 | cdp->i_gen = 1; | 2905 | cdp->i_gen = 1; |
2892 | error = xfs_bumplink(tp, dp); | 2906 | error = xfs_bumplink(tp, dp); |
2893 | if (error) { | 2907 | if (error) |
2894 | goto error2; | 2908 | goto error2; |
2895 | } | ||
2896 | 2909 | ||
2897 | cvp = XFS_ITOV(cdp); | 2910 | cvp = XFS_ITOV(cdp); |
2898 | 2911 | ||
@@ -2969,7 +2982,7 @@ std_return: | |||
2969 | STATIC int | 2982 | STATIC int |
2970 | xfs_rmdir( | 2983 | xfs_rmdir( |
2971 | bhv_desc_t *dir_bdp, | 2984 | bhv_desc_t *dir_bdp, |
2972 | vname_t *dentry, | 2985 | bhv_vname_t *dentry, |
2973 | cred_t *credp) | 2986 | cred_t *credp) |
2974 | { | 2987 | { |
2975 | char *name = VNAME(dentry); | 2988 | char *name = VNAME(dentry); |
@@ -2982,7 +2995,7 @@ xfs_rmdir( | |||
2982 | xfs_fsblock_t first_block; | 2995 | xfs_fsblock_t first_block; |
2983 | int cancel_flags; | 2996 | int cancel_flags; |
2984 | int committed; | 2997 | int committed; |
2985 | vnode_t *dir_vp; | 2998 | bhv_vnode_t *dir_vp; |
2986 | int dm_di_mode = 0; | 2999 | int dm_di_mode = 0; |
2987 | int last_cdp_link; | 3000 | int last_cdp_link; |
2988 | int namelen; | 3001 | int namelen; |
@@ -3101,16 +3114,15 @@ xfs_rmdir( | |||
3101 | error = XFS_ERROR(ENOTEMPTY); | 3114 | error = XFS_ERROR(ENOTEMPTY); |
3102 | goto error_return; | 3115 | goto error_return; |
3103 | } | 3116 | } |
3104 | if (!XFS_DIR_ISEMPTY(mp, cdp)) { | 3117 | if (!xfs_dir_isempty(cdp)) { |
3105 | error = XFS_ERROR(ENOTEMPTY); | 3118 | error = XFS_ERROR(ENOTEMPTY); |
3106 | goto error_return; | 3119 | goto error_return; |
3107 | } | 3120 | } |
3108 | 3121 | ||
3109 | error = XFS_DIR_REMOVENAME(mp, tp, dp, name, namelen, cdp->i_ino, | 3122 | error = xfs_dir_removename(tp, dp, name, namelen, cdp->i_ino, |
3110 | &first_block, &free_list, resblks); | 3123 | &first_block, &free_list, resblks); |
3111 | if (error) { | 3124 | if (error) |
3112 | goto error1; | 3125 | goto error1; |
3113 | } | ||
3114 | 3126 | ||
3115 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 3127 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
3116 | 3128 | ||
@@ -3181,7 +3193,7 @@ xfs_rmdir( | |||
3181 | /* | 3193 | /* |
3182 | * Let interposed file systems know about removed links. | 3194 | * Let interposed file systems know about removed links. |
3183 | */ | 3195 | */ |
3184 | VOP_LINK_REMOVED(XFS_ITOV(cdp), dir_vp, last_cdp_link); | 3196 | bhv_vop_link_removed(XFS_ITOV(cdp), dir_vp, last_cdp_link); |
3185 | 3197 | ||
3186 | IRELE(cdp); | 3198 | IRELE(cdp); |
3187 | 3199 | ||
@@ -3209,8 +3221,6 @@ xfs_rmdir( | |||
3209 | 3221 | ||
3210 | 3222 | ||
3211 | /* | 3223 | /* |
3212 | * xfs_readdir | ||
3213 | * | ||
3214 | * Read dp's entries starting at uiop->uio_offset and translate them into | 3224 | * Read dp's entries starting at uiop->uio_offset and translate them into |
3215 | * bufsize bytes worth of struct dirents starting at bufbase. | 3225 | * bufsize bytes worth of struct dirents starting at bufbase. |
3216 | */ | 3226 | */ |
@@ -3230,28 +3240,23 @@ xfs_readdir( | |||
3230 | (inst_t *)__return_address); | 3240 | (inst_t *)__return_address); |
3231 | dp = XFS_BHVTOI(dir_bdp); | 3241 | dp = XFS_BHVTOI(dir_bdp); |
3232 | 3242 | ||
3233 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) { | 3243 | if (XFS_FORCED_SHUTDOWN(dp->i_mount)) |
3234 | return XFS_ERROR(EIO); | 3244 | return XFS_ERROR(EIO); |
3235 | } | ||
3236 | 3245 | ||
3237 | lock_mode = xfs_ilock_map_shared(dp); | 3246 | lock_mode = xfs_ilock_map_shared(dp); |
3238 | error = XFS_DIR_GETDENTS(dp->i_mount, tp, dp, uiop, eofp); | 3247 | error = xfs_dir_getdents(tp, dp, uiop, eofp); |
3239 | xfs_iunlock_map_shared(dp, lock_mode); | 3248 | xfs_iunlock_map_shared(dp, lock_mode); |
3240 | return error; | 3249 | return error; |
3241 | } | 3250 | } |
3242 | 3251 | ||
3243 | 3252 | ||
3244 | /* | ||
3245 | * xfs_symlink | ||
3246 | * | ||
3247 | */ | ||
3248 | STATIC int | 3253 | STATIC int |
3249 | xfs_symlink( | 3254 | xfs_symlink( |
3250 | bhv_desc_t *dir_bdp, | 3255 | bhv_desc_t *dir_bdp, |
3251 | vname_t *dentry, | 3256 | bhv_vname_t *dentry, |
3252 | vattr_t *vap, | 3257 | bhv_vattr_t *vap, |
3253 | char *target_path, | 3258 | char *target_path, |
3254 | vnode_t **vpp, | 3259 | bhv_vnode_t **vpp, |
3255 | cred_t *credp) | 3260 | cred_t *credp) |
3256 | { | 3261 | { |
3257 | xfs_trans_t *tp; | 3262 | xfs_trans_t *tp; |
@@ -3263,7 +3268,7 @@ xfs_symlink( | |||
3263 | xfs_bmap_free_t free_list; | 3268 | xfs_bmap_free_t free_list; |
3264 | xfs_fsblock_t first_block; | 3269 | xfs_fsblock_t first_block; |
3265 | boolean_t dp_joined_to_trans; | 3270 | boolean_t dp_joined_to_trans; |
3266 | vnode_t *dir_vp; | 3271 | bhv_vnode_t *dir_vp; |
3267 | uint cancel_flags; | 3272 | uint cancel_flags; |
3268 | int committed; | 3273 | int committed; |
3269 | xfs_fileoff_t first_fsb; | 3274 | xfs_fileoff_t first_fsb; |
@@ -3308,7 +3313,7 @@ xfs_symlink( | |||
3308 | int len, total; | 3313 | int len, total; |
3309 | char *path; | 3314 | char *path; |
3310 | 3315 | ||
3311 | for(total = 0, path = target_path; total < pathlen;) { | 3316 | for (total = 0, path = target_path; total < pathlen;) { |
3312 | /* | 3317 | /* |
3313 | * Skip any slashes. | 3318 | * Skip any slashes. |
3314 | */ | 3319 | */ |
@@ -3402,7 +3407,7 @@ xfs_symlink( | |||
3402 | * Check for ability to enter directory entry, if no space reserved. | 3407 | * Check for ability to enter directory entry, if no space reserved. |
3403 | */ | 3408 | */ |
3404 | if (resblks == 0 && | 3409 | if (resblks == 0 && |
3405 | (error = XFS_DIR_CANENTER(mp, tp, dp, link_name, link_namelen))) | 3410 | (error = xfs_dir_canenter(tp, dp, link_name, link_namelen))) |
3406 | goto error_return; | 3411 | goto error_return; |
3407 | /* | 3412 | /* |
3408 | * Initialize the bmap freelist prior to calling either | 3413 | * Initialize the bmap freelist prior to calling either |
@@ -3457,7 +3462,7 @@ xfs_symlink( | |||
3457 | error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, | 3462 | error = xfs_bmapi(tp, ip, first_fsb, fs_blocks, |
3458 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, | 3463 | XFS_BMAPI_WRITE | XFS_BMAPI_METADATA, |
3459 | &first_block, resblks, mval, &nmaps, | 3464 | &first_block, resblks, mval, &nmaps, |
3460 | &free_list); | 3465 | &free_list, NULL); |
3461 | if (error) { | 3466 | if (error) { |
3462 | goto error1; | 3467 | goto error1; |
3463 | } | 3468 | } |
@@ -3489,11 +3494,10 @@ xfs_symlink( | |||
3489 | /* | 3494 | /* |
3490 | * Create the directory entry for the symlink. | 3495 | * Create the directory entry for the symlink. |
3491 | */ | 3496 | */ |
3492 | error = XFS_DIR_CREATENAME(mp, tp, dp, link_name, link_namelen, | 3497 | error = xfs_dir_createname(tp, dp, link_name, link_namelen, ip->i_ino, |
3493 | ip->i_ino, &first_block, &free_list, resblks); | 3498 | &first_block, &free_list, resblks); |
3494 | if (error) { | 3499 | if (error) |
3495 | goto error1; | 3500 | goto error1; |
3496 | } | ||
3497 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 3501 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
3498 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | 3502 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); |
3499 | 3503 | ||
@@ -3541,7 +3545,7 @@ std_return: | |||
3541 | } | 3545 | } |
3542 | 3546 | ||
3543 | if (!error) { | 3547 | if (!error) { |
3544 | vnode_t *vp; | 3548 | bhv_vnode_t *vp; |
3545 | 3549 | ||
3546 | ASSERT(ip); | 3550 | ASSERT(ip); |
3547 | vp = XFS_ITOV(ip); | 3551 | vp = XFS_ITOV(ip); |
@@ -3606,10 +3610,10 @@ xfs_fid2( | |||
3606 | int | 3610 | int |
3607 | xfs_rwlock( | 3611 | xfs_rwlock( |
3608 | bhv_desc_t *bdp, | 3612 | bhv_desc_t *bdp, |
3609 | vrwlock_t locktype) | 3613 | bhv_vrwlock_t locktype) |
3610 | { | 3614 | { |
3611 | xfs_inode_t *ip; | 3615 | xfs_inode_t *ip; |
3612 | vnode_t *vp; | 3616 | bhv_vnode_t *vp; |
3613 | 3617 | ||
3614 | vp = BHV_TO_VNODE(bdp); | 3618 | vp = BHV_TO_VNODE(bdp); |
3615 | if (VN_ISDIR(vp)) | 3619 | if (VN_ISDIR(vp)) |
@@ -3637,10 +3641,10 @@ xfs_rwlock( | |||
3637 | void | 3641 | void |
3638 | xfs_rwunlock( | 3642 | xfs_rwunlock( |
3639 | bhv_desc_t *bdp, | 3643 | bhv_desc_t *bdp, |
3640 | vrwlock_t locktype) | 3644 | bhv_vrwlock_t locktype) |
3641 | { | 3645 | { |
3642 | xfs_inode_t *ip; | 3646 | xfs_inode_t *ip; |
3643 | vnode_t *vp; | 3647 | bhv_vnode_t *vp; |
3644 | 3648 | ||
3645 | vp = BHV_TO_VNODE(bdp); | 3649 | vp = BHV_TO_VNODE(bdp); |
3646 | if (VN_ISDIR(vp)) | 3650 | if (VN_ISDIR(vp)) |
@@ -3744,7 +3748,6 @@ xfs_inode_flush( | |||
3744 | return error; | 3748 | return error; |
3745 | } | 3749 | } |
3746 | 3750 | ||
3747 | |||
3748 | int | 3751 | int |
3749 | xfs_set_dmattrs ( | 3752 | xfs_set_dmattrs ( |
3750 | bhv_desc_t *bdp, | 3753 | bhv_desc_t *bdp, |
@@ -3785,16 +3788,12 @@ xfs_set_dmattrs ( | |||
3785 | return error; | 3788 | return error; |
3786 | } | 3789 | } |
3787 | 3790 | ||
3788 | |||
3789 | /* | ||
3790 | * xfs_reclaim | ||
3791 | */ | ||
3792 | STATIC int | 3791 | STATIC int |
3793 | xfs_reclaim( | 3792 | xfs_reclaim( |
3794 | bhv_desc_t *bdp) | 3793 | bhv_desc_t *bdp) |
3795 | { | 3794 | { |
3796 | xfs_inode_t *ip; | 3795 | xfs_inode_t *ip; |
3797 | vnode_t *vp; | 3796 | bhv_vnode_t *vp; |
3798 | 3797 | ||
3799 | vp = BHV_TO_VNODE(bdp); | 3798 | vp = BHV_TO_VNODE(bdp); |
3800 | ip = XFS_BHVTOI(bdp); | 3799 | ip = XFS_BHVTOI(bdp); |
@@ -3849,7 +3848,7 @@ xfs_finish_reclaim( | |||
3849 | int sync_mode) | 3848 | int sync_mode) |
3850 | { | 3849 | { |
3851 | xfs_ihash_t *ih = ip->i_hash; | 3850 | xfs_ihash_t *ih = ip->i_hash; |
3852 | vnode_t *vp = XFS_ITOV_NULL(ip); | 3851 | bhv_vnode_t *vp = XFS_ITOV_NULL(ip); |
3853 | int error; | 3852 | int error; |
3854 | 3853 | ||
3855 | if (vp && VN_BAD(vp)) | 3854 | if (vp && VN_BAD(vp)) |
@@ -4116,10 +4115,10 @@ retry: | |||
4116 | * Issue the xfs_bmapi() call to allocate the blocks | 4115 | * Issue the xfs_bmapi() call to allocate the blocks |
4117 | */ | 4116 | */ |
4118 | XFS_BMAP_INIT(&free_list, &firstfsb); | 4117 | XFS_BMAP_INIT(&free_list, &firstfsb); |
4119 | error = xfs_bmapi(tp, ip, startoffset_fsb, | 4118 | error = XFS_BMAPI(mp, tp, &ip->i_iocore, startoffset_fsb, |
4120 | allocatesize_fsb, bmapi_flag, | 4119 | allocatesize_fsb, bmapi_flag, |
4121 | &firstfsb, 0, imapp, &nimaps, | 4120 | &firstfsb, 0, imapp, &nimaps, |
4122 | &free_list); | 4121 | &free_list, NULL); |
4123 | if (error) { | 4122 | if (error) { |
4124 | goto error0; | 4123 | goto error0; |
4125 | } | 4124 | } |
@@ -4199,8 +4198,8 @@ xfs_zero_remaining_bytes( | |||
4199 | for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { | 4198 | for (offset = startoff; offset <= endoff; offset = lastoffset + 1) { |
4200 | offset_fsb = XFS_B_TO_FSBT(mp, offset); | 4199 | offset_fsb = XFS_B_TO_FSBT(mp, offset); |
4201 | nimap = 1; | 4200 | nimap = 1; |
4202 | error = xfs_bmapi(NULL, ip, offset_fsb, 1, 0, NULL, 0, &imap, | 4201 | error = XFS_BMAPI(mp, NULL, &ip->i_iocore, offset_fsb, 1, 0, |
4203 | &nimap, NULL); | 4202 | NULL, 0, &imap, &nimap, NULL, NULL); |
4204 | if (error || nimap < 1) | 4203 | if (error || nimap < 1) |
4205 | break; | 4204 | break; |
4206 | ASSERT(imap.br_blockcount >= 1); | 4205 | ASSERT(imap.br_blockcount >= 1); |
@@ -4259,7 +4258,7 @@ xfs_free_file_space( | |||
4259 | xfs_off_t len, | 4258 | xfs_off_t len, |
4260 | int attr_flags) | 4259 | int attr_flags) |
4261 | { | 4260 | { |
4262 | vnode_t *vp; | 4261 | bhv_vnode_t *vp; |
4263 | int committed; | 4262 | int committed; |
4264 | int done; | 4263 | int done; |
4265 | xfs_off_t end_dmi_offset; | 4264 | xfs_off_t end_dmi_offset; |
@@ -4308,7 +4307,6 @@ xfs_free_file_space( | |||
4308 | return error; | 4307 | return error; |
4309 | } | 4308 | } |
4310 | 4309 | ||
4311 | ASSERT(attr_flags & ATTR_NOLOCK ? attr_flags & ATTR_DMI : 1); | ||
4312 | if (attr_flags & ATTR_NOLOCK) | 4310 | if (attr_flags & ATTR_NOLOCK) |
4313 | need_iolock = 0; | 4311 | need_iolock = 0; |
4314 | if (need_iolock) { | 4312 | if (need_iolock) { |
@@ -4326,7 +4324,7 @@ xfs_free_file_space( | |||
4326 | if (VN_CACHED(vp) != 0) { | 4324 | if (VN_CACHED(vp) != 0) { |
4327 | xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, | 4325 | xfs_inval_cached_trace(&ip->i_iocore, ioffset, -1, |
4328 | ctooff(offtoct(ioffset)), -1); | 4326 | ctooff(offtoct(ioffset)), -1); |
4329 | VOP_FLUSHINVAL_PAGES(vp, ctooff(offtoct(ioffset)), | 4327 | bhv_vop_flushinval_pages(vp, ctooff(offtoct(ioffset)), |
4330 | -1, FI_REMAPF_LOCKED); | 4328 | -1, FI_REMAPF_LOCKED); |
4331 | } | 4329 | } |
4332 | 4330 | ||
@@ -4338,8 +4336,8 @@ xfs_free_file_space( | |||
4338 | */ | 4336 | */ |
4339 | if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) { | 4337 | if (rt && !XFS_SB_VERSION_HASEXTFLGBIT(&mp->m_sb)) { |
4340 | nimap = 1; | 4338 | nimap = 1; |
4341 | error = xfs_bmapi(NULL, ip, startoffset_fsb, 1, 0, NULL, 0, | 4339 | error = XFS_BMAPI(mp, NULL, &ip->i_iocore, startoffset_fsb, |
4342 | &imap, &nimap, NULL); | 4340 | 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); |
4343 | if (error) | 4341 | if (error) |
4344 | goto out_unlock_iolock; | 4342 | goto out_unlock_iolock; |
4345 | ASSERT(nimap == 0 || nimap == 1); | 4343 | ASSERT(nimap == 0 || nimap == 1); |
@@ -4353,8 +4351,8 @@ xfs_free_file_space( | |||
4353 | startoffset_fsb += mp->m_sb.sb_rextsize - mod; | 4351 | startoffset_fsb += mp->m_sb.sb_rextsize - mod; |
4354 | } | 4352 | } |
4355 | nimap = 1; | 4353 | nimap = 1; |
4356 | error = xfs_bmapi(NULL, ip, endoffset_fsb - 1, 1, 0, NULL, 0, | 4354 | error = XFS_BMAPI(mp, NULL, &ip->i_iocore, endoffset_fsb - 1, |
4357 | &imap, &nimap, NULL); | 4355 | 1, 0, NULL, 0, &imap, &nimap, NULL, NULL); |
4358 | if (error) | 4356 | if (error) |
4359 | goto out_unlock_iolock; | 4357 | goto out_unlock_iolock; |
4360 | ASSERT(nimap == 0 || nimap == 1); | 4358 | ASSERT(nimap == 0 || nimap == 1); |
@@ -4426,9 +4424,9 @@ xfs_free_file_space( | |||
4426 | * issue the bunmapi() call to free the blocks | 4424 | * issue the bunmapi() call to free the blocks |
4427 | */ | 4425 | */ |
4428 | XFS_BMAP_INIT(&free_list, &firstfsb); | 4426 | XFS_BMAP_INIT(&free_list, &firstfsb); |
4429 | error = xfs_bunmapi(tp, ip, startoffset_fsb, | 4427 | error = XFS_BUNMAPI(mp, tp, &ip->i_iocore, startoffset_fsb, |
4430 | endoffset_fsb - startoffset_fsb, | 4428 | endoffset_fsb - startoffset_fsb, |
4431 | 0, 2, &firstfsb, &free_list, &done); | 4429 | 0, 2, &firstfsb, &free_list, NULL, &done); |
4432 | if (error) { | 4430 | if (error) { |
4433 | goto error0; | 4431 | goto error0; |
4434 | } | 4432 | } |
@@ -4488,8 +4486,8 @@ xfs_change_file_space( | |||
4488 | xfs_off_t startoffset; | 4486 | xfs_off_t startoffset; |
4489 | xfs_off_t llen; | 4487 | xfs_off_t llen; |
4490 | xfs_trans_t *tp; | 4488 | xfs_trans_t *tp; |
4491 | vattr_t va; | 4489 | bhv_vattr_t va; |
4492 | vnode_t *vp; | 4490 | bhv_vnode_t *vp; |
4493 | 4491 | ||
4494 | vp = BHV_TO_VNODE(bdp); | 4492 | vp = BHV_TO_VNODE(bdp); |
4495 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); | 4493 | vn_trace_entry(vp, __FUNCTION__, (inst_t *)__return_address); |
@@ -4642,9 +4640,10 @@ xfs_change_file_space( | |||
4642 | return error; | 4640 | return error; |
4643 | } | 4641 | } |
4644 | 4642 | ||
4645 | vnodeops_t xfs_vnodeops = { | 4643 | bhv_vnodeops_t xfs_vnodeops = { |
4646 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), | 4644 | BHV_IDENTITY_INIT(VN_BHV_XFS,VNODE_POSITION_XFS), |
4647 | .vop_open = xfs_open, | 4645 | .vop_open = xfs_open, |
4646 | .vop_close = xfs_close, | ||
4648 | .vop_read = xfs_read, | 4647 | .vop_read = xfs_read, |
4649 | #ifdef HAVE_SENDFILE | 4648 | #ifdef HAVE_SENDFILE |
4650 | .vop_sendfile = xfs_sendfile, | 4649 | .vop_sendfile = xfs_sendfile, |