diff options
Diffstat (limited to 'fs')
71 files changed, 2263 insertions, 768 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index 94b9d861bf9b..ee11f8d94085 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
| @@ -991,7 +991,7 @@ config TMPFS_POSIX_ACL | |||
| 991 | 991 | ||
| 992 | config HUGETLBFS | 992 | config HUGETLBFS |
| 993 | bool "HugeTLB file system support" | 993 | bool "HugeTLB file system support" |
| 994 | depends on X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN | 994 | depends on X86 || IA64 || PPC64 || SPARC64 || (SUPERH && MMU) || BROKEN |
| 995 | help | 995 | help |
| 996 | hugetlbfs is a filesystem backing for HugeTLB pages, based on | 996 | hugetlbfs is a filesystem backing for HugeTLB pages, based on |
| 997 | ramfs. For architectures that support it, say Y here and read | 997 | ramfs. For architectures that support it, say Y here and read |
diff --git a/fs/afs/Makefile b/fs/afs/Makefile index 73ce561f3ea0..a66671082cfb 100644 --- a/fs/afs/Makefile +++ b/fs/afs/Makefile | |||
| @@ -8,6 +8,7 @@ kafs-objs := \ | |||
| 8 | cmservice.o \ | 8 | cmservice.o \ |
| 9 | dir.o \ | 9 | dir.o \ |
| 10 | file.o \ | 10 | file.o \ |
| 11 | flock.o \ | ||
| 11 | fsclient.o \ | 12 | fsclient.o \ |
| 12 | inode.o \ | 13 | inode.o \ |
| 13 | main.o \ | 14 | main.o \ |
diff --git a/fs/afs/afs.h b/fs/afs/afs.h index 245257948140..c548aa346f0d 100644 --- a/fs/afs/afs.h +++ b/fs/afs/afs.h | |||
| @@ -37,6 +37,13 @@ typedef enum { | |||
| 37 | AFS_FTYPE_SYMLINK = 3, | 37 | AFS_FTYPE_SYMLINK = 3, |
| 38 | } afs_file_type_t; | 38 | } afs_file_type_t; |
| 39 | 39 | ||
| 40 | typedef enum { | ||
| 41 | AFS_LOCK_READ = 0, /* read lock request */ | ||
| 42 | AFS_LOCK_WRITE = 1, /* write lock request */ | ||
| 43 | } afs_lock_type_t; | ||
| 44 | |||
| 45 | #define AFS_LOCKWAIT (5 * 60) /* time until a lock times out (seconds) */ | ||
| 46 | |||
| 40 | /* | 47 | /* |
| 41 | * AFS file identifier | 48 | * AFS file identifier |
| 42 | */ | 49 | */ |
| @@ -120,6 +127,7 @@ struct afs_file_status { | |||
| 120 | struct afs_fid parent; /* parent dir ID for non-dirs only */ | 127 | struct afs_fid parent; /* parent dir ID for non-dirs only */ |
| 121 | time_t mtime_client; /* last time client changed data */ | 128 | time_t mtime_client; /* last time client changed data */ |
| 122 | time_t mtime_server; /* last time server changed data */ | 129 | time_t mtime_server; /* last time server changed data */ |
| 130 | s32 lock_count; /* file lock count (0=UNLK -1=WRLCK +ve=#RDLCK */ | ||
| 123 | }; | 131 | }; |
| 124 | 132 | ||
| 125 | /* | 133 | /* |
diff --git a/fs/afs/afs_fs.h b/fs/afs/afs_fs.h index a18c374ebe08..eb647323d8f0 100644 --- a/fs/afs/afs_fs.h +++ b/fs/afs/afs_fs.h | |||
| @@ -31,6 +31,9 @@ enum AFS_FS_Operations { | |||
| 31 | FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */ | 31 | FSGETVOLUMEINFO = 148, /* AFS Get information about a volume */ |
| 32 | FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */ | 32 | FSGETVOLUMESTATUS = 149, /* AFS Get volume status information */ |
| 33 | FSGETROOTVOLUME = 151, /* AFS Get root volume name */ | 33 | FSGETROOTVOLUME = 151, /* AFS Get root volume name */ |
| 34 | FSSETLOCK = 156, /* AFS Request a file lock */ | ||
| 35 | FSEXTENDLOCK = 157, /* AFS Extend a file lock */ | ||
| 36 | FSRELEASELOCK = 158, /* AFS Release a file lock */ | ||
| 34 | FSLOOKUP = 161, /* AFS lookup file in directory */ | 37 | FSLOOKUP = 161, /* AFS lookup file in directory */ |
| 35 | FSFETCHDATA64 = 65537, /* AFS Fetch file data */ | 38 | FSFETCHDATA64 = 65537, /* AFS Fetch file data */ |
| 36 | FSSTOREDATA64 = 65538, /* AFS Store file data */ | 39 | FSSTOREDATA64 = 65538, /* AFS Store file data */ |
diff --git a/fs/afs/callback.c b/fs/afs/callback.c index bacf518c6fa8..b8243945818d 100644 --- a/fs/afs/callback.c +++ b/fs/afs/callback.c | |||
| @@ -125,6 +125,9 @@ static void afs_break_callback(struct afs_server *server, | |||
| 125 | spin_unlock(&server->cb_lock); | 125 | spin_unlock(&server->cb_lock); |
| 126 | 126 | ||
| 127 | queue_work(afs_callback_update_worker, &vnode->cb_broken_work); | 127 | queue_work(afs_callback_update_worker, &vnode->cb_broken_work); |
| 128 | if (list_empty(&vnode->granted_locks) && | ||
| 129 | !list_empty(&vnode->pending_locks)) | ||
| 130 | afs_lock_may_be_available(vnode); | ||
| 128 | spin_unlock(&vnode->lock); | 131 | spin_unlock(&vnode->lock); |
| 129 | } | 132 | } |
| 130 | } | 133 | } |
diff --git a/fs/afs/dir.c b/fs/afs/dir.c index 546c59522eb1..33fe39ad4e03 100644 --- a/fs/afs/dir.c +++ b/fs/afs/dir.c | |||
| @@ -44,6 +44,7 @@ const struct file_operations afs_dir_file_operations = { | |||
| 44 | .open = afs_dir_open, | 44 | .open = afs_dir_open, |
| 45 | .release = afs_release, | 45 | .release = afs_release, |
| 46 | .readdir = afs_readdir, | 46 | .readdir = afs_readdir, |
| 47 | .lock = afs_lock, | ||
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 49 | const struct inode_operations afs_dir_inode_operations = { | 50 | const struct inode_operations afs_dir_inode_operations = { |
diff --git a/fs/afs/file.c b/fs/afs/file.c index aede7eb66dd4..525f7c56e068 100644 --- a/fs/afs/file.c +++ b/fs/afs/file.c | |||
| @@ -34,6 +34,8 @@ const struct file_operations afs_file_operations = { | |||
| 34 | .mmap = generic_file_readonly_mmap, | 34 | .mmap = generic_file_readonly_mmap, |
| 35 | .splice_read = generic_file_splice_read, | 35 | .splice_read = generic_file_splice_read, |
| 36 | .fsync = afs_fsync, | 36 | .fsync = afs_fsync, |
| 37 | .lock = afs_lock, | ||
| 38 | .flock = afs_flock, | ||
| 37 | }; | 39 | }; |
| 38 | 40 | ||
| 39 | const struct inode_operations afs_file_inode_operations = { | 41 | const struct inode_operations afs_file_inode_operations = { |
diff --git a/fs/afs/flock.c b/fs/afs/flock.c new file mode 100644 index 000000000000..8f07f8d1bfa9 --- /dev/null +++ b/fs/afs/flock.c | |||
| @@ -0,0 +1,558 @@ | |||
| 1 | /* AFS file locking support | ||
| 2 | * | ||
| 3 | * Copyright (C) 2007 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public License | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the License, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/smp_lock.h> | ||
| 13 | #include "internal.h" | ||
| 14 | |||
| 15 | #define AFS_LOCK_GRANTED 0 | ||
| 16 | #define AFS_LOCK_PENDING 1 | ||
| 17 | |||
| 18 | static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl); | ||
| 19 | static void afs_fl_release_private(struct file_lock *fl); | ||
| 20 | |||
| 21 | static struct workqueue_struct *afs_lock_manager; | ||
| 22 | |||
| 23 | static struct file_lock_operations afs_lock_ops = { | ||
| 24 | .fl_copy_lock = afs_fl_copy_lock, | ||
| 25 | .fl_release_private = afs_fl_release_private, | ||
| 26 | }; | ||
| 27 | |||
| 28 | /* | ||
| 29 | * initialise the lock manager thread if it isn't already running | ||
| 30 | */ | ||
| 31 | static int afs_init_lock_manager(void) | ||
| 32 | { | ||
| 33 | if (!afs_lock_manager) { | ||
| 34 | afs_lock_manager = create_singlethread_workqueue("kafs_lockd"); | ||
| 35 | if (!afs_lock_manager) | ||
| 36 | return -ENOMEM; | ||
| 37 | } | ||
| 38 | return 0; | ||
| 39 | } | ||
| 40 | |||
| 41 | /* | ||
| 42 | * destroy the lock manager thread if it's running | ||
| 43 | */ | ||
| 44 | void __exit afs_kill_lock_manager(void) | ||
| 45 | { | ||
| 46 | if (afs_lock_manager) | ||
| 47 | destroy_workqueue(afs_lock_manager); | ||
| 48 | } | ||
| 49 | |||
| 50 | /* | ||
| 51 | * if the callback is broken on this vnode, then the lock may now be available | ||
| 52 | */ | ||
| 53 | void afs_lock_may_be_available(struct afs_vnode *vnode) | ||
| 54 | { | ||
| 55 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | ||
| 56 | |||
| 57 | queue_delayed_work(afs_lock_manager, &vnode->lock_work, 0); | ||
| 58 | } | ||
| 59 | |||
| 60 | /* | ||
| 61 | * the lock will time out in 5 minutes unless we extend it, so schedule | ||
| 62 | * extension in a bit less than that time | ||
| 63 | */ | ||
| 64 | static void afs_schedule_lock_extension(struct afs_vnode *vnode) | ||
| 65 | { | ||
| 66 | queue_delayed_work(afs_lock_manager, &vnode->lock_work, | ||
| 67 | AFS_LOCKWAIT * HZ / 2); | ||
| 68 | } | ||
| 69 | |||
| 70 | /* | ||
| 71 | * do work for a lock, including: | ||
| 72 | * - probing for a lock we're waiting on but didn't get immediately | ||
| 73 | * - extending a lock that's close to timing out | ||
| 74 | */ | ||
| 75 | void afs_lock_work(struct work_struct *work) | ||
| 76 | { | ||
| 77 | struct afs_vnode *vnode = | ||
| 78 | container_of(work, struct afs_vnode, lock_work.work); | ||
| 79 | struct file_lock *fl; | ||
| 80 | afs_lock_type_t type; | ||
| 81 | struct key *key; | ||
| 82 | int ret; | ||
| 83 | |||
| 84 | _enter("{%x:%u}", vnode->fid.vid, vnode->fid.vnode); | ||
| 85 | |||
| 86 | spin_lock(&vnode->lock); | ||
| 87 | |||
| 88 | if (test_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) { | ||
| 89 | _debug("unlock"); | ||
| 90 | spin_unlock(&vnode->lock); | ||
| 91 | |||
| 92 | /* attempt to release the server lock; if it fails, we just | ||
| 93 | * wait 5 minutes and it'll time out anyway */ | ||
| 94 | ret = afs_vnode_release_lock(vnode, vnode->unlock_key); | ||
| 95 | if (ret < 0) | ||
| 96 | printk(KERN_WARNING "AFS:" | ||
| 97 | " Failed to release lock on {%x:%x} error %d\n", | ||
| 98 | vnode->fid.vid, vnode->fid.vnode, ret); | ||
| 99 | |||
| 100 | spin_lock(&vnode->lock); | ||
| 101 | key_put(vnode->unlock_key); | ||
| 102 | vnode->unlock_key = NULL; | ||
| 103 | clear_bit(AFS_VNODE_UNLOCKING, &vnode->flags); | ||
| 104 | } | ||
| 105 | |||
| 106 | /* if we've got a lock, then it must be time to extend that lock as AFS | ||
| 107 | * locks time out after 5 minutes */ | ||
| 108 | if (!list_empty(&vnode->granted_locks)) { | ||
| 109 | _debug("extend"); | ||
| 110 | |||
| 111 | if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags)) | ||
| 112 | BUG(); | ||
| 113 | fl = list_entry(vnode->granted_locks.next, | ||
| 114 | struct file_lock, fl_u.afs.link); | ||
| 115 | key = key_get(fl->fl_file->private_data); | ||
| 116 | spin_unlock(&vnode->lock); | ||
| 117 | |||
| 118 | ret = afs_vnode_extend_lock(vnode, key); | ||
| 119 | clear_bit(AFS_VNODE_LOCKING, &vnode->flags); | ||
| 120 | key_put(key); | ||
| 121 | switch (ret) { | ||
| 122 | case 0: | ||
| 123 | afs_schedule_lock_extension(vnode); | ||
| 124 | break; | ||
| 125 | default: | ||
| 126 | /* ummm... we failed to extend the lock - retry | ||
| 127 | * extension shortly */ | ||
| 128 | printk(KERN_WARNING "AFS:" | ||
| 129 | " Failed to extend lock on {%x:%x} error %d\n", | ||
| 130 | vnode->fid.vid, vnode->fid.vnode, ret); | ||
| 131 | queue_delayed_work(afs_lock_manager, &vnode->lock_work, | ||
| 132 | HZ * 10); | ||
| 133 | break; | ||
| 134 | } | ||
| 135 | _leave(" [extend]"); | ||
| 136 | return; | ||
| 137 | } | ||
| 138 | |||
| 139 | /* if we don't have a granted lock, then we must've been called back by | ||
| 140 | * the server, and so if might be possible to get a lock we're | ||
| 141 | * currently waiting for */ | ||
| 142 | if (!list_empty(&vnode->pending_locks)) { | ||
| 143 | _debug("get"); | ||
| 144 | |||
| 145 | if (test_and_set_bit(AFS_VNODE_LOCKING, &vnode->flags)) | ||
| 146 | BUG(); | ||
| 147 | fl = list_entry(vnode->pending_locks.next, | ||
| 148 | struct file_lock, fl_u.afs.link); | ||
| 149 | key = key_get(fl->fl_file->private_data); | ||
| 150 | type = (fl->fl_type == F_RDLCK) ? | ||
| 151 | AFS_LOCK_READ : AFS_LOCK_WRITE; | ||
| 152 | spin_unlock(&vnode->lock); | ||
| 153 | |||
| 154 | ret = afs_vnode_set_lock(vnode, key, type); | ||
| 155 | clear_bit(AFS_VNODE_LOCKING, &vnode->flags); | ||
| 156 | switch (ret) { | ||
| 157 | case -EWOULDBLOCK: | ||
| 158 | _debug("blocked"); | ||
| 159 | break; | ||
| 160 | case 0: | ||
| 161 | _debug("acquired"); | ||
| 162 | if (type == AFS_LOCK_READ) | ||
| 163 | set_bit(AFS_VNODE_READLOCKED, &vnode->flags); | ||
| 164 | else | ||
| 165 | set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags); | ||
| 166 | ret = AFS_LOCK_GRANTED; | ||
| 167 | default: | ||
| 168 | spin_lock(&vnode->lock); | ||
| 169 | /* the pending lock may have been withdrawn due to a | ||
| 170 | * signal */ | ||
| 171 | if (list_entry(vnode->pending_locks.next, | ||
| 172 | struct file_lock, fl_u.afs.link) == fl) { | ||
| 173 | fl->fl_u.afs.state = ret; | ||
| 174 | if (ret == AFS_LOCK_GRANTED) | ||
| 175 | list_move_tail(&fl->fl_u.afs.link, | ||
| 176 | &vnode->granted_locks); | ||
| 177 | else | ||
| 178 | list_del_init(&fl->fl_u.afs.link); | ||
| 179 | wake_up(&fl->fl_wait); | ||
| 180 | spin_unlock(&vnode->lock); | ||
| 181 | } else { | ||
| 182 | _debug("withdrawn"); | ||
| 183 | clear_bit(AFS_VNODE_READLOCKED, &vnode->flags); | ||
| 184 | clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags); | ||
| 185 | spin_unlock(&vnode->lock); | ||
| 186 | afs_vnode_release_lock(vnode, key); | ||
| 187 | if (!list_empty(&vnode->pending_locks)) | ||
| 188 | afs_lock_may_be_available(vnode); | ||
| 189 | } | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | key_put(key); | ||
| 193 | _leave(" [pend]"); | ||
| 194 | return; | ||
| 195 | } | ||
| 196 | |||
| 197 | /* looks like the lock request was withdrawn on a signal */ | ||
| 198 | spin_unlock(&vnode->lock); | ||
| 199 | _leave(" [no locks]"); | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * pass responsibility for the unlocking of a vnode on the server to the | ||
| 204 | * manager thread, lest a pending signal in the calling thread interrupt | ||
| 205 | * AF_RXRPC | ||
| 206 | * - the caller must hold the vnode lock | ||
| 207 | */ | ||
| 208 | static void afs_defer_unlock(struct afs_vnode *vnode, struct key *key) | ||
| 209 | { | ||
| 210 | cancel_delayed_work(&vnode->lock_work); | ||
| 211 | if (!test_and_clear_bit(AFS_VNODE_READLOCKED, &vnode->flags) && | ||
| 212 | !test_and_clear_bit(AFS_VNODE_WRITELOCKED, &vnode->flags)) | ||
| 213 | BUG(); | ||
| 214 | if (test_and_set_bit(AFS_VNODE_UNLOCKING, &vnode->flags)) | ||
| 215 | BUG(); | ||
| 216 | vnode->unlock_key = key_get(key); | ||
| 217 | afs_lock_may_be_available(vnode); | ||
| 218 | } | ||
| 219 | |||
| 220 | /* | ||
| 221 | * request a lock on a file on the server | ||
| 222 | */ | ||
| 223 | static int afs_do_setlk(struct file *file, struct file_lock *fl) | ||
| 224 | { | ||
| 225 | struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); | ||
| 226 | afs_lock_type_t type; | ||
| 227 | struct key *key = file->private_data; | ||
| 228 | int ret; | ||
| 229 | |||
| 230 | _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); | ||
| 231 | |||
| 232 | /* only whole-file locks are supported */ | ||
| 233 | if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX) | ||
| 234 | return -EINVAL; | ||
| 235 | |||
| 236 | ret = afs_init_lock_manager(); | ||
| 237 | if (ret < 0) | ||
| 238 | return ret; | ||
| 239 | |||
| 240 | fl->fl_ops = &afs_lock_ops; | ||
| 241 | INIT_LIST_HEAD(&fl->fl_u.afs.link); | ||
| 242 | fl->fl_u.afs.state = AFS_LOCK_PENDING; | ||
| 243 | |||
| 244 | type = (fl->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE; | ||
| 245 | |||
| 246 | lock_kernel(); | ||
| 247 | |||
| 248 | /* make sure we've got a callback on this file and that our view of the | ||
| 249 | * data version is up to date */ | ||
| 250 | ret = afs_vnode_fetch_status(vnode, NULL, key); | ||
| 251 | if (ret < 0) | ||
| 252 | goto error; | ||
| 253 | |||
| 254 | if (vnode->status.lock_count != 0 && !(fl->fl_flags & FL_SLEEP)) { | ||
| 255 | ret = -EAGAIN; | ||
| 256 | goto error; | ||
| 257 | } | ||
| 258 | |||
| 259 | spin_lock(&vnode->lock); | ||
| 260 | |||
| 261 | if (list_empty(&vnode->pending_locks)) { | ||
| 262 | /* if there's no-one else with a lock on this vnode, then we | ||
| 263 | * need to ask the server for a lock */ | ||
| 264 | if (list_empty(&vnode->granted_locks)) { | ||
| 265 | _debug("not locked"); | ||
| 266 | ASSERTCMP(vnode->flags & | ||
| 267 | ((1 << AFS_VNODE_LOCKING) | | ||
| 268 | (1 << AFS_VNODE_READLOCKED) | | ||
| 269 | (1 << AFS_VNODE_WRITELOCKED)), ==, 0); | ||
| 270 | list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks); | ||
| 271 | set_bit(AFS_VNODE_LOCKING, &vnode->flags); | ||
| 272 | spin_unlock(&vnode->lock); | ||
| 273 | |||
| 274 | ret = afs_vnode_set_lock(vnode, key, type); | ||
| 275 | clear_bit(AFS_VNODE_LOCKING, &vnode->flags); | ||
| 276 | switch (ret) { | ||
| 277 | case 0: | ||
| 278 | goto acquired_server_lock; | ||
| 279 | case -EWOULDBLOCK: | ||
| 280 | spin_lock(&vnode->lock); | ||
| 281 | ASSERT(list_empty(&vnode->granted_locks)); | ||
| 282 | ASSERTCMP(vnode->pending_locks.next, ==, | ||
| 283 | &fl->fl_u.afs.link); | ||
| 284 | goto wait; | ||
| 285 | default: | ||
| 286 | spin_lock(&vnode->lock); | ||
| 287 | list_del_init(&fl->fl_u.afs.link); | ||
| 288 | spin_unlock(&vnode->lock); | ||
| 289 | goto error; | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | /* if we've already got a readlock on the server and no waiting | ||
| 294 | * writelocks, then we might be able to instantly grant another | ||
| 295 | * readlock */ | ||
| 296 | if (type == AFS_LOCK_READ && | ||
| 297 | vnode->flags & (1 << AFS_VNODE_READLOCKED)) { | ||
| 298 | _debug("instant readlock"); | ||
| 299 | ASSERTCMP(vnode->flags & | ||
| 300 | ((1 << AFS_VNODE_LOCKING) | | ||
| 301 | (1 << AFS_VNODE_WRITELOCKED)), ==, 0); | ||
| 302 | ASSERT(!list_empty(&vnode->granted_locks)); | ||
| 303 | goto sharing_existing_lock; | ||
| 304 | } | ||
| 305 | } | ||
| 306 | |||
| 307 | /* otherwise, we need to wait for a local lock to become available */ | ||
| 308 | _debug("wait local"); | ||
| 309 | list_add_tail(&fl->fl_u.afs.link, &vnode->pending_locks); | ||
| 310 | wait: | ||
| 311 | if (!(fl->fl_flags & FL_SLEEP)) { | ||
| 312 | _debug("noblock"); | ||
| 313 | ret = -EAGAIN; | ||
| 314 | goto abort_attempt; | ||
| 315 | } | ||
| 316 | spin_unlock(&vnode->lock); | ||
| 317 | |||
| 318 | /* now we need to sleep and wait for the lock manager thread to get the | ||
| 319 | * lock from the server */ | ||
| 320 | _debug("sleep"); | ||
| 321 | ret = wait_event_interruptible(fl->fl_wait, | ||
| 322 | fl->fl_u.afs.state <= AFS_LOCK_GRANTED); | ||
| 323 | if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) { | ||
| 324 | ret = fl->fl_u.afs.state; | ||
| 325 | if (ret < 0) | ||
| 326 | goto error; | ||
| 327 | spin_lock(&vnode->lock); | ||
| 328 | goto given_lock; | ||
| 329 | } | ||
| 330 | |||
| 331 | /* we were interrupted, but someone may still be in the throes of | ||
| 332 | * giving us the lock */ | ||
| 333 | _debug("intr"); | ||
| 334 | ASSERTCMP(ret, ==, -ERESTARTSYS); | ||
| 335 | |||
| 336 | spin_lock(&vnode->lock); | ||
| 337 | if (fl->fl_u.afs.state <= AFS_LOCK_GRANTED) { | ||
| 338 | ret = fl->fl_u.afs.state; | ||
| 339 | if (ret < 0) { | ||
| 340 | spin_unlock(&vnode->lock); | ||
| 341 | goto error; | ||
| 342 | } | ||
| 343 | goto given_lock; | ||
| 344 | } | ||
| 345 | |||
| 346 | abort_attempt: | ||
| 347 | /* we aren't going to get the lock, either because we're unwilling to | ||
| 348 | * wait, or because some signal happened */ | ||
| 349 | _debug("abort"); | ||
| 350 | if (list_empty(&vnode->granted_locks) && | ||
| 351 | vnode->pending_locks.next == &fl->fl_u.afs.link) { | ||
| 352 | if (vnode->pending_locks.prev != &fl->fl_u.afs.link) { | ||
| 353 | /* kick the next pending lock into having a go */ | ||
| 354 | list_del_init(&fl->fl_u.afs.link); | ||
| 355 | afs_lock_may_be_available(vnode); | ||
| 356 | } | ||
| 357 | } else { | ||
| 358 | list_del_init(&fl->fl_u.afs.link); | ||
| 359 | } | ||
| 360 | spin_unlock(&vnode->lock); | ||
| 361 | goto error; | ||
| 362 | |||
| 363 | acquired_server_lock: | ||
| 364 | /* we've acquired a server lock, but it needs to be renewed after 5 | ||
| 365 | * mins */ | ||
| 366 | spin_lock(&vnode->lock); | ||
| 367 | afs_schedule_lock_extension(vnode); | ||
| 368 | if (type == AFS_LOCK_READ) | ||
| 369 | set_bit(AFS_VNODE_READLOCKED, &vnode->flags); | ||
| 370 | else | ||
| 371 | set_bit(AFS_VNODE_WRITELOCKED, &vnode->flags); | ||
| 372 | sharing_existing_lock: | ||
| 373 | /* the lock has been granted as far as we're concerned... */ | ||
| 374 | fl->fl_u.afs.state = AFS_LOCK_GRANTED; | ||
| 375 | list_move_tail(&fl->fl_u.afs.link, &vnode->granted_locks); | ||
| 376 | given_lock: | ||
| 377 | /* ... but we do still need to get the VFS's blessing */ | ||
| 378 | ASSERT(!(vnode->flags & (1 << AFS_VNODE_LOCKING))); | ||
| 379 | ASSERT((vnode->flags & ((1 << AFS_VNODE_READLOCKED) | | ||
| 380 | (1 << AFS_VNODE_WRITELOCKED))) != 0); | ||
| 381 | ret = posix_lock_file(file, fl, NULL); | ||
| 382 | if (ret < 0) | ||
| 383 | goto vfs_rejected_lock; | ||
| 384 | spin_unlock(&vnode->lock); | ||
| 385 | |||
| 386 | /* again, make sure we've got a callback on this file and, again, make | ||
| 387 | * sure that our view of the data version is up to date (we ignore | ||
| 388 | * errors incurred here and deal with the consequences elsewhere) */ | ||
| 389 | afs_vnode_fetch_status(vnode, NULL, key); | ||
| 390 | |||
| 391 | error: | ||
| 392 | unlock_kernel(); | ||
| 393 | _leave(" = %d", ret); | ||
| 394 | return ret; | ||
| 395 | |||
| 396 | vfs_rejected_lock: | ||
| 397 | /* the VFS rejected the lock we just obtained, so we have to discard | ||
| 398 | * what we just got */ | ||
| 399 | _debug("vfs refused %d", ret); | ||
| 400 | list_del_init(&fl->fl_u.afs.link); | ||
| 401 | if (list_empty(&vnode->granted_locks)) | ||
| 402 | afs_defer_unlock(vnode, key); | ||
| 403 | spin_unlock(&vnode->lock); | ||
| 404 | goto abort_attempt; | ||
| 405 | } | ||
| 406 | |||
| 407 | /* | ||
| 408 | * unlock on a file on the server | ||
| 409 | */ | ||
| 410 | static int afs_do_unlk(struct file *file, struct file_lock *fl) | ||
| 411 | { | ||
| 412 | struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); | ||
| 413 | struct key *key = file->private_data; | ||
| 414 | int ret; | ||
| 415 | |||
| 416 | _enter("{%x:%u},%u", vnode->fid.vid, vnode->fid.vnode, fl->fl_type); | ||
| 417 | |||
| 418 | /* only whole-file unlocks are supported */ | ||
| 419 | if (fl->fl_start != 0 || fl->fl_end != OFFSET_MAX) | ||
| 420 | return -EINVAL; | ||
| 421 | |||
| 422 | fl->fl_ops = &afs_lock_ops; | ||
| 423 | INIT_LIST_HEAD(&fl->fl_u.afs.link); | ||
| 424 | fl->fl_u.afs.state = AFS_LOCK_PENDING; | ||
| 425 | |||
| 426 | spin_lock(&vnode->lock); | ||
| 427 | ret = posix_lock_file(file, fl, NULL); | ||
| 428 | if (ret < 0) { | ||
| 429 | spin_unlock(&vnode->lock); | ||
| 430 | _leave(" = %d [vfs]", ret); | ||
| 431 | return ret; | ||
| 432 | } | ||
| 433 | |||
| 434 | /* discard the server lock only if all granted locks are gone */ | ||
| 435 | if (list_empty(&vnode->granted_locks)) | ||
| 436 | afs_defer_unlock(vnode, key); | ||
| 437 | spin_unlock(&vnode->lock); | ||
| 438 | _leave(" = 0"); | ||
| 439 | return 0; | ||
| 440 | } | ||
| 441 | |||
| 442 | /* | ||
| 443 | * return information about a lock we currently hold, if indeed we hold one | ||
| 444 | */ | ||
| 445 | static int afs_do_getlk(struct file *file, struct file_lock *fl) | ||
| 446 | { | ||
| 447 | struct afs_vnode *vnode = AFS_FS_I(file->f_mapping->host); | ||
| 448 | struct key *key = file->private_data; | ||
| 449 | int ret, lock_count; | ||
| 450 | |||
| 451 | _enter(""); | ||
| 452 | |||
| 453 | fl->fl_type = F_UNLCK; | ||
| 454 | |||
| 455 | mutex_lock(&vnode->vfs_inode.i_mutex); | ||
| 456 | |||
| 457 | /* check local lock records first */ | ||
| 458 | ret = 0; | ||
| 459 | if (posix_test_lock(file, fl) == 0) { | ||
| 460 | /* no local locks; consult the server */ | ||
| 461 | ret = afs_vnode_fetch_status(vnode, NULL, key); | ||
| 462 | if (ret < 0) | ||
| 463 | goto error; | ||
| 464 | lock_count = vnode->status.lock_count; | ||
| 465 | if (lock_count) { | ||
| 466 | if (lock_count > 0) | ||
| 467 | fl->fl_type = F_RDLCK; | ||
| 468 | else | ||
| 469 | fl->fl_type = F_WRLCK; | ||
| 470 | fl->fl_start = 0; | ||
| 471 | fl->fl_end = OFFSET_MAX; | ||
| 472 | } | ||
| 473 | } | ||
| 474 | |||
| 475 | error: | ||
| 476 | mutex_unlock(&vnode->vfs_inode.i_mutex); | ||
| 477 | _leave(" = %d [%hd]", ret, fl->fl_type); | ||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 481 | /* | ||
| 482 | * manage POSIX locks on a file | ||
| 483 | */ | ||
| 484 | int afs_lock(struct file *file, int cmd, struct file_lock *fl) | ||
| 485 | { | ||
| 486 | struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode); | ||
| 487 | |||
| 488 | _enter("{%x:%u},%d,{t=%x,fl=%x,r=%Ld:%Ld}", | ||
| 489 | vnode->fid.vid, vnode->fid.vnode, cmd, | ||
| 490 | fl->fl_type, fl->fl_flags, | ||
| 491 | (long long) fl->fl_start, (long long) fl->fl_end); | ||
| 492 | |||
| 493 | /* AFS doesn't support mandatory locks */ | ||
| 494 | if ((vnode->vfs_inode.i_mode & (S_ISGID | S_IXGRP)) == S_ISGID && | ||
| 495 | fl->fl_type != F_UNLCK) | ||
| 496 | return -ENOLCK; | ||
| 497 | |||
| 498 | if (IS_GETLK(cmd)) | ||
| 499 | return afs_do_getlk(file, fl); | ||
| 500 | if (fl->fl_type == F_UNLCK) | ||
| 501 | return afs_do_unlk(file, fl); | ||
| 502 | return afs_do_setlk(file, fl); | ||
| 503 | } | ||
| 504 | |||
| 505 | /* | ||
| 506 | * manage FLOCK locks on a file | ||
| 507 | */ | ||
| 508 | int afs_flock(struct file *file, int cmd, struct file_lock *fl) | ||
| 509 | { | ||
| 510 | struct afs_vnode *vnode = AFS_FS_I(file->f_dentry->d_inode); | ||
| 511 | |||
| 512 | _enter("{%x:%u},%d,{t=%x,fl=%x}", | ||
| 513 | vnode->fid.vid, vnode->fid.vnode, cmd, | ||
| 514 | fl->fl_type, fl->fl_flags); | ||
| 515 | |||
| 516 | /* | ||
| 517 | * No BSD flocks over NFS allowed. | ||
| 518 | * Note: we could try to fake a POSIX lock request here by | ||
| 519 | * using ((u32) filp | 0x80000000) or some such as the pid. | ||
| 520 | * Not sure whether that would be unique, though, or whether | ||
| 521 | * that would break in other places. | ||
| 522 | */ | ||
| 523 | if (!(fl->fl_flags & FL_FLOCK)) | ||
| 524 | return -ENOLCK; | ||
| 525 | |||
| 526 | /* we're simulating flock() locks using posix locks on the server */ | ||
| 527 | fl->fl_owner = (fl_owner_t) file; | ||
| 528 | fl->fl_start = 0; | ||
| 529 | fl->fl_end = OFFSET_MAX; | ||
| 530 | |||
| 531 | if (fl->fl_type == F_UNLCK) | ||
| 532 | return afs_do_unlk(file, fl); | ||
| 533 | return afs_do_setlk(file, fl); | ||
| 534 | } | ||
| 535 | |||
| 536 | /* | ||
| 537 | * the POSIX lock management core VFS code copies the lock record and adds the | ||
| 538 | * copy into its own list, so we need to add that copy to the vnode's lock | ||
| 539 | * queue in the same place as the original (which will be deleted shortly | ||
| 540 | * after) | ||
| 541 | */ | ||
| 542 | static void afs_fl_copy_lock(struct file_lock *new, struct file_lock *fl) | ||
| 543 | { | ||
| 544 | _enter(""); | ||
| 545 | |||
| 546 | list_add(&new->fl_u.afs.link, &fl->fl_u.afs.link); | ||
| 547 | } | ||
| 548 | |||
| 549 | /* | ||
| 550 | * need to remove this lock from the vnode queue when it's removed from the | ||
| 551 | * VFS's list | ||
| 552 | */ | ||
| 553 | static void afs_fl_release_private(struct file_lock *fl) | ||
| 554 | { | ||
| 555 | _enter(""); | ||
| 556 | |||
| 557 | list_del_init(&fl->fl_u.afs.link); | ||
| 558 | } | ||
diff --git a/fs/afs/fsclient.c b/fs/afs/fsclient.c index 5dff1308b6f0..023b95b0d9d7 100644 --- a/fs/afs/fsclient.c +++ b/fs/afs/fsclient.c | |||
| @@ -67,7 +67,7 @@ static void xdr_decode_AFSFetchStatus(const __be32 **_bp, | |||
| 67 | EXTRACT(status->group); | 67 | EXTRACT(status->group); |
| 68 | bp++; /* sync counter */ | 68 | bp++; /* sync counter */ |
| 69 | data_version |= (u64) ntohl(*bp++) << 32; | 69 | data_version |= (u64) ntohl(*bp++) << 32; |
| 70 | bp++; /* lock count */ | 70 | EXTRACT(status->lock_count); |
| 71 | size |= (u64) ntohl(*bp++) << 32; | 71 | size |= (u64) ntohl(*bp++) << 32; |
| 72 | bp++; /* spare 4 */ | 72 | bp++; /* spare 4 */ |
| 73 | *_bp = bp; | 73 | *_bp = bp; |
| @@ -1748,3 +1748,156 @@ int afs_fs_get_volume_status(struct afs_server *server, | |||
| 1748 | 1748 | ||
| 1749 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | 1749 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); |
| 1750 | } | 1750 | } |
| 1751 | |||
| 1752 | /* | ||
| 1753 | * deliver reply data to an FS.SetLock, FS.ExtendLock or FS.ReleaseLock | ||
| 1754 | */ | ||
| 1755 | static int afs_deliver_fs_xxxx_lock(struct afs_call *call, | ||
| 1756 | struct sk_buff *skb, bool last) | ||
| 1757 | { | ||
| 1758 | const __be32 *bp; | ||
| 1759 | |||
| 1760 | _enter("{%u},{%u},%d", call->unmarshall, skb->len, last); | ||
| 1761 | |||
| 1762 | afs_transfer_reply(call, skb); | ||
| 1763 | if (!last) | ||
| 1764 | return 0; | ||
| 1765 | |||
| 1766 | if (call->reply_size != call->reply_max) | ||
| 1767 | return -EBADMSG; | ||
| 1768 | |||
| 1769 | /* unmarshall the reply once we've received all of it */ | ||
| 1770 | bp = call->buffer; | ||
| 1771 | /* xdr_decode_AFSVolSync(&bp, call->replyX); */ | ||
| 1772 | |||
| 1773 | _leave(" = 0 [done]"); | ||
| 1774 | return 0; | ||
| 1775 | } | ||
| 1776 | |||
| 1777 | /* | ||
| 1778 | * FS.SetLock operation type | ||
| 1779 | */ | ||
| 1780 | static const struct afs_call_type afs_RXFSSetLock = { | ||
| 1781 | .name = "FS.SetLock", | ||
| 1782 | .deliver = afs_deliver_fs_xxxx_lock, | ||
| 1783 | .abort_to_error = afs_abort_to_error, | ||
| 1784 | .destructor = afs_flat_call_destructor, | ||
| 1785 | }; | ||
| 1786 | |||
| 1787 | /* | ||
| 1788 | * FS.ExtendLock operation type | ||
| 1789 | */ | ||
| 1790 | static const struct afs_call_type afs_RXFSExtendLock = { | ||
| 1791 | .name = "FS.ExtendLock", | ||
| 1792 | .deliver = afs_deliver_fs_xxxx_lock, | ||
| 1793 | .abort_to_error = afs_abort_to_error, | ||
| 1794 | .destructor = afs_flat_call_destructor, | ||
| 1795 | }; | ||
| 1796 | |||
| 1797 | /* | ||
| 1798 | * FS.ReleaseLock operation type | ||
| 1799 | */ | ||
| 1800 | static const struct afs_call_type afs_RXFSReleaseLock = { | ||
| 1801 | .name = "FS.ReleaseLock", | ||
| 1802 | .deliver = afs_deliver_fs_xxxx_lock, | ||
| 1803 | .abort_to_error = afs_abort_to_error, | ||
| 1804 | .destructor = afs_flat_call_destructor, | ||
| 1805 | }; | ||
| 1806 | |||
| 1807 | /* | ||
| 1808 | * get a lock on a file | ||
| 1809 | */ | ||
| 1810 | int afs_fs_set_lock(struct afs_server *server, | ||
| 1811 | struct key *key, | ||
| 1812 | struct afs_vnode *vnode, | ||
| 1813 | afs_lock_type_t type, | ||
| 1814 | const struct afs_wait_mode *wait_mode) | ||
| 1815 | { | ||
| 1816 | struct afs_call *call; | ||
| 1817 | __be32 *bp; | ||
| 1818 | |||
| 1819 | _enter(""); | ||
| 1820 | |||
| 1821 | call = afs_alloc_flat_call(&afs_RXFSSetLock, 5 * 4, 6 * 4); | ||
| 1822 | if (!call) | ||
| 1823 | return -ENOMEM; | ||
| 1824 | |||
| 1825 | call->key = key; | ||
| 1826 | call->reply = vnode; | ||
| 1827 | call->service_id = FS_SERVICE; | ||
| 1828 | call->port = htons(AFS_FS_PORT); | ||
| 1829 | |||
| 1830 | /* marshall the parameters */ | ||
| 1831 | bp = call->request; | ||
| 1832 | *bp++ = htonl(FSSETLOCK); | ||
| 1833 | *bp++ = htonl(vnode->fid.vid); | ||
| 1834 | *bp++ = htonl(vnode->fid.vnode); | ||
| 1835 | *bp++ = htonl(vnode->fid.unique); | ||
| 1836 | *bp++ = htonl(type); | ||
| 1837 | |||
| 1838 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
| 1839 | } | ||
| 1840 | |||
| 1841 | /* | ||
| 1842 | * extend a lock on a file | ||
| 1843 | */ | ||
| 1844 | int afs_fs_extend_lock(struct afs_server *server, | ||
| 1845 | struct key *key, | ||
| 1846 | struct afs_vnode *vnode, | ||
| 1847 | const struct afs_wait_mode *wait_mode) | ||
| 1848 | { | ||
| 1849 | struct afs_call *call; | ||
| 1850 | __be32 *bp; | ||
| 1851 | |||
| 1852 | _enter(""); | ||
| 1853 | |||
| 1854 | call = afs_alloc_flat_call(&afs_RXFSExtendLock, 4 * 4, 6 * 4); | ||
| 1855 | if (!call) | ||
| 1856 | return -ENOMEM; | ||
| 1857 | |||
| 1858 | call->key = key; | ||
| 1859 | call->reply = vnode; | ||
| 1860 | call->service_id = FS_SERVICE; | ||
| 1861 | call->port = htons(AFS_FS_PORT); | ||
| 1862 | |||
| 1863 | /* marshall the parameters */ | ||
| 1864 | bp = call->request; | ||
| 1865 | *bp++ = htonl(FSEXTENDLOCK); | ||
| 1866 | *bp++ = htonl(vnode->fid.vid); | ||
| 1867 | *bp++ = htonl(vnode->fid.vnode); | ||
| 1868 | *bp++ = htonl(vnode->fid.unique); | ||
| 1869 | |||
| 1870 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
| 1871 | } | ||
| 1872 | |||
| 1873 | /* | ||
| 1874 | * release a lock on a file | ||
| 1875 | */ | ||
| 1876 | int afs_fs_release_lock(struct afs_server *server, | ||
| 1877 | struct key *key, | ||
| 1878 | struct afs_vnode *vnode, | ||
| 1879 | const struct afs_wait_mode *wait_mode) | ||
| 1880 | { | ||
| 1881 | struct afs_call *call; | ||
| 1882 | __be32 *bp; | ||
| 1883 | |||
| 1884 | _enter(""); | ||
| 1885 | |||
| 1886 | call = afs_alloc_flat_call(&afs_RXFSReleaseLock, 4 * 4, 6 * 4); | ||
| 1887 | if (!call) | ||
| 1888 | return -ENOMEM; | ||
| 1889 | |||
| 1890 | call->key = key; | ||
| 1891 | call->reply = vnode; | ||
| 1892 | call->service_id = FS_SERVICE; | ||
| 1893 | call->port = htons(AFS_FS_PORT); | ||
| 1894 | |||
| 1895 | /* marshall the parameters */ | ||
| 1896 | bp = call->request; | ||
| 1897 | *bp++ = htonl(FSRELEASELOCK); | ||
| 1898 | *bp++ = htonl(vnode->fid.vid); | ||
| 1899 | *bp++ = htonl(vnode->fid.vnode); | ||
| 1900 | *bp++ = htonl(vnode->fid.unique); | ||
| 1901 | |||
| 1902 | return afs_make_call(&server->addr, call, GFP_NOFS, wait_mode); | ||
| 1903 | } | ||
diff --git a/fs/afs/internal.h b/fs/afs/internal.h index 2c55dd94a1de..6306438f331f 100644 --- a/fs/afs/internal.h +++ b/fs/afs/internal.h | |||
| @@ -351,10 +351,18 @@ struct afs_vnode { | |||
| 351 | #define AFS_VNODE_ZAP_DATA 3 /* set if vnode's data should be invalidated */ | 351 | #define AFS_VNODE_ZAP_DATA 3 /* set if vnode's data should be invalidated */ |
| 352 | #define AFS_VNODE_DELETED 4 /* set if vnode deleted on server */ | 352 | #define AFS_VNODE_DELETED 4 /* set if vnode deleted on server */ |
| 353 | #define AFS_VNODE_MOUNTPOINT 5 /* set if vnode is a mountpoint symlink */ | 353 | #define AFS_VNODE_MOUNTPOINT 5 /* set if vnode is a mountpoint symlink */ |
| 354 | #define AFS_VNODE_LOCKING 6 /* set if waiting for lock on vnode */ | ||
| 355 | #define AFS_VNODE_READLOCKED 7 /* set if vnode is read-locked on the server */ | ||
| 356 | #define AFS_VNODE_WRITELOCKED 8 /* set if vnode is write-locked on the server */ | ||
| 357 | #define AFS_VNODE_UNLOCKING 9 /* set if vnode is being unlocked on the server */ | ||
| 354 | 358 | ||
| 355 | long acl_order; /* ACL check count (callback break count) */ | 359 | long acl_order; /* ACL check count (callback break count) */ |
| 356 | 360 | ||
| 357 | struct list_head writebacks; /* alterations in pagecache that need writing */ | 361 | struct list_head writebacks; /* alterations in pagecache that need writing */ |
| 362 | struct list_head pending_locks; /* locks waiting to be granted */ | ||
| 363 | struct list_head granted_locks; /* locks granted on this file */ | ||
| 364 | struct delayed_work lock_work; /* work to be done in locking */ | ||
| 365 | struct key *unlock_key; /* key to be used in unlocking */ | ||
| 358 | 366 | ||
| 359 | /* outstanding callback notification on this file */ | 367 | /* outstanding callback notification on this file */ |
| 360 | struct rb_node server_rb; /* link in server->fs_vnodes */ | 368 | struct rb_node server_rb; /* link in server->fs_vnodes */ |
| @@ -474,6 +482,15 @@ extern int afs_open(struct inode *, struct file *); | |||
| 474 | extern int afs_release(struct inode *, struct file *); | 482 | extern int afs_release(struct inode *, struct file *); |
| 475 | 483 | ||
| 476 | /* | 484 | /* |
| 485 | * flock.c | ||
| 486 | */ | ||
| 487 | extern void __exit afs_kill_lock_manager(void); | ||
| 488 | extern void afs_lock_work(struct work_struct *); | ||
| 489 | extern void afs_lock_may_be_available(struct afs_vnode *); | ||
| 490 | extern int afs_lock(struct file *, int, struct file_lock *); | ||
| 491 | extern int afs_flock(struct file *, int, struct file_lock *); | ||
| 492 | |||
| 493 | /* | ||
| 477 | * fsclient.c | 494 | * fsclient.c |
| 478 | */ | 495 | */ |
| 479 | extern int afs_fs_fetch_file_status(struct afs_server *, struct key *, | 496 | extern int afs_fs_fetch_file_status(struct afs_server *, struct key *, |
| @@ -513,6 +530,15 @@ extern int afs_fs_get_volume_status(struct afs_server *, struct key *, | |||
| 513 | struct afs_vnode *, | 530 | struct afs_vnode *, |
| 514 | struct afs_volume_status *, | 531 | struct afs_volume_status *, |
| 515 | const struct afs_wait_mode *); | 532 | const struct afs_wait_mode *); |
| 533 | extern int afs_fs_set_lock(struct afs_server *, struct key *, | ||
| 534 | struct afs_vnode *, afs_lock_type_t, | ||
| 535 | const struct afs_wait_mode *); | ||
| 536 | extern int afs_fs_extend_lock(struct afs_server *, struct key *, | ||
| 537 | struct afs_vnode *, | ||
| 538 | const struct afs_wait_mode *); | ||
| 539 | extern int afs_fs_release_lock(struct afs_server *, struct key *, | ||
| 540 | struct afs_vnode *, | ||
| 541 | const struct afs_wait_mode *); | ||
| 516 | 542 | ||
| 517 | /* | 543 | /* |
| 518 | * inode.c | 544 | * inode.c |
| @@ -681,6 +707,10 @@ extern int afs_vnode_store_data(struct afs_writeback *, pgoff_t, pgoff_t, | |||
| 681 | extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *); | 707 | extern int afs_vnode_setattr(struct afs_vnode *, struct key *, struct iattr *); |
| 682 | extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *, | 708 | extern int afs_vnode_get_volume_status(struct afs_vnode *, struct key *, |
| 683 | struct afs_volume_status *); | 709 | struct afs_volume_status *); |
| 710 | extern int afs_vnode_set_lock(struct afs_vnode *, struct key *, | ||
| 711 | afs_lock_type_t); | ||
| 712 | extern int afs_vnode_extend_lock(struct afs_vnode *, struct key *); | ||
| 713 | extern int afs_vnode_release_lock(struct afs_vnode *, struct key *); | ||
| 684 | 714 | ||
| 685 | /* | 715 | /* |
| 686 | * volume.c | 716 | * volume.c |
diff --git a/fs/afs/main.c b/fs/afs/main.c index cd21195bbb24..0f60f6b35769 100644 --- a/fs/afs/main.c +++ b/fs/afs/main.c | |||
| @@ -168,6 +168,7 @@ static void __exit afs_exit(void) | |||
| 168 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); | 168 | printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n"); |
| 169 | 169 | ||
| 170 | afs_fs_exit(); | 170 | afs_fs_exit(); |
| 171 | afs_kill_lock_manager(); | ||
| 171 | afs_close_socket(); | 172 | afs_close_socket(); |
| 172 | afs_purge_servers(); | 173 | afs_purge_servers(); |
| 173 | afs_callback_update_kill(); | 174 | afs_callback_update_kill(); |
diff --git a/fs/afs/misc.c b/fs/afs/misc.c index d1a889c40742..2d33a5f7d218 100644 --- a/fs/afs/misc.c +++ b/fs/afs/misc.c | |||
| @@ -35,6 +35,7 @@ int afs_abort_to_error(u32 abort_code) | |||
| 35 | case VOVERQUOTA: return -EDQUOT; | 35 | case VOVERQUOTA: return -EDQUOT; |
| 36 | case VBUSY: return -EBUSY; | 36 | case VBUSY: return -EBUSY; |
| 37 | case VMOVED: return -ENXIO; | 37 | case VMOVED: return -ENXIO; |
| 38 | case 0x2f6df0a: return -EWOULDBLOCK; | ||
| 38 | case 0x2f6df0c: return -EACCES; | 39 | case 0x2f6df0c: return -EACCES; |
| 39 | case 0x2f6df0f: return -EBUSY; | 40 | case 0x2f6df0f: return -EBUSY; |
| 40 | case 0x2f6df10: return -EEXIST; | 41 | case 0x2f6df10: return -EEXIST; |
diff --git a/fs/afs/proc.c b/fs/afs/proc.c index 13df512aea9e..6edb56683b9a 100644 --- a/fs/afs/proc.c +++ b/fs/afs/proc.c | |||
| @@ -201,23 +201,9 @@ static int afs_proc_cells_open(struct inode *inode, struct file *file) | |||
| 201 | */ | 201 | */ |
| 202 | static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos) | 202 | static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos) |
| 203 | { | 203 | { |
| 204 | struct list_head *_p; | ||
| 205 | loff_t pos = *_pos; | ||
| 206 | |||
| 207 | /* lock the list against modification */ | 204 | /* lock the list against modification */ |
| 208 | down_read(&afs_proc_cells_sem); | 205 | down_read(&afs_proc_cells_sem); |
| 209 | 206 | return seq_list_start_head(&afs_proc_cells, *_pos); | |
| 210 | /* allow for the header line */ | ||
| 211 | if (!pos) | ||
| 212 | return (void *) 1; | ||
| 213 | pos--; | ||
| 214 | |||
| 215 | /* find the n'th element in the list */ | ||
| 216 | list_for_each(_p, &afs_proc_cells) | ||
| 217 | if (!pos--) | ||
| 218 | break; | ||
| 219 | |||
| 220 | return _p != &afs_proc_cells ? _p : NULL; | ||
| 221 | } | 207 | } |
| 222 | 208 | ||
| 223 | /* | 209 | /* |
| @@ -225,14 +211,7 @@ static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos) | |||
| 225 | */ | 211 | */ |
| 226 | static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos) | 212 | static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos) |
| 227 | { | 213 | { |
| 228 | struct list_head *_p; | 214 | return seq_list_next(v, &afs_proc_cells, pos); |
| 229 | |||
| 230 | (*pos)++; | ||
| 231 | |||
| 232 | _p = v; | ||
| 233 | _p = v == (void *) 1 ? afs_proc_cells.next : _p->next; | ||
| 234 | |||
| 235 | return _p != &afs_proc_cells ? _p : NULL; | ||
| 236 | } | 215 | } |
| 237 | 216 | ||
| 238 | /* | 217 | /* |
| @@ -250,7 +229,7 @@ static int afs_proc_cells_show(struct seq_file *m, void *v) | |||
| 250 | { | 229 | { |
| 251 | struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link); | 230 | struct afs_cell *cell = list_entry(v, struct afs_cell, proc_link); |
| 252 | 231 | ||
| 253 | if (v == (void *) 1) { | 232 | if (v == &afs_proc_cells) { |
| 254 | /* display header on line 1 */ | 233 | /* display header on line 1 */ |
| 255 | seq_puts(m, "USE NAME\n"); | 234 | seq_puts(m, "USE NAME\n"); |
| 256 | return 0; | 235 | return 0; |
| @@ -503,26 +482,13 @@ static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file) | |||
| 503 | */ | 482 | */ |
| 504 | static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos) | 483 | static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos) |
| 505 | { | 484 | { |
| 506 | struct list_head *_p; | ||
| 507 | struct afs_cell *cell = m->private; | 485 | struct afs_cell *cell = m->private; |
| 508 | loff_t pos = *_pos; | ||
| 509 | 486 | ||
| 510 | _enter("cell=%p pos=%Ld", cell, *_pos); | 487 | _enter("cell=%p pos=%Ld", cell, *_pos); |
| 511 | 488 | ||
| 512 | /* lock the list against modification */ | 489 | /* lock the list against modification */ |
| 513 | down_read(&cell->vl_sem); | 490 | down_read(&cell->vl_sem); |
| 514 | 491 | return seq_list_start_head(&cell->vl_list, *_pos); | |
| 515 | /* allow for the header line */ | ||
| 516 | if (!pos) | ||
| 517 | return (void *) 1; | ||
| 518 | pos--; | ||
| 519 | |||
| 520 | /* find the n'th element in the list */ | ||
| 521 | list_for_each(_p, &cell->vl_list) | ||
| 522 | if (!pos--) | ||
| 523 | break; | ||
| 524 | |||
| 525 | return _p != &cell->vl_list ? _p : NULL; | ||
| 526 | } | 492 | } |
| 527 | 493 | ||
| 528 | /* | 494 | /* |
| @@ -531,17 +497,10 @@ static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos) | |||
| 531 | static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v, | 497 | static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v, |
| 532 | loff_t *_pos) | 498 | loff_t *_pos) |
| 533 | { | 499 | { |
| 534 | struct list_head *_p; | ||
| 535 | struct afs_cell *cell = p->private; | 500 | struct afs_cell *cell = p->private; |
| 536 | 501 | ||
| 537 | _enter("cell=%p pos=%Ld", cell, *_pos); | 502 | _enter("cell=%p pos=%Ld", cell, *_pos); |
| 538 | 503 | return seq_list_next(v, &cell->vl_list, _pos); | |
| 539 | (*_pos)++; | ||
| 540 | |||
| 541 | _p = v; | ||
| 542 | _p = (v == (void *) 1) ? cell->vl_list.next : _p->next; | ||
| 543 | |||
| 544 | return (_p != &cell->vl_list) ? _p : NULL; | ||
| 545 | } | 504 | } |
| 546 | 505 | ||
| 547 | /* | 506 | /* |
| @@ -569,11 +528,12 @@ const char afs_vlocation_states[][4] = { | |||
| 569 | */ | 528 | */ |
| 570 | static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) | 529 | static int afs_proc_cell_volumes_show(struct seq_file *m, void *v) |
| 571 | { | 530 | { |
| 531 | struct afs_cell *cell = m->private; | ||
| 572 | struct afs_vlocation *vlocation = | 532 | struct afs_vlocation *vlocation = |
| 573 | list_entry(v, struct afs_vlocation, link); | 533 | list_entry(v, struct afs_vlocation, link); |
| 574 | 534 | ||
| 575 | /* display header on line 1 */ | 535 | /* display header on line 1 */ |
| 576 | if (v == (void *) 1) { | 536 | if (v == &cell->vl_list) { |
| 577 | seq_puts(m, "USE STT VLID[0] VLID[1] VLID[2] NAME\n"); | 537 | seq_puts(m, "USE STT VLID[0] VLID[1] VLID[2] NAME\n"); |
| 578 | return 0; | 538 | return 0; |
| 579 | } | 539 | } |
| @@ -734,26 +694,13 @@ static int afs_proc_cell_servers_release(struct inode *inode, | |||
| 734 | static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos) | 694 | static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos) |
| 735 | __acquires(m->private->servers_lock) | 695 | __acquires(m->private->servers_lock) |
| 736 | { | 696 | { |
| 737 | struct list_head *_p; | ||
| 738 | struct afs_cell *cell = m->private; | 697 | struct afs_cell *cell = m->private; |
| 739 | loff_t pos = *_pos; | ||
| 740 | 698 | ||
| 741 | _enter("cell=%p pos=%Ld", cell, *_pos); | 699 | _enter("cell=%p pos=%Ld", cell, *_pos); |
| 742 | 700 | ||
| 743 | /* lock the list against modification */ | 701 | /* lock the list against modification */ |
| 744 | read_lock(&cell->servers_lock); | 702 | read_lock(&cell->servers_lock); |
| 745 | 703 | return seq_list_start_head(&cell->servers, *_pos); | |
| 746 | /* allow for the header line */ | ||
| 747 | if (!pos) | ||
| 748 | return (void *) 1; | ||
| 749 | pos--; | ||
| 750 | |||
| 751 | /* find the n'th element in the list */ | ||
| 752 | list_for_each(_p, &cell->servers) | ||
| 753 | if (!pos--) | ||
| 754 | break; | ||
| 755 | |||
| 756 | return _p != &cell->servers ? _p : NULL; | ||
| 757 | } | 704 | } |
| 758 | 705 | ||
| 759 | /* | 706 | /* |
| @@ -762,17 +709,10 @@ static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos) | |||
| 762 | static void *afs_proc_cell_servers_next(struct seq_file *p, void *v, | 709 | static void *afs_proc_cell_servers_next(struct seq_file *p, void *v, |
| 763 | loff_t *_pos) | 710 | loff_t *_pos) |
| 764 | { | 711 | { |
| 765 | struct list_head *_p; | ||
| 766 | struct afs_cell *cell = p->private; | 712 | struct afs_cell *cell = p->private; |
| 767 | 713 | ||
| 768 | _enter("cell=%p pos=%Ld", cell, *_pos); | 714 | _enter("cell=%p pos=%Ld", cell, *_pos); |
| 769 | 715 | return seq_list_next(v, &cell->servers, _pos); | |
| 770 | (*_pos)++; | ||
| 771 | |||
| 772 | _p = v; | ||
| 773 | _p = v == (void *) 1 ? cell->servers.next : _p->next; | ||
| 774 | |||
| 775 | return _p != &cell->servers ? _p : NULL; | ||
| 776 | } | 716 | } |
| 777 | 717 | ||
| 778 | /* | 718 | /* |
| @@ -791,11 +731,12 @@ static void afs_proc_cell_servers_stop(struct seq_file *p, void *v) | |||
| 791 | */ | 731 | */ |
| 792 | static int afs_proc_cell_servers_show(struct seq_file *m, void *v) | 732 | static int afs_proc_cell_servers_show(struct seq_file *m, void *v) |
| 793 | { | 733 | { |
| 734 | struct afs_cell *cell = m->private; | ||
| 794 | struct afs_server *server = list_entry(v, struct afs_server, link); | 735 | struct afs_server *server = list_entry(v, struct afs_server, link); |
| 795 | char ipaddr[20]; | 736 | char ipaddr[20]; |
| 796 | 737 | ||
| 797 | /* display header on line 1 */ | 738 | /* display header on line 1 */ |
| 798 | if (v == (void *) 1) { | 739 | if (v == &cell->servers) { |
| 799 | seq_puts(m, "USE ADDR STATE\n"); | 740 | seq_puts(m, "USE ADDR STATE\n"); |
| 800 | return 0; | 741 | return 0; |
| 801 | } | 742 | } |
diff --git a/fs/afs/super.c b/fs/afs/super.c index 2e8496ba1205..993cdf1cce3a 100644 --- a/fs/afs/super.c +++ b/fs/afs/super.c | |||
| @@ -460,6 +460,9 @@ static void afs_i_init_once(void *_vnode, struct kmem_cache *cachep, | |||
| 460 | spin_lock_init(&vnode->writeback_lock); | 460 | spin_lock_init(&vnode->writeback_lock); |
| 461 | spin_lock_init(&vnode->lock); | 461 | spin_lock_init(&vnode->lock); |
| 462 | INIT_LIST_HEAD(&vnode->writebacks); | 462 | INIT_LIST_HEAD(&vnode->writebacks); |
| 463 | INIT_LIST_HEAD(&vnode->pending_locks); | ||
| 464 | INIT_LIST_HEAD(&vnode->granted_locks); | ||
| 465 | INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work); | ||
| 463 | INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); | 466 | INIT_WORK(&vnode->cb_broken_work, afs_broken_callback_work); |
| 464 | } | 467 | } |
| 465 | 468 | ||
diff --git a/fs/afs/vnode.c b/fs/afs/vnode.c index 232c55dc245d..2f05c4fc2a70 100644 --- a/fs/afs/vnode.c +++ b/fs/afs/vnode.c | |||
| @@ -561,7 +561,7 @@ no_server: | |||
| 561 | /* | 561 | /* |
| 562 | * create a hard link | 562 | * create a hard link |
| 563 | */ | 563 | */ |
| 564 | extern int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode, | 564 | int afs_vnode_link(struct afs_vnode *dvnode, struct afs_vnode *vnode, |
| 565 | struct key *key, const char *name) | 565 | struct key *key, const char *name) |
| 566 | { | 566 | { |
| 567 | struct afs_server *server; | 567 | struct afs_server *server; |
| @@ -887,11 +887,6 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key, | |||
| 887 | vnode->fid.unique, | 887 | vnode->fid.unique, |
| 888 | key_serial(key)); | 888 | key_serial(key)); |
| 889 | 889 | ||
| 890 | /* this op will fetch the status */ | ||
| 891 | spin_lock(&vnode->lock); | ||
| 892 | vnode->update_cnt++; | ||
| 893 | spin_unlock(&vnode->lock); | ||
| 894 | |||
| 895 | do { | 890 | do { |
| 896 | /* pick a server to query */ | 891 | /* pick a server to query */ |
| 897 | server = afs_volume_pick_fileserver(vnode); | 892 | server = afs_volume_pick_fileserver(vnode); |
| @@ -905,20 +900,127 @@ int afs_vnode_get_volume_status(struct afs_vnode *vnode, struct key *key, | |||
| 905 | } while (!afs_volume_release_fileserver(vnode, server, ret)); | 900 | } while (!afs_volume_release_fileserver(vnode, server, ret)); |
| 906 | 901 | ||
| 907 | /* adjust the flags */ | 902 | /* adjust the flags */ |
| 908 | if (ret == 0) { | 903 | if (ret == 0) |
| 909 | afs_vnode_finalise_status_update(vnode, server); | 904 | afs_put_server(server); |
| 905 | |||
| 906 | _leave(" = %d", ret); | ||
| 907 | return ret; | ||
| 908 | |||
| 909 | no_server: | ||
| 910 | return PTR_ERR(server); | ||
| 911 | } | ||
| 912 | |||
| 913 | /* | ||
| 914 | * get a lock on a file | ||
| 915 | */ | ||
| 916 | int afs_vnode_set_lock(struct afs_vnode *vnode, struct key *key, | ||
| 917 | afs_lock_type_t type) | ||
| 918 | { | ||
| 919 | struct afs_server *server; | ||
| 920 | int ret; | ||
| 921 | |||
| 922 | _enter("%s{%x:%u.%u},%x,%u", | ||
| 923 | vnode->volume->vlocation->vldb.name, | ||
| 924 | vnode->fid.vid, | ||
| 925 | vnode->fid.vnode, | ||
| 926 | vnode->fid.unique, | ||
| 927 | key_serial(key), type); | ||
| 928 | |||
| 929 | do { | ||
| 930 | /* pick a server to query */ | ||
| 931 | server = afs_volume_pick_fileserver(vnode); | ||
| 932 | if (IS_ERR(server)) | ||
| 933 | goto no_server; | ||
| 934 | |||
| 935 | _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); | ||
| 936 | |||
| 937 | ret = afs_fs_set_lock(server, key, vnode, type, &afs_sync_call); | ||
| 938 | |||
| 939 | } while (!afs_volume_release_fileserver(vnode, server, ret)); | ||
| 940 | |||
| 941 | /* adjust the flags */ | ||
| 942 | if (ret == 0) | ||
| 943 | afs_put_server(server); | ||
| 944 | |||
| 945 | _leave(" = %d", ret); | ||
| 946 | return ret; | ||
| 947 | |||
| 948 | no_server: | ||
| 949 | return PTR_ERR(server); | ||
| 950 | } | ||
| 951 | |||
| 952 | /* | ||
| 953 | * extend a lock on a file | ||
| 954 | */ | ||
| 955 | int afs_vnode_extend_lock(struct afs_vnode *vnode, struct key *key) | ||
| 956 | { | ||
| 957 | struct afs_server *server; | ||
| 958 | int ret; | ||
| 959 | |||
| 960 | _enter("%s{%x:%u.%u},%x", | ||
| 961 | vnode->volume->vlocation->vldb.name, | ||
| 962 | vnode->fid.vid, | ||
| 963 | vnode->fid.vnode, | ||
| 964 | vnode->fid.unique, | ||
| 965 | key_serial(key)); | ||
| 966 | |||
| 967 | do { | ||
| 968 | /* pick a server to query */ | ||
| 969 | server = afs_volume_pick_fileserver(vnode); | ||
| 970 | if (IS_ERR(server)) | ||
| 971 | goto no_server; | ||
| 972 | |||
| 973 | _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); | ||
| 974 | |||
| 975 | ret = afs_fs_extend_lock(server, key, vnode, &afs_sync_call); | ||
| 976 | |||
| 977 | } while (!afs_volume_release_fileserver(vnode, server, ret)); | ||
| 978 | |||
| 979 | /* adjust the flags */ | ||
| 980 | if (ret == 0) | ||
| 981 | afs_put_server(server); | ||
| 982 | |||
| 983 | _leave(" = %d", ret); | ||
| 984 | return ret; | ||
| 985 | |||
| 986 | no_server: | ||
| 987 | return PTR_ERR(server); | ||
| 988 | } | ||
| 989 | |||
| 990 | /* | ||
| 991 | * release a lock on a file | ||
| 992 | */ | ||
| 993 | int afs_vnode_release_lock(struct afs_vnode *vnode, struct key *key) | ||
| 994 | { | ||
| 995 | struct afs_server *server; | ||
| 996 | int ret; | ||
| 997 | |||
| 998 | _enter("%s{%x:%u.%u},%x", | ||
| 999 | vnode->volume->vlocation->vldb.name, | ||
| 1000 | vnode->fid.vid, | ||
| 1001 | vnode->fid.vnode, | ||
| 1002 | vnode->fid.unique, | ||
| 1003 | key_serial(key)); | ||
| 1004 | |||
| 1005 | do { | ||
| 1006 | /* pick a server to query */ | ||
| 1007 | server = afs_volume_pick_fileserver(vnode); | ||
| 1008 | if (IS_ERR(server)) | ||
| 1009 | goto no_server; | ||
| 1010 | |||
| 1011 | _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr)); | ||
| 1012 | |||
| 1013 | ret = afs_fs_release_lock(server, key, vnode, &afs_sync_call); | ||
| 1014 | |||
| 1015 | } while (!afs_volume_release_fileserver(vnode, server, ret)); | ||
| 1016 | |||
| 1017 | /* adjust the flags */ | ||
| 1018 | if (ret == 0) | ||
| 910 | afs_put_server(server); | 1019 | afs_put_server(server); |
| 911 | } else { | ||
| 912 | afs_vnode_status_update_failed(vnode, ret); | ||
| 913 | } | ||
| 914 | 1020 | ||
| 915 | _leave(" = %d", ret); | 1021 | _leave(" = %d", ret); |
| 916 | return ret; | 1022 | return ret; |
| 917 | 1023 | ||
| 918 | no_server: | 1024 | no_server: |
| 919 | spin_lock(&vnode->lock); | ||
| 920 | vnode->update_cnt--; | ||
| 921 | ASSERTCMP(vnode->update_cnt, >=, 0); | ||
| 922 | spin_unlock(&vnode->lock); | ||
| 923 | return PTR_ERR(server); | 1025 | return PTR_ERR(server); |
| 924 | } | 1026 | } |
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c index 40fe3a3222e4..a260198306c2 100644 --- a/fs/anon_inodes.c +++ b/fs/anon_inodes.c | |||
| @@ -53,7 +53,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = { | |||
| 53 | }; | 53 | }; |
| 54 | 54 | ||
| 55 | /** | 55 | /** |
| 56 | * anon_inode_getfd - creates a new file instance by hooking it up to and | 56 | * anon_inode_getfd - creates a new file instance by hooking it up to an |
| 57 | * anonymous inode, and a dentry that describe the "class" | 57 | * anonymous inode, and a dentry that describe the "class" |
| 58 | * of the file | 58 | * of the file |
| 59 | * | 59 | * |
| @@ -66,7 +66,7 @@ static struct dentry_operations anon_inodefs_dentry_operations = { | |||
| 66 | * | 66 | * |
| 67 | * Creates a new file by hooking it on a single inode. This is useful for files | 67 | * Creates a new file by hooking it on a single inode. This is useful for files |
| 68 | * that do not need to have a full-fledged inode in order to operate correctly. | 68 | * that do not need to have a full-fledged inode in order to operate correctly. |
| 69 | * All the files created with anon_inode_getfd() will share a single inode, by | 69 | * All the files created with anon_inode_getfd() will share a single inode, |
| 70 | * hence saving memory and avoiding code duplication for the file/inode/dentry | 70 | * hence saving memory and avoiding code duplication for the file/inode/dentry |
| 71 | * setup. | 71 | * setup. |
| 72 | */ | 72 | */ |
| @@ -141,9 +141,9 @@ err_put_filp: | |||
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | /* | 143 | /* |
| 144 | * A single inode exist for all anon_inode files. Contrary to pipes, | 144 | * A single inode exists for all anon_inode files. Contrary to pipes, |
| 145 | * anon_inode inodes has no per-instance data associated, so we can avoid | 145 | * anon_inode inodes have no associated per-instance data, so we need |
| 146 | * the allocation of multiple of them. | 146 | * only allocate one of them. |
| 147 | */ | 147 | */ |
| 148 | static struct inode *anon_inode_mkinode(void) | 148 | static struct inode *anon_inode_mkinode(void) |
| 149 | { | 149 | { |
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c index 08e4414b8374..a27e42bf3400 100644 --- a/fs/binfmt_elf.c +++ b/fs/binfmt_elf.c | |||
| @@ -45,7 +45,7 @@ | |||
| 45 | 45 | ||
| 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); | 46 | static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs); |
| 47 | static int load_elf_library(struct file *); | 47 | static int load_elf_library(struct file *); |
| 48 | 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, unsigned long); |
| 49 | 49 | ||
| 50 | /* | 50 | /* |
| 51 | * If we don't support core dumping, then supply a NULL so we | 51 | * If we don't support core dumping, then supply a NULL so we |
| @@ -80,7 +80,7 @@ static struct linux_binfmt elf_format = { | |||
| 80 | .hasvdso = 1 | 80 | .hasvdso = 1 |
| 81 | }; | 81 | }; |
| 82 | 82 | ||
| 83 | #define BAD_ADDR(x) ((unsigned long)(x) >= TASK_SIZE) | 83 | #define BAD_ADDR(x) IS_ERR_VALUE(x) |
| 84 | 84 | ||
| 85 | static int set_brk(unsigned long start, unsigned long end) | 85 | static int set_brk(unsigned long start, unsigned long end) |
| 86 | { | 86 | { |
| @@ -285,33 +285,70 @@ create_elf_tables(struct linux_binprm *bprm, struct elfhdr *exec, | |||
| 285 | #ifndef elf_map | 285 | #ifndef elf_map |
| 286 | 286 | ||
| 287 | static unsigned long elf_map(struct file *filep, unsigned long addr, | 287 | static unsigned long elf_map(struct file *filep, unsigned long addr, |
| 288 | struct elf_phdr *eppnt, int prot, int type) | 288 | struct elf_phdr *eppnt, int prot, int type, |
| 289 | unsigned long total_size) | ||
| 289 | { | 290 | { |
| 290 | unsigned long map_addr; | 291 | unsigned long map_addr; |
| 291 | unsigned long pageoffset = ELF_PAGEOFFSET(eppnt->p_vaddr); | 292 | unsigned long size = eppnt->p_filesz + ELF_PAGEOFFSET(eppnt->p_vaddr); |
| 293 | unsigned long off = eppnt->p_offset - ELF_PAGEOFFSET(eppnt->p_vaddr); | ||
| 294 | addr = ELF_PAGESTART(addr); | ||
| 295 | size = ELF_PAGEALIGN(size); | ||
| 292 | 296 | ||
| 293 | down_write(¤t->mm->mmap_sem); | ||
| 294 | /* mmap() will return -EINVAL if given a zero size, but a | 297 | /* mmap() will return -EINVAL if given a zero size, but a |
| 295 | * segment with zero filesize is perfectly valid */ | 298 | * segment with zero filesize is perfectly valid */ |
| 296 | if (eppnt->p_filesz + pageoffset) | 299 | if (!size) |
| 297 | map_addr = do_mmap(filep, ELF_PAGESTART(addr), | 300 | return addr; |
| 298 | eppnt->p_filesz + pageoffset, prot, type, | 301 | |
| 299 | eppnt->p_offset - pageoffset); | 302 | down_write(¤t->mm->mmap_sem); |
| 300 | else | 303 | /* |
| 301 | map_addr = ELF_PAGESTART(addr); | 304 | * total_size is the size of the ELF (interpreter) image. |
| 305 | * The _first_ mmap needs to know the full size, otherwise | ||
| 306 | * randomization might put this image into an overlapping | ||
| 307 | * position with the ELF binary image. (since size < total_size) | ||
| 308 | * So we first map the 'big' image - and unmap the remainder at | ||
| 309 | * the end. (which unmap is needed for ELF images with holes.) | ||
| 310 | */ | ||
| 311 | if (total_size) { | ||
| 312 | total_size = ELF_PAGEALIGN(total_size); | ||
| 313 | map_addr = do_mmap(filep, addr, total_size, prot, type, off); | ||
| 314 | if (!BAD_ADDR(map_addr)) | ||
| 315 | do_munmap(current->mm, map_addr+size, total_size-size); | ||
| 316 | } else | ||
| 317 | map_addr = do_mmap(filep, addr, size, prot, type, off); | ||
| 318 | |||
| 302 | up_write(¤t->mm->mmap_sem); | 319 | up_write(¤t->mm->mmap_sem); |
| 303 | return(map_addr); | 320 | return(map_addr); |
| 304 | } | 321 | } |
| 305 | 322 | ||
| 306 | #endif /* !elf_map */ | 323 | #endif /* !elf_map */ |
| 307 | 324 | ||
| 325 | static unsigned long total_mapping_size(struct elf_phdr *cmds, int nr) | ||
| 326 | { | ||
| 327 | int i, first_idx = -1, last_idx = -1; | ||
| 328 | |||
| 329 | for (i = 0; i < nr; i++) { | ||
| 330 | if (cmds[i].p_type == PT_LOAD) { | ||
| 331 | last_idx = i; | ||
| 332 | if (first_idx == -1) | ||
| 333 | first_idx = i; | ||
| 334 | } | ||
| 335 | } | ||
| 336 | if (first_idx == -1) | ||
| 337 | return 0; | ||
| 338 | |||
| 339 | return cmds[last_idx].p_vaddr + cmds[last_idx].p_memsz - | ||
| 340 | ELF_PAGESTART(cmds[first_idx].p_vaddr); | ||
| 341 | } | ||
| 342 | |||
| 343 | |||
| 308 | /* This is much more generalized than the library routine read function, | 344 | /* This is much more generalized than the library routine read function, |
| 309 | so we keep this separate. Technically the library read function | 345 | so we keep this separate. Technically the library read function |
| 310 | is only provided so that we can read a.out libraries that have | 346 | is only provided so that we can read a.out libraries that have |
| 311 | an ELF header */ | 347 | an ELF header */ |
| 312 | 348 | ||
| 313 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | 349 | static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, |
| 314 | struct file *interpreter, unsigned long *interp_load_addr) | 350 | struct file *interpreter, unsigned long *interp_map_addr, |
| 351 | unsigned long no_base) | ||
| 315 | { | 352 | { |
| 316 | struct elf_phdr *elf_phdata; | 353 | struct elf_phdr *elf_phdata; |
| 317 | struct elf_phdr *eppnt; | 354 | struct elf_phdr *eppnt; |
| @@ -319,6 +356,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
| 319 | int load_addr_set = 0; | 356 | int load_addr_set = 0; |
| 320 | unsigned long last_bss = 0, elf_bss = 0; | 357 | unsigned long last_bss = 0, elf_bss = 0; |
| 321 | unsigned long error = ~0UL; | 358 | unsigned long error = ~0UL; |
| 359 | unsigned long total_size; | ||
| 322 | int retval, i, size; | 360 | int retval, i, size; |
| 323 | 361 | ||
| 324 | /* First of all, some simple consistency checks */ | 362 | /* First of all, some simple consistency checks */ |
| @@ -357,6 +395,12 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
| 357 | goto out_close; | 395 | goto out_close; |
| 358 | } | 396 | } |
| 359 | 397 | ||
| 398 | total_size = total_mapping_size(elf_phdata, interp_elf_ex->e_phnum); | ||
| 399 | if (!total_size) { | ||
| 400 | error = -EINVAL; | ||
| 401 | goto out_close; | ||
| 402 | } | ||
| 403 | |||
| 360 | eppnt = elf_phdata; | 404 | eppnt = elf_phdata; |
| 361 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { | 405 | for (i = 0; i < interp_elf_ex->e_phnum; i++, eppnt++) { |
| 362 | if (eppnt->p_type == PT_LOAD) { | 406 | if (eppnt->p_type == PT_LOAD) { |
| @@ -374,9 +418,14 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
| 374 | vaddr = eppnt->p_vaddr; | 418 | vaddr = eppnt->p_vaddr; |
| 375 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) | 419 | if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) |
| 376 | elf_type |= MAP_FIXED; | 420 | elf_type |= MAP_FIXED; |
| 421 | else if (no_base && interp_elf_ex->e_type == ET_DYN) | ||
| 422 | load_addr = -vaddr; | ||
| 377 | 423 | ||
| 378 | map_addr = elf_map(interpreter, load_addr + vaddr, | 424 | map_addr = elf_map(interpreter, load_addr + vaddr, |
| 379 | eppnt, elf_prot, elf_type); | 425 | eppnt, elf_prot, elf_type, total_size); |
| 426 | total_size = 0; | ||
| 427 | if (!*interp_map_addr) | ||
| 428 | *interp_map_addr = map_addr; | ||
| 380 | error = map_addr; | 429 | error = map_addr; |
| 381 | if (BAD_ADDR(map_addr)) | 430 | if (BAD_ADDR(map_addr)) |
| 382 | goto out_close; | 431 | goto out_close; |
| @@ -442,8 +491,7 @@ static unsigned long load_elf_interp(struct elfhdr *interp_elf_ex, | |||
| 442 | goto out_close; | 491 | goto out_close; |
| 443 | } | 492 | } |
| 444 | 493 | ||
| 445 | *interp_load_addr = load_addr; | 494 | error = load_addr; |
| 446 | error = ((unsigned long)interp_elf_ex->e_entry) + load_addr; | ||
| 447 | 495 | ||
| 448 | out_close: | 496 | out_close: |
| 449 | kfree(elf_phdata); | 497 | kfree(elf_phdata); |
| @@ -540,7 +588,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 540 | int elf_exec_fileno; | 588 | int elf_exec_fileno; |
| 541 | int retval, i; | 589 | int retval, i; |
| 542 | unsigned int size; | 590 | unsigned int size; |
| 543 | unsigned long elf_entry, interp_load_addr = 0; | 591 | unsigned long elf_entry; |
| 592 | unsigned long interp_load_addr = 0; | ||
| 544 | unsigned long start_code, end_code, start_data, end_data; | 593 | unsigned long start_code, end_code, start_data, end_data; |
| 545 | unsigned long reloc_func_desc = 0; | 594 | unsigned long reloc_func_desc = 0; |
| 546 | char passed_fileno[6]; | 595 | char passed_fileno[6]; |
| @@ -808,9 +857,7 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 808 | current->mm->start_stack = bprm->p; | 857 | current->mm->start_stack = bprm->p; |
| 809 | 858 | ||
| 810 | /* Now we do a little grungy work by mmaping the ELF image into | 859 | /* Now we do a little grungy work by mmaping the ELF image into |
| 811 | the correct location in memory. At this point, we assume that | 860 | the correct location in memory. */ |
| 812 | the image should be loaded at fixed address, not at a variable | ||
| 813 | address. */ | ||
| 814 | for(i = 0, elf_ppnt = elf_phdata; | 861 | for(i = 0, elf_ppnt = elf_phdata; |
| 815 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { | 862 | i < loc->elf_ex.e_phnum; i++, elf_ppnt++) { |
| 816 | int elf_prot = 0, elf_flags; | 863 | int elf_prot = 0, elf_flags; |
| @@ -864,11 +911,15 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 864 | * default mmap base, as well as whatever program they | 911 | * default mmap base, as well as whatever program they |
| 865 | * might try to exec. This is because the brk will | 912 | * might try to exec. This is because the brk will |
| 866 | * follow the loader, and is not movable. */ | 913 | * follow the loader, and is not movable. */ |
| 914 | #ifdef CONFIG_X86 | ||
| 915 | load_bias = 0; | ||
| 916 | #else | ||
| 867 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); | 917 | load_bias = ELF_PAGESTART(ELF_ET_DYN_BASE - vaddr); |
| 918 | #endif | ||
| 868 | } | 919 | } |
| 869 | 920 | ||
| 870 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, | 921 | error = elf_map(bprm->file, load_bias + vaddr, elf_ppnt, |
| 871 | elf_prot, elf_flags); | 922 | elf_prot, elf_flags,0); |
| 872 | if (BAD_ADDR(error)) { | 923 | if (BAD_ADDR(error)) { |
| 873 | send_sig(SIGKILL, current, 0); | 924 | send_sig(SIGKILL, current, 0); |
| 874 | retval = IS_ERR((void *)error) ? | 925 | retval = IS_ERR((void *)error) ? |
| @@ -944,13 +995,25 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs) | |||
| 944 | } | 995 | } |
| 945 | 996 | ||
| 946 | if (elf_interpreter) { | 997 | if (elf_interpreter) { |
| 947 | if (interpreter_type == INTERPRETER_AOUT) | 998 | if (interpreter_type == INTERPRETER_AOUT) { |
| 948 | elf_entry = load_aout_interp(&loc->interp_ex, | 999 | elf_entry = load_aout_interp(&loc->interp_ex, |
| 949 | interpreter); | 1000 | interpreter); |
| 950 | else | 1001 | } else { |
| 1002 | unsigned long uninitialized_var(interp_map_addr); | ||
| 1003 | |||
| 951 | elf_entry = load_elf_interp(&loc->interp_elf_ex, | 1004 | elf_entry = load_elf_interp(&loc->interp_elf_ex, |
| 952 | interpreter, | 1005 | interpreter, |
| 953 | &interp_load_addr); | 1006 | &interp_map_addr, |
| 1007 | load_bias); | ||
| 1008 | if (!BAD_ADDR(elf_entry)) { | ||
| 1009 | /* | ||
| 1010 | * load_elf_interp() returns relocation | ||
| 1011 | * adjustment | ||
| 1012 | */ | ||
| 1013 | interp_load_addr = elf_entry; | ||
| 1014 | elf_entry += loc->interp_elf_ex.e_entry; | ||
| 1015 | } | ||
| 1016 | } | ||
| 954 | if (BAD_ADDR(elf_entry)) { | 1017 | if (BAD_ADDR(elf_entry)) { |
| 955 | force_sig(SIGSEGV, current); | 1018 | force_sig(SIGSEGV, current); |
| 956 | retval = IS_ERR((void *)elf_entry) ? | 1019 | retval = IS_ERR((void *)elf_entry) ? |
diff --git a/fs/block_dev.c b/fs/block_dev.c index b3e9bfa748cf..3635315e3b99 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c | |||
| @@ -588,12 +588,10 @@ EXPORT_SYMBOL(bdget); | |||
| 588 | 588 | ||
| 589 | long nr_blockdev_pages(void) | 589 | long nr_blockdev_pages(void) |
| 590 | { | 590 | { |
| 591 | struct list_head *p; | 591 | struct block_device *bdev; |
| 592 | long ret = 0; | 592 | long ret = 0; |
| 593 | spin_lock(&bdev_lock); | 593 | spin_lock(&bdev_lock); |
| 594 | list_for_each(p, &all_bdevs) { | 594 | list_for_each_entry(bdev, &all_bdevs, bd_list) { |
| 595 | struct block_device *bdev; | ||
| 596 | bdev = list_entry(p, struct block_device, bd_list); | ||
| 597 | ret += bdev->bd_inode->i_mapping->nrpages; | 595 | ret += bdev->bd_inode->i_mapping->nrpages; |
| 598 | } | 596 | } |
| 599 | spin_unlock(&bdev_lock); | 597 | spin_unlock(&bdev_lock); |
| @@ -874,7 +872,7 @@ static struct bd_holder *find_bd_holder(struct block_device *bdev, | |||
| 874 | */ | 872 | */ |
| 875 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | 873 | static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) |
| 876 | { | 874 | { |
| 877 | int ret; | 875 | int err; |
| 878 | 876 | ||
| 879 | if (!bo) | 877 | if (!bo) |
| 880 | return -EINVAL; | 878 | return -EINVAL; |
| @@ -882,15 +880,18 @@ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) | |||
| 882 | if (!bd_holder_grab_dirs(bdev, bo)) | 880 | if (!bd_holder_grab_dirs(bdev, bo)) |
| 883 | return -EBUSY; | 881 | return -EBUSY; |
| 884 | 882 | ||
| 885 | ret = add_symlink(bo->sdir, bo->sdev); | 883 | err = add_symlink(bo->sdir, bo->sdev); |
| 886 | if (ret == 0) { | 884 | if (err) |
| 887 | ret = add_symlink(bo->hdir, bo->hdev); | 885 | return err; |
| 888 | if (ret) | 886 | |
| 889 | del_symlink(bo->sdir, bo->sdev); | 887 | err = add_symlink(bo->hdir, bo->hdev); |
| 888 | if (err) { | ||
| 889 | del_symlink(bo->sdir, bo->sdev); | ||
| 890 | return err; | ||
| 890 | } | 891 | } |
| 891 | if (ret == 0) | 892 | |
| 892 | list_add_tail(&bo->list, &bdev->bd_holder_list); | 893 | list_add_tail(&bo->list, &bdev->bd_holder_list); |
| 893 | return ret; | 894 | return 0; |
| 894 | } | 895 | } |
| 895 | 896 | ||
| 896 | /** | 897 | /** |
| @@ -948,7 +949,7 @@ static struct bd_holder *del_bd_holder(struct block_device *bdev, | |||
| 948 | static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | 949 | static int bd_claim_by_kobject(struct block_device *bdev, void *holder, |
| 949 | struct kobject *kobj) | 950 | struct kobject *kobj) |
| 950 | { | 951 | { |
| 951 | int res; | 952 | int err; |
| 952 | struct bd_holder *bo, *found; | 953 | struct bd_holder *bo, *found; |
| 953 | 954 | ||
| 954 | if (!kobj) | 955 | if (!kobj) |
| @@ -959,21 +960,24 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
| 959 | return -ENOMEM; | 960 | return -ENOMEM; |
| 960 | 961 | ||
| 961 | mutex_lock(&bdev->bd_mutex); | 962 | mutex_lock(&bdev->bd_mutex); |
| 962 | res = bd_claim(bdev, holder); | ||
| 963 | if (res == 0) { | ||
| 964 | found = find_bd_holder(bdev, bo); | ||
| 965 | if (found == NULL) { | ||
| 966 | res = add_bd_holder(bdev, bo); | ||
| 967 | if (res) | ||
| 968 | bd_release(bdev); | ||
| 969 | } | ||
| 970 | } | ||
| 971 | 963 | ||
| 972 | if (res || found) | 964 | err = bd_claim(bdev, holder); |
| 973 | free_bd_holder(bo); | 965 | if (err) |
| 974 | mutex_unlock(&bdev->bd_mutex); | 966 | goto fail; |
| 975 | 967 | ||
| 976 | return res; | 968 | found = find_bd_holder(bdev, bo); |
| 969 | if (found) | ||
| 970 | goto fail; | ||
| 971 | |||
| 972 | err = add_bd_holder(bdev, bo); | ||
| 973 | if (err) | ||
| 974 | bd_release(bdev); | ||
| 975 | else | ||
| 976 | bo = NULL; | ||
| 977 | fail: | ||
| 978 | mutex_unlock(&bdev->bd_mutex); | ||
| 979 | free_bd_holder(bo); | ||
| 980 | return err; | ||
| 977 | } | 981 | } |
| 978 | 982 | ||
| 979 | /** | 983 | /** |
| @@ -987,15 +991,12 @@ static int bd_claim_by_kobject(struct block_device *bdev, void *holder, | |||
| 987 | static void bd_release_from_kobject(struct block_device *bdev, | 991 | static void bd_release_from_kobject(struct block_device *bdev, |
| 988 | struct kobject *kobj) | 992 | struct kobject *kobj) |
| 989 | { | 993 | { |
| 990 | struct bd_holder *bo; | ||
| 991 | |||
| 992 | if (!kobj) | 994 | if (!kobj) |
| 993 | return; | 995 | return; |
| 994 | 996 | ||
| 995 | mutex_lock(&bdev->bd_mutex); | 997 | mutex_lock(&bdev->bd_mutex); |
| 996 | bd_release(bdev); | 998 | bd_release(bdev); |
| 997 | if ((bo = del_bd_holder(bdev, kobj))) | 999 | free_bd_holder(del_bd_holder(bdev, kobj)); |
| 998 | free_bd_holder(bo); | ||
| 999 | mutex_unlock(&bdev->bd_mutex); | 1000 | mutex_unlock(&bdev->bd_mutex); |
| 1000 | } | 1001 | } |
| 1001 | 1002 | ||
diff --git a/fs/buffer.c b/fs/buffer.c index aa68206bd517..424165b569f8 100644 --- a/fs/buffer.c +++ b/fs/buffer.c | |||
| @@ -1026,11 +1026,6 @@ failed: | |||
| 1026 | /* | 1026 | /* |
| 1027 | * Create buffers for the specified block device block's page. If | 1027 | * Create buffers for the specified block device block's page. If |
| 1028 | * that page was dirty, the buffers are set dirty also. | 1028 | * that page was dirty, the buffers are set dirty also. |
| 1029 | * | ||
| 1030 | * Except that's a bug. Attaching dirty buffers to a dirty | ||
| 1031 | * blockdev's page can result in filesystem corruption, because | ||
| 1032 | * some of those buffers may be aliases of filesystem data. | ||
| 1033 | * grow_dev_page() will go BUG() if this happens. | ||
| 1034 | */ | 1029 | */ |
| 1035 | static int | 1030 | static int |
| 1036 | grow_buffers(struct block_device *bdev, sector_t block, int size) | 1031 | grow_buffers(struct block_device *bdev, sector_t block, int size) |
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index 6b44cdc96fac..e440a7b95d02 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
| @@ -63,6 +63,7 @@ | |||
| 63 | #include <linux/wireless.h> | 63 | #include <linux/wireless.h> |
| 64 | #include <linux/atalk.h> | 64 | #include <linux/atalk.h> |
| 65 | #include <linux/blktrace_api.h> | 65 | #include <linux/blktrace_api.h> |
| 66 | #include <linux/loop.h> | ||
| 66 | 67 | ||
| 67 | #include <net/bluetooth/bluetooth.h> | 68 | #include <net/bluetooth/bluetooth.h> |
| 68 | #include <net/bluetooth/hci.h> | 69 | #include <net/bluetooth/hci.h> |
| @@ -3489,6 +3490,9 @@ HANDLE_IOCTL(LPSETTIMEOUT, lp_timeout_trans) | |||
| 3489 | 3490 | ||
| 3490 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) | 3491 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_BOTH32) |
| 3491 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) | 3492 | IGNORE_IOCTL(VFAT_IOCTL_READDIR_SHORT32) |
| 3493 | |||
| 3494 | /* loop */ | ||
| 3495 | IGNORE_IOCTL(LOOP_CLR_FD) | ||
| 3492 | }; | 3496 | }; |
| 3493 | 3497 | ||
| 3494 | #define IOCTL_HASHSIZE 256 | 3498 | #define IOCTL_HASHSIZE 256 |
diff --git a/fs/drop_caches.c b/fs/drop_caches.c index 03ea7696fe39..59375efcf39d 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c | |||
| @@ -20,7 +20,7 @@ static void drop_pagecache_sb(struct super_block *sb) | |||
| 20 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { | 20 | list_for_each_entry(inode, &sb->s_inodes, i_sb_list) { |
| 21 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) | 21 | if (inode->i_state & (I_FREEING|I_WILL_FREE)) |
| 22 | continue; | 22 | continue; |
| 23 | invalidate_mapping_pages(inode->i_mapping, 0, -1); | 23 | __invalidate_mapping_pages(inode->i_mapping, 0, -1, true); |
| 24 | } | 24 | } |
| 25 | spin_unlock(&inode_lock); | 25 | spin_unlock(&inode_lock); |
| 26 | } | 26 | } |
diff --git a/fs/ext2/file.c b/fs/ext2/file.c index 04afeecaaef3..ab7961260c49 100644 --- a/fs/ext2/file.c +++ b/fs/ext2/file.c | |||
| @@ -24,9 +24,9 @@ | |||
| 24 | #include "acl.h" | 24 | #include "acl.h" |
| 25 | 25 | ||
| 26 | /* | 26 | /* |
| 27 | * Called when an inode is released. Note that this is different | 27 | * Called when filp is released. This happens when all file descriptors |
| 28 | * from ext2_open_file: open gets called at every open, but release | 28 | * for a single struct file are closed. Note that different open() calls |
| 29 | * gets called only when /all/ the files are closed. | 29 | * for the same file yield different struct file structures. |
| 30 | */ | 30 | */ |
| 31 | static int ext2_release_file (struct inode * inode, struct file * filp) | 31 | static int ext2_release_file (struct inode * inode, struct file * filp) |
| 32 | { | 32 | { |
diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 5de5061eb331..b2efd9083b9b 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c | |||
| @@ -1099,15 +1099,18 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 1099 | struct super_block *sb = dentry->d_sb; | 1099 | struct super_block *sb = dentry->d_sb; |
| 1100 | struct ext2_sb_info *sbi = EXT2_SB(sb); | 1100 | struct ext2_sb_info *sbi = EXT2_SB(sb); |
| 1101 | struct ext2_super_block *es = sbi->s_es; | 1101 | struct ext2_super_block *es = sbi->s_es; |
| 1102 | unsigned long overhead; | ||
| 1103 | int i; | ||
| 1104 | u64 fsid; | 1102 | u64 fsid; |
| 1105 | 1103 | ||
| 1106 | if (test_opt (sb, MINIX_DF)) | 1104 | if (test_opt (sb, MINIX_DF)) |
| 1107 | overhead = 0; | 1105 | sbi->s_overhead_last = 0; |
| 1108 | else { | 1106 | else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { |
| 1107 | unsigned long i, overhead = 0; | ||
| 1108 | smp_rmb(); | ||
| 1109 | |||
| 1109 | /* | 1110 | /* |
| 1110 | * Compute the overhead (FS structures) | 1111 | * Compute the overhead (FS structures). This is constant |
| 1112 | * for a given filesystem unless the number of block groups | ||
| 1113 | * changes so we cache the previous value until it does. | ||
| 1111 | */ | 1114 | */ |
| 1112 | 1115 | ||
| 1113 | /* | 1116 | /* |
| @@ -1131,17 +1134,22 @@ static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 1131 | */ | 1134 | */ |
| 1132 | overhead += (sbi->s_groups_count * | 1135 | overhead += (sbi->s_groups_count * |
| 1133 | (2 + sbi->s_itb_per_group)); | 1136 | (2 + sbi->s_itb_per_group)); |
| 1137 | sbi->s_overhead_last = overhead; | ||
| 1138 | smp_wmb(); | ||
| 1139 | sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); | ||
| 1134 | } | 1140 | } |
| 1135 | 1141 | ||
| 1136 | buf->f_type = EXT2_SUPER_MAGIC; | 1142 | buf->f_type = EXT2_SUPER_MAGIC; |
| 1137 | buf->f_bsize = sb->s_blocksize; | 1143 | buf->f_bsize = sb->s_blocksize; |
| 1138 | buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; | 1144 | buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last; |
| 1139 | buf->f_bfree = ext2_count_free_blocks(sb); | 1145 | buf->f_bfree = ext2_count_free_blocks(sb); |
| 1146 | es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); | ||
| 1140 | buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); | 1147 | buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); |
| 1141 | if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) | 1148 | if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) |
| 1142 | buf->f_bavail = 0; | 1149 | buf->f_bavail = 0; |
| 1143 | buf->f_files = le32_to_cpu(es->s_inodes_count); | 1150 | buf->f_files = le32_to_cpu(es->s_inodes_count); |
| 1144 | buf->f_ffree = ext2_count_free_inodes(sb); | 1151 | buf->f_ffree = ext2_count_free_inodes(sb); |
| 1152 | es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); | ||
| 1145 | buf->f_namelen = EXT2_NAME_LEN; | 1153 | buf->f_namelen = EXT2_NAME_LEN; |
| 1146 | fsid = le64_to_cpup((void *)es->s_uuid) ^ | 1154 | fsid = le64_to_cpup((void *)es->s_uuid) ^ |
| 1147 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); | 1155 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); |
diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 2a85ddee4740..de4e3161e479 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c | |||
| @@ -3195,7 +3195,7 @@ int ext3_change_inode_journal_flag(struct inode *inode, int val) | |||
| 3195 | */ | 3195 | */ |
| 3196 | 3196 | ||
| 3197 | journal = EXT3_JOURNAL(inode); | 3197 | journal = EXT3_JOURNAL(inode); |
| 3198 | if (is_journal_aborted(journal) || IS_RDONLY(inode)) | 3198 | if (is_journal_aborted(journal)) |
| 3199 | return -EROFS; | 3199 | return -EROFS; |
| 3200 | 3200 | ||
| 3201 | journal_lock_updates(journal); | 3201 | journal_lock_updates(journal); |
diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 9bb046df827a..1586807b8177 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c | |||
| @@ -1019,6 +1019,11 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str | |||
| 1019 | 1019 | ||
| 1020 | if (!inode) | 1020 | if (!inode) |
| 1021 | return ERR_PTR(-EACCES); | 1021 | return ERR_PTR(-EACCES); |
| 1022 | |||
| 1023 | if (is_bad_inode(inode)) { | ||
| 1024 | iput(inode); | ||
| 1025 | return ERR_PTR(-ENOENT); | ||
| 1026 | } | ||
| 1022 | } | 1027 | } |
| 1023 | return d_splice_alias(inode, dentry); | 1028 | return d_splice_alias(inode, dentry); |
| 1024 | } | 1029 | } |
| @@ -1054,6 +1059,11 @@ struct dentry *ext3_get_parent(struct dentry *child) | |||
| 1054 | if (!inode) | 1059 | if (!inode) |
| 1055 | return ERR_PTR(-EACCES); | 1060 | return ERR_PTR(-EACCES); |
| 1056 | 1061 | ||
| 1062 | if (is_bad_inode(inode)) { | ||
| 1063 | iput(inode); | ||
| 1064 | return ERR_PTR(-ENOENT); | ||
| 1065 | } | ||
| 1066 | |||
| 1057 | parent = d_alloc_anon(inode); | 1067 | parent = d_alloc_anon(inode); |
| 1058 | if (!parent) { | 1068 | if (!parent) { |
| 1059 | iput(inode); | 1069 | iput(inode); |
diff --git a/fs/ext3/super.c b/fs/ext3/super.c index 6e3062913a92..51d1c456cdab 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c | |||
| @@ -35,6 +35,7 @@ | |||
| 35 | #include <linux/namei.h> | 35 | #include <linux/namei.h> |
| 36 | #include <linux/quotaops.h> | 36 | #include <linux/quotaops.h> |
| 37 | #include <linux/seq_file.h> | 37 | #include <linux/seq_file.h> |
| 38 | #include <linux/log2.h> | ||
| 38 | 39 | ||
| 39 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
| 40 | 41 | ||
| @@ -459,6 +460,14 @@ static struct inode *ext3_alloc_inode(struct super_block *sb) | |||
| 459 | 460 | ||
| 460 | static void ext3_destroy_inode(struct inode *inode) | 461 | static void ext3_destroy_inode(struct inode *inode) |
| 461 | { | 462 | { |
| 463 | if (!list_empty(&(EXT3_I(inode)->i_orphan))) { | ||
| 464 | printk("EXT3 Inode %p: orphan list check failed!\n", | ||
| 465 | EXT3_I(inode)); | ||
| 466 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4, | ||
| 467 | EXT3_I(inode), sizeof(struct ext3_inode_info), | ||
| 468 | false); | ||
| 469 | dump_stack(); | ||
| 470 | } | ||
| 462 | kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); | 471 | kmem_cache_free(ext3_inode_cachep, EXT3_I(inode)); |
| 463 | } | 472 | } |
| 464 | 473 | ||
| @@ -1566,7 +1575,7 @@ static int ext3_fill_super (struct super_block *sb, void *data, int silent) | |||
| 1566 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); | 1575 | sbi->s_inode_size = le16_to_cpu(es->s_inode_size); |
| 1567 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); | 1576 | sbi->s_first_ino = le32_to_cpu(es->s_first_ino); |
| 1568 | if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || | 1577 | if ((sbi->s_inode_size < EXT3_GOOD_OLD_INODE_SIZE) || |
| 1569 | (sbi->s_inode_size & (sbi->s_inode_size - 1)) || | 1578 | (!is_power_of_2(sbi->s_inode_size)) || |
| 1570 | (sbi->s_inode_size > blocksize)) { | 1579 | (sbi->s_inode_size > blocksize)) { |
| 1571 | printk (KERN_ERR | 1580 | printk (KERN_ERR |
| 1572 | "EXT3-fs: unsupported inode size: %d\n", | 1581 | "EXT3-fs: unsupported inode size: %d\n", |
| @@ -2075,6 +2084,7 @@ static int ext3_create_journal(struct super_block * sb, | |||
| 2075 | unsigned int journal_inum) | 2084 | unsigned int journal_inum) |
| 2076 | { | 2085 | { |
| 2077 | journal_t *journal; | 2086 | journal_t *journal; |
| 2087 | int err; | ||
| 2078 | 2088 | ||
| 2079 | if (sb->s_flags & MS_RDONLY) { | 2089 | if (sb->s_flags & MS_RDONLY) { |
| 2080 | printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to " | 2090 | printk(KERN_ERR "EXT3-fs: readonly filesystem when trying to " |
| @@ -2082,13 +2092,15 @@ static int ext3_create_journal(struct super_block * sb, | |||
| 2082 | return -EROFS; | 2092 | return -EROFS; |
| 2083 | } | 2093 | } |
| 2084 | 2094 | ||
| 2085 | if (!(journal = ext3_get_journal(sb, journal_inum))) | 2095 | journal = ext3_get_journal(sb, journal_inum); |
| 2096 | if (!journal) | ||
| 2086 | return -EINVAL; | 2097 | return -EINVAL; |
| 2087 | 2098 | ||
| 2088 | printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n", | 2099 | printk(KERN_INFO "EXT3-fs: creating new journal on inode %u\n", |
| 2089 | journal_inum); | 2100 | journal_inum); |
| 2090 | 2101 | ||
| 2091 | if (journal_create(journal)) { | 2102 | err = journal_create(journal); |
| 2103 | if (err) { | ||
| 2092 | printk(KERN_ERR "EXT3-fs: error creating journal.\n"); | 2104 | printk(KERN_ERR "EXT3-fs: error creating journal.\n"); |
| 2093 | journal_destroy(journal); | 2105 | journal_destroy(journal); |
| 2094 | return -EIO; | 2106 | return -EIO; |
| @@ -2139,12 +2151,14 @@ static void ext3_mark_recovery_complete(struct super_block * sb, | |||
| 2139 | 2151 | ||
| 2140 | journal_lock_updates(journal); | 2152 | journal_lock_updates(journal); |
| 2141 | journal_flush(journal); | 2153 | journal_flush(journal); |
| 2154 | lock_super(sb); | ||
| 2142 | if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) && | 2155 | if (EXT3_HAS_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER) && |
| 2143 | sb->s_flags & MS_RDONLY) { | 2156 | sb->s_flags & MS_RDONLY) { |
| 2144 | EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); | 2157 | EXT3_CLEAR_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER); |
| 2145 | sb->s_dirt = 0; | 2158 | sb->s_dirt = 0; |
| 2146 | ext3_commit_super(sb, es, 1); | 2159 | ext3_commit_super(sb, es, 1); |
| 2147 | } | 2160 | } |
| 2161 | unlock_super(sb); | ||
| 2148 | journal_unlock_updates(journal); | 2162 | journal_unlock_updates(journal); |
| 2149 | } | 2163 | } |
| 2150 | 2164 | ||
| @@ -2333,7 +2347,13 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) | |||
| 2333 | (sbi->s_mount_state & EXT3_VALID_FS)) | 2347 | (sbi->s_mount_state & EXT3_VALID_FS)) |
| 2334 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 2348 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 2335 | 2349 | ||
| 2350 | /* | ||
| 2351 | * We have to unlock super so that we can wait for | ||
| 2352 | * transactions. | ||
| 2353 | */ | ||
| 2354 | unlock_super(sb); | ||
| 2336 | ext3_mark_recovery_complete(sb, es); | 2355 | ext3_mark_recovery_complete(sb, es); |
| 2356 | lock_super(sb); | ||
| 2337 | } else { | 2357 | } else { |
| 2338 | __le32 ret; | 2358 | __le32 ret; |
| 2339 | if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb, | 2359 | if ((ret = EXT3_HAS_RO_COMPAT_FEATURE(sb, |
| @@ -2406,19 +2426,19 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2406 | struct super_block *sb = dentry->d_sb; | 2426 | struct super_block *sb = dentry->d_sb; |
| 2407 | struct ext3_sb_info *sbi = EXT3_SB(sb); | 2427 | struct ext3_sb_info *sbi = EXT3_SB(sb); |
| 2408 | struct ext3_super_block *es = sbi->s_es; | 2428 | struct ext3_super_block *es = sbi->s_es; |
| 2409 | ext3_fsblk_t overhead; | ||
| 2410 | int i; | ||
| 2411 | u64 fsid; | 2429 | u64 fsid; |
| 2412 | 2430 | ||
| 2413 | if (test_opt (sb, MINIX_DF)) | 2431 | if (test_opt(sb, MINIX_DF)) { |
| 2414 | overhead = 0; | 2432 | sbi->s_overhead_last = 0; |
| 2415 | else { | 2433 | } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { |
| 2416 | unsigned long ngroups; | 2434 | unsigned long ngroups = sbi->s_groups_count, i; |
| 2417 | ngroups = EXT3_SB(sb)->s_groups_count; | 2435 | ext3_fsblk_t overhead = 0; |
| 2418 | smp_rmb(); | 2436 | smp_rmb(); |
| 2419 | 2437 | ||
| 2420 | /* | 2438 | /* |
| 2421 | * Compute the overhead (FS structures) | 2439 | * Compute the overhead (FS structures). This is constant |
| 2440 | * for a given filesystem unless the number of block groups | ||
| 2441 | * changes so we cache the previous value until it does. | ||
| 2422 | */ | 2442 | */ |
| 2423 | 2443 | ||
| 2424 | /* | 2444 | /* |
| @@ -2442,18 +2462,23 @@ static int ext3_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2442 | * Every block group has an inode bitmap, a block | 2462 | * Every block group has an inode bitmap, a block |
| 2443 | * bitmap, and an inode table. | 2463 | * bitmap, and an inode table. |
| 2444 | */ | 2464 | */ |
| 2445 | overhead += (ngroups * (2 + EXT3_SB(sb)->s_itb_per_group)); | 2465 | overhead += ngroups * (2 + sbi->s_itb_per_group); |
| 2466 | sbi->s_overhead_last = overhead; | ||
| 2467 | smp_wmb(); | ||
| 2468 | sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); | ||
| 2446 | } | 2469 | } |
| 2447 | 2470 | ||
| 2448 | buf->f_type = EXT3_SUPER_MAGIC; | 2471 | buf->f_type = EXT3_SUPER_MAGIC; |
| 2449 | buf->f_bsize = sb->s_blocksize; | 2472 | buf->f_bsize = sb->s_blocksize; |
| 2450 | buf->f_blocks = le32_to_cpu(es->s_blocks_count) - overhead; | 2473 | buf->f_blocks = le32_to_cpu(es->s_blocks_count) - sbi->s_overhead_last; |
| 2451 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); | 2474 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); |
| 2475 | es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); | ||
| 2452 | buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); | 2476 | buf->f_bavail = buf->f_bfree - le32_to_cpu(es->s_r_blocks_count); |
| 2453 | if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) | 2477 | if (buf->f_bfree < le32_to_cpu(es->s_r_blocks_count)) |
| 2454 | buf->f_bavail = 0; | 2478 | buf->f_bavail = 0; |
| 2455 | buf->f_files = le32_to_cpu(es->s_inodes_count); | 2479 | buf->f_files = le32_to_cpu(es->s_inodes_count); |
| 2456 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); | 2480 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); |
| 2481 | es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); | ||
| 2457 | buf->f_namelen = EXT3_NAME_LEN; | 2482 | buf->f_namelen = EXT3_NAME_LEN; |
| 2458 | fsid = le64_to_cpup((void *)es->s_uuid) ^ | 2483 | fsid = le64_to_cpup((void *)es->s_uuid) ^ |
| 2459 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); | 2484 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); |
diff --git a/fs/ext4/balloc.c b/fs/ext4/balloc.c index 3b64bb16c727..9de54ae48dee 100644 --- a/fs/ext4/balloc.c +++ b/fs/ext4/balloc.c | |||
| @@ -1585,7 +1585,7 @@ allocated: | |||
| 1585 | ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no); | 1585 | ret_block = grp_alloc_blk + ext4_group_first_block_no(sb, group_no); |
| 1586 | 1586 | ||
| 1587 | if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || | 1587 | if (in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || |
| 1588 | in_range(ext4_block_bitmap(sb, gdp), ret_block, num) || | 1588 | in_range(ext4_inode_bitmap(sb, gdp), ret_block, num) || |
| 1589 | in_range(ret_block, ext4_inode_table(sb, gdp), | 1589 | in_range(ret_block, ext4_inode_table(sb, gdp), |
| 1590 | EXT4_SB(sb)->s_itb_per_group) || | 1590 | EXT4_SB(sb)->s_itb_per_group) || |
| 1591 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), | 1591 | in_range(ret_block + num - 1, ext4_inode_table(sb, gdp), |
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 2811e5720ad0..2de339dd7554 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c | |||
| @@ -1017,6 +1017,11 @@ static struct dentry *ext4_lookup(struct inode * dir, struct dentry *dentry, str | |||
| 1017 | 1017 | ||
| 1018 | if (!inode) | 1018 | if (!inode) |
| 1019 | return ERR_PTR(-EACCES); | 1019 | return ERR_PTR(-EACCES); |
| 1020 | |||
| 1021 | if (is_bad_inode(inode)) { | ||
| 1022 | iput(inode); | ||
| 1023 | return ERR_PTR(-ENOENT); | ||
| 1024 | } | ||
| 1020 | } | 1025 | } |
| 1021 | return d_splice_alias(inode, dentry); | 1026 | return d_splice_alias(inode, dentry); |
| 1022 | } | 1027 | } |
| @@ -1052,6 +1057,11 @@ struct dentry *ext4_get_parent(struct dentry *child) | |||
| 1052 | if (!inode) | 1057 | if (!inode) |
| 1053 | return ERR_PTR(-EACCES); | 1058 | return ERR_PTR(-EACCES); |
| 1054 | 1059 | ||
| 1060 | if (is_bad_inode(inode)) { | ||
| 1061 | iput(inode); | ||
| 1062 | return ERR_PTR(-ENOENT); | ||
| 1063 | } | ||
| 1064 | |||
| 1055 | parent = d_alloc_anon(inode); | 1065 | parent = d_alloc_anon(inode); |
| 1056 | if (!parent) { | 1066 | if (!parent) { |
| 1057 | iput(inode); | 1067 | iput(inode); |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 175b68c60968..d0d8c76c7edb 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
| @@ -510,6 +510,14 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
| 510 | 510 | ||
| 511 | static void ext4_destroy_inode(struct inode *inode) | 511 | static void ext4_destroy_inode(struct inode *inode) |
| 512 | { | 512 | { |
| 513 | if (!list_empty(&(EXT4_I(inode)->i_orphan))) { | ||
| 514 | printk("EXT4 Inode %p: orphan list check failed!\n", | ||
| 515 | EXT4_I(inode)); | ||
| 516 | print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 16, 4, | ||
| 517 | EXT4_I(inode), sizeof(struct ext4_inode_info), | ||
| 518 | true); | ||
| 519 | dump_stack(); | ||
| 520 | } | ||
| 513 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); | 521 | kmem_cache_free(ext4_inode_cachep, EXT4_I(inode)); |
| 514 | } | 522 | } |
| 515 | 523 | ||
| @@ -2150,6 +2158,7 @@ static int ext4_create_journal(struct super_block * sb, | |||
| 2150 | unsigned int journal_inum) | 2158 | unsigned int journal_inum) |
| 2151 | { | 2159 | { |
| 2152 | journal_t *journal; | 2160 | journal_t *journal; |
| 2161 | int err; | ||
| 2153 | 2162 | ||
| 2154 | if (sb->s_flags & MS_RDONLY) { | 2163 | if (sb->s_flags & MS_RDONLY) { |
| 2155 | printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to " | 2164 | printk(KERN_ERR "EXT4-fs: readonly filesystem when trying to " |
| @@ -2157,13 +2166,15 @@ static int ext4_create_journal(struct super_block * sb, | |||
| 2157 | return -EROFS; | 2166 | return -EROFS; |
| 2158 | } | 2167 | } |
| 2159 | 2168 | ||
| 2160 | if (!(journal = ext4_get_journal(sb, journal_inum))) | 2169 | journal = ext4_get_journal(sb, journal_inum); |
| 2170 | if (!journal) | ||
| 2161 | return -EINVAL; | 2171 | return -EINVAL; |
| 2162 | 2172 | ||
| 2163 | printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n", | 2173 | printk(KERN_INFO "EXT4-fs: creating new journal on inode %u\n", |
| 2164 | journal_inum); | 2174 | journal_inum); |
| 2165 | 2175 | ||
| 2166 | if (jbd2_journal_create(journal)) { | 2176 | err = jbd2_journal_create(journal); |
| 2177 | if (err) { | ||
| 2167 | printk(KERN_ERR "EXT4-fs: error creating journal.\n"); | 2178 | printk(KERN_ERR "EXT4-fs: error creating journal.\n"); |
| 2168 | jbd2_journal_destroy(journal); | 2179 | jbd2_journal_destroy(journal); |
| 2169 | return -EIO; | 2180 | return -EIO; |
| @@ -2214,12 +2225,14 @@ static void ext4_mark_recovery_complete(struct super_block * sb, | |||
| 2214 | 2225 | ||
| 2215 | jbd2_journal_lock_updates(journal); | 2226 | jbd2_journal_lock_updates(journal); |
| 2216 | jbd2_journal_flush(journal); | 2227 | jbd2_journal_flush(journal); |
| 2228 | lock_super(sb); | ||
| 2217 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && | 2229 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER) && |
| 2218 | sb->s_flags & MS_RDONLY) { | 2230 | sb->s_flags & MS_RDONLY) { |
| 2219 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); | 2231 | EXT4_CLEAR_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_RECOVER); |
| 2220 | sb->s_dirt = 0; | 2232 | sb->s_dirt = 0; |
| 2221 | ext4_commit_super(sb, es, 1); | 2233 | ext4_commit_super(sb, es, 1); |
| 2222 | } | 2234 | } |
| 2235 | unlock_super(sb); | ||
| 2223 | jbd2_journal_unlock_updates(journal); | 2236 | jbd2_journal_unlock_updates(journal); |
| 2224 | } | 2237 | } |
| 2225 | 2238 | ||
| @@ -2408,7 +2421,13 @@ static int ext4_remount (struct super_block * sb, int * flags, char * data) | |||
| 2408 | (sbi->s_mount_state & EXT4_VALID_FS)) | 2421 | (sbi->s_mount_state & EXT4_VALID_FS)) |
| 2409 | es->s_state = cpu_to_le16(sbi->s_mount_state); | 2422 | es->s_state = cpu_to_le16(sbi->s_mount_state); |
| 2410 | 2423 | ||
| 2424 | /* | ||
| 2425 | * We have to unlock super so that we can wait for | ||
| 2426 | * transactions. | ||
| 2427 | */ | ||
| 2428 | unlock_super(sb); | ||
| 2411 | ext4_mark_recovery_complete(sb, es); | 2429 | ext4_mark_recovery_complete(sb, es); |
| 2430 | lock_super(sb); | ||
| 2412 | } else { | 2431 | } else { |
| 2413 | __le32 ret; | 2432 | __le32 ret; |
| 2414 | if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb, | 2433 | if ((ret = EXT4_HAS_RO_COMPAT_FEATURE(sb, |
| @@ -2481,19 +2500,19 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2481 | struct super_block *sb = dentry->d_sb; | 2500 | struct super_block *sb = dentry->d_sb; |
| 2482 | struct ext4_sb_info *sbi = EXT4_SB(sb); | 2501 | struct ext4_sb_info *sbi = EXT4_SB(sb); |
| 2483 | struct ext4_super_block *es = sbi->s_es; | 2502 | struct ext4_super_block *es = sbi->s_es; |
| 2484 | ext4_fsblk_t overhead; | ||
| 2485 | int i; | ||
| 2486 | u64 fsid; | 2503 | u64 fsid; |
| 2487 | 2504 | ||
| 2488 | if (test_opt (sb, MINIX_DF)) | 2505 | if (test_opt(sb, MINIX_DF)) { |
| 2489 | overhead = 0; | 2506 | sbi->s_overhead_last = 0; |
| 2490 | else { | 2507 | } else if (sbi->s_blocks_last != le32_to_cpu(es->s_blocks_count)) { |
| 2491 | unsigned long ngroups; | 2508 | unsigned long ngroups = sbi->s_groups_count, i; |
| 2492 | ngroups = EXT4_SB(sb)->s_groups_count; | 2509 | ext4_fsblk_t overhead = 0; |
| 2493 | smp_rmb(); | 2510 | smp_rmb(); |
| 2494 | 2511 | ||
| 2495 | /* | 2512 | /* |
| 2496 | * Compute the overhead (FS structures) | 2513 | * Compute the overhead (FS structures). This is constant |
| 2514 | * for a given filesystem unless the number of block groups | ||
| 2515 | * changes so we cache the previous value until it does. | ||
| 2497 | */ | 2516 | */ |
| 2498 | 2517 | ||
| 2499 | /* | 2518 | /* |
| @@ -2517,18 +2536,23 @@ static int ext4_statfs (struct dentry * dentry, struct kstatfs * buf) | |||
| 2517 | * Every block group has an inode bitmap, a block | 2536 | * Every block group has an inode bitmap, a block |
| 2518 | * bitmap, and an inode table. | 2537 | * bitmap, and an inode table. |
| 2519 | */ | 2538 | */ |
| 2520 | overhead += (ngroups * (2 + EXT4_SB(sb)->s_itb_per_group)); | 2539 | overhead += ngroups * (2 + sbi->s_itb_per_group); |
| 2540 | sbi->s_overhead_last = overhead; | ||
| 2541 | smp_wmb(); | ||
| 2542 | sbi->s_blocks_last = le32_to_cpu(es->s_blocks_count); | ||
| 2521 | } | 2543 | } |
| 2522 | 2544 | ||
| 2523 | buf->f_type = EXT4_SUPER_MAGIC; | 2545 | buf->f_type = EXT4_SUPER_MAGIC; |
| 2524 | buf->f_bsize = sb->s_blocksize; | 2546 | buf->f_bsize = sb->s_blocksize; |
| 2525 | buf->f_blocks = ext4_blocks_count(es) - overhead; | 2547 | buf->f_blocks = ext4_blocks_count(es) - sbi->s_overhead_last; |
| 2526 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); | 2548 | buf->f_bfree = percpu_counter_sum(&sbi->s_freeblocks_counter); |
| 2549 | es->s_free_blocks_count = cpu_to_le32(buf->f_bfree); | ||
| 2527 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); | 2550 | buf->f_bavail = buf->f_bfree - ext4_r_blocks_count(es); |
| 2528 | if (buf->f_bfree < ext4_r_blocks_count(es)) | 2551 | if (buf->f_bfree < ext4_r_blocks_count(es)) |
| 2529 | buf->f_bavail = 0; | 2552 | buf->f_bavail = 0; |
| 2530 | buf->f_files = le32_to_cpu(es->s_inodes_count); | 2553 | buf->f_files = le32_to_cpu(es->s_inodes_count); |
| 2531 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); | 2554 | buf->f_ffree = percpu_counter_sum(&sbi->s_freeinodes_counter); |
| 2555 | es->s_free_inodes_count = cpu_to_le32(buf->f_ffree); | ||
| 2532 | buf->f_namelen = EXT4_NAME_LEN; | 2556 | buf->f_namelen = EXT4_NAME_LEN; |
| 2533 | fsid = le64_to_cpup((void *)es->s_uuid) ^ | 2557 | fsid = le64_to_cpup((void *)es->s_uuid) ^ |
| 2534 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); | 2558 | le64_to_cpup((void *)es->s_uuid + sizeof(u64)); |
diff --git a/fs/fat/dir.c b/fs/fat/dir.c index ccf161dffb63..72cbcd61bd95 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c | |||
| @@ -313,7 +313,7 @@ int fat_search_long(struct inode *inode, const unsigned char *name, | |||
| 313 | wchar_t bufuname[14]; | 313 | wchar_t bufuname[14]; |
| 314 | unsigned char xlate_len, nr_slots; | 314 | unsigned char xlate_len, nr_slots; |
| 315 | wchar_t *unicode = NULL; | 315 | wchar_t *unicode = NULL; |
| 316 | unsigned char work[8], bufname[260]; /* 256 + 4 */ | 316 | unsigned char work[MSDOS_NAME], bufname[260]; /* 256 + 4 */ |
| 317 | int uni_xlate = sbi->options.unicode_xlate; | 317 | int uni_xlate = sbi->options.unicode_xlate; |
| 318 | int utf8 = sbi->options.utf8; | 318 | int utf8 = sbi->options.utf8; |
| 319 | int anycase = (sbi->options.name_check != 's'); | 319 | int anycase = (sbi->options.name_check != 's'); |
| @@ -351,7 +351,8 @@ parse_record: | |||
| 351 | if (work[0] == 0x05) | 351 | if (work[0] == 0x05) |
| 352 | work[0] = 0xE5; | 352 | work[0] = 0xE5; |
| 353 | for (i = 0, j = 0, last_u = 0; i < 8;) { | 353 | for (i = 0, j = 0, last_u = 0; i < 8;) { |
| 354 | if (!work[i]) break; | 354 | if (!work[i]) |
| 355 | break; | ||
| 355 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, | 356 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, |
| 356 | &bufuname[j++], opt_shortname, | 357 | &bufuname[j++], opt_shortname, |
| 357 | de->lcase & CASE_LOWER_BASE); | 358 | de->lcase & CASE_LOWER_BASE); |
| @@ -365,13 +366,15 @@ parse_record: | |||
| 365 | } | 366 | } |
| 366 | j = last_u; | 367 | j = last_u; |
| 367 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); | 368 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); |
| 368 | for (i = 0; i < 3;) { | 369 | for (i = 8; i < MSDOS_NAME;) { |
| 369 | if (!de->ext[i]) break; | 370 | if (!work[i]) |
| 370 | chl = fat_shortname2uni(nls_disk, &de->ext[i], 3 - i, | 371 | break; |
| 372 | chl = fat_shortname2uni(nls_disk, &work[i], | ||
| 373 | MSDOS_NAME - i, | ||
| 371 | &bufuname[j++], opt_shortname, | 374 | &bufuname[j++], opt_shortname, |
| 372 | de->lcase & CASE_LOWER_EXT); | 375 | de->lcase & CASE_LOWER_EXT); |
| 373 | if (chl <= 1) { | 376 | if (chl <= 1) { |
| 374 | if (de->ext[i] != ' ') | 377 | if (work[i] != ' ') |
| 375 | last_u = j; | 378 | last_u = j; |
| 376 | } else { | 379 | } else { |
| 377 | last_u = j; | 380 | last_u = j; |
| @@ -445,7 +448,7 @@ static int __fat_readdir(struct inode *inode, struct file *filp, void *dirent, | |||
| 445 | int fill_len; | 448 | int fill_len; |
| 446 | wchar_t bufuname[14]; | 449 | wchar_t bufuname[14]; |
| 447 | wchar_t *unicode = NULL; | 450 | wchar_t *unicode = NULL; |
| 448 | unsigned char c, work[8], bufname[56], *ptname = bufname; | 451 | unsigned char c, work[MSDOS_NAME], bufname[56], *ptname = bufname; |
| 449 | unsigned long lpos, dummy, *furrfu = &lpos; | 452 | unsigned long lpos, dummy, *furrfu = &lpos; |
| 450 | int uni_xlate = sbi->options.unicode_xlate; | 453 | int uni_xlate = sbi->options.unicode_xlate; |
| 451 | int isvfat = sbi->options.isvfat; | 454 | int isvfat = sbi->options.isvfat; |
| @@ -527,7 +530,8 @@ parse_record: | |||
| 527 | if (work[0] == 0x05) | 530 | if (work[0] == 0x05) |
| 528 | work[0] = 0xE5; | 531 | work[0] = 0xE5; |
| 529 | for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) { | 532 | for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) { |
| 530 | if (!(c = work[i])) break; | 533 | if (!(c = work[i])) |
| 534 | break; | ||
| 531 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, | 535 | chl = fat_shortname2uni(nls_disk, &work[i], 8 - i, |
| 532 | &bufuname[j++], opt_shortname, | 536 | &bufuname[j++], opt_shortname, |
| 533 | de->lcase & CASE_LOWER_BASE); | 537 | de->lcase & CASE_LOWER_BASE); |
| @@ -549,9 +553,10 @@ parse_record: | |||
| 549 | j = last_u; | 553 | j = last_u; |
| 550 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); | 554 | fat_short2uni(nls_disk, ".", 1, &bufuname[j++]); |
| 551 | ptname[i++] = '.'; | 555 | ptname[i++] = '.'; |
| 552 | for (i2 = 0; i2 < 3;) { | 556 | for (i2 = 8; i2 < MSDOS_NAME;) { |
| 553 | if (!(c = de->ext[i2])) break; | 557 | if (!(c = work[i2])) |
| 554 | chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2, | 558 | break; |
| 559 | chl = fat_shortname2uni(nls_disk, &work[i2], MSDOS_NAME - i2, | ||
| 555 | &bufuname[j++], opt_shortname, | 560 | &bufuname[j++], opt_shortname, |
| 556 | de->lcase & CASE_LOWER_EXT); | 561 | de->lcase & CASE_LOWER_EXT); |
| 557 | if (chl <= 1) { | 562 | if (chl <= 1) { |
| @@ -563,8 +568,8 @@ parse_record: | |||
| 563 | } | 568 | } |
| 564 | } else { | 569 | } else { |
| 565 | last_u = j; | 570 | last_u = j; |
| 566 | for (chi = 0; chi < chl && i2 < 3; chi++) { | 571 | for (chi = 0; chi < chl && i2 < MSDOS_NAME; chi++) { |
| 567 | ptname[i++] = de->ext[i2++]; | 572 | ptname[i++] = work[i2++]; |
| 568 | last = i; | 573 | last = i; |
| 569 | } | 574 | } |
| 570 | } | 575 | } |
diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index ab171ea8e869..2c1b73fb82ae 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c | |||
| @@ -17,6 +17,8 @@ struct fatent_operations { | |||
| 17 | int (*ent_next)(struct fat_entry *); | 17 | int (*ent_next)(struct fat_entry *); |
| 18 | }; | 18 | }; |
| 19 | 19 | ||
| 20 | static DEFINE_SPINLOCK(fat12_entry_lock); | ||
| 21 | |||
| 20 | static void fat12_ent_blocknr(struct super_block *sb, int entry, | 22 | static void fat12_ent_blocknr(struct super_block *sb, int entry, |
| 21 | int *offset, sector_t *blocknr) | 23 | int *offset, sector_t *blocknr) |
| 22 | { | 24 | { |
| @@ -116,10 +118,13 @@ static int fat12_ent_get(struct fat_entry *fatent) | |||
| 116 | u8 **ent12_p = fatent->u.ent12_p; | 118 | u8 **ent12_p = fatent->u.ent12_p; |
| 117 | int next; | 119 | int next; |
| 118 | 120 | ||
| 121 | spin_lock(&fat12_entry_lock); | ||
| 119 | if (fatent->entry & 1) | 122 | if (fatent->entry & 1) |
| 120 | next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4); | 123 | next = (*ent12_p[0] >> 4) | (*ent12_p[1] << 4); |
| 121 | else | 124 | else |
| 122 | next = (*ent12_p[1] << 8) | *ent12_p[0]; | 125 | next = (*ent12_p[1] << 8) | *ent12_p[0]; |
| 126 | spin_unlock(&fat12_entry_lock); | ||
| 127 | |||
| 123 | next &= 0x0fff; | 128 | next &= 0x0fff; |
| 124 | if (next >= BAD_FAT12) | 129 | if (next >= BAD_FAT12) |
| 125 | next = FAT_ENT_EOF; | 130 | next = FAT_ENT_EOF; |
| @@ -151,6 +156,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new) | |||
| 151 | if (new == FAT_ENT_EOF) | 156 | if (new == FAT_ENT_EOF) |
| 152 | new = EOF_FAT12; | 157 | new = EOF_FAT12; |
| 153 | 158 | ||
| 159 | spin_lock(&fat12_entry_lock); | ||
| 154 | if (fatent->entry & 1) { | 160 | if (fatent->entry & 1) { |
| 155 | *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f); | 161 | *ent12_p[0] = (new << 4) | (*ent12_p[0] & 0x0f); |
| 156 | *ent12_p[1] = new >> 4; | 162 | *ent12_p[1] = new >> 4; |
| @@ -158,6 +164,7 @@ static void fat12_ent_put(struct fat_entry *fatent, int new) | |||
| 158 | *ent12_p[0] = new & 0xff; | 164 | *ent12_p[0] = new & 0xff; |
| 159 | *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8); | 165 | *ent12_p[1] = (*ent12_p[1] & 0xf0) | (new >> 8); |
| 160 | } | 166 | } |
| 167 | spin_unlock(&fat12_entry_lock); | ||
| 161 | 168 | ||
| 162 | mark_buffer_dirty(fatent->bhs[0]); | 169 | mark_buffer_dirty(fatent->bhs[0]); |
| 163 | if (fatent->nr_bhs == 2) | 170 | if (fatent->nr_bhs == 2) |
diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 479722d89667..cfaf5877d98b 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c | |||
| @@ -354,8 +354,7 @@ static int fat_fill_inode(struct inode *inode, struct msdos_dir_entry *de) | |||
| 354 | } else { /* not a directory */ | 354 | } else { /* not a directory */ |
| 355 | inode->i_generation |= 1; | 355 | inode->i_generation |= 1; |
| 356 | inode->i_mode = MSDOS_MKMODE(de->attr, | 356 | inode->i_mode = MSDOS_MKMODE(de->attr, |
| 357 | ((sbi->options.showexec && | 357 | ((sbi->options.showexec && !is_exec(de->name + 8)) |
| 358 | !is_exec(de->ext)) | ||
| 359 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) | 358 | ? S_IRUGO|S_IWUGO : S_IRWXUGO) |
| 360 | & ~sbi->options.fs_fmask) | S_IFREG; | 359 | & ~sbi->options.fs_fmask) | S_IFREG; |
| 361 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); | 360 | MSDOS_I(inode)->i_start = le16_to_cpu(de->start); |
diff --git a/fs/freevxfs/vxfs_dir.h b/fs/freevxfs/vxfs_dir.h index 8a4dfef1ddad..3c96d6e63978 100644 --- a/fs/freevxfs/vxfs_dir.h +++ b/fs/freevxfs/vxfs_dir.h | |||
| @@ -80,7 +80,7 @@ struct vxfs_direct { | |||
| 80 | * a d_name with size len. | 80 | * a d_name with size len. |
| 81 | */ | 81 | */ |
| 82 | #define VXFS_DIRPAD 4 | 82 | #define VXFS_DIRPAD 4 |
| 83 | #define VXFS_NAMEMIN ((int)((struct vxfs_direct *)0)->d_name) | 83 | #define VXFS_NAMEMIN offsetof(struct vxfs_direct, d_name) |
| 84 | #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1)) | 84 | #define VXFS_DIRROUND(len) ((VXFS_DIRPAD + (len) - 1) & ~(VXFS_DIRPAD -1)) |
| 85 | #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len))) | 85 | #define VXFS_DIRLEN(len) (VXFS_DIRROUND(VXFS_NAMEMIN + (len))) |
| 86 | 86 | ||
diff --git a/fs/gfs2/eaops.c b/fs/gfs2/eaops.c index c1f44009853f..1ab3e9d73886 100644 --- a/fs/gfs2/eaops.c +++ b/fs/gfs2/eaops.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/spinlock.h> | 11 | #include <linux/spinlock.h> |
| 12 | #include <linux/completion.h> | 12 | #include <linux/completion.h> |
| 13 | #include <linux/buffer_head.h> | 13 | #include <linux/buffer_head.h> |
| 14 | #include <linux/capability.h> | ||
| 14 | #include <linux/xattr.h> | 15 | #include <linux/xattr.h> |
| 15 | #include <linux/gfs2_ondisk.h> | 16 | #include <linux/gfs2_ondisk.h> |
| 16 | #include <linux/lm_interface.h> | 17 | #include <linux/lm_interface.h> |
diff --git a/fs/hfsplus/btree.c b/fs/hfsplus/btree.c index 90ebab753d30..050d29c0a5b5 100644 --- a/fs/hfsplus/btree.c +++ b/fs/hfsplus/btree.c | |||
| @@ -62,8 +62,10 @@ struct hfs_btree *hfs_btree_open(struct super_block *sb, u32 id) | |||
| 62 | if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && | 62 | if ((HFSPLUS_SB(sb).flags & HFSPLUS_SB_HFSX) && |
| 63 | (head->key_type == HFSPLUS_KEY_BINARY)) | 63 | (head->key_type == HFSPLUS_KEY_BINARY)) |
| 64 | tree->keycmp = hfsplus_cat_bin_cmp_key; | 64 | tree->keycmp = hfsplus_cat_bin_cmp_key; |
| 65 | else | 65 | else { |
| 66 | tree->keycmp = hfsplus_cat_case_cmp_key; | 66 | tree->keycmp = hfsplus_cat_case_cmp_key; |
| 67 | HFSPLUS_SB(sb).flags |= HFSPLUS_SB_CASEFOLD; | ||
| 68 | } | ||
| 67 | } else { | 69 | } else { |
| 68 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); | 70 | printk(KERN_ERR "hfs: unknown B*Tree requested\n"); |
| 69 | goto fail_page; | 71 | goto fail_page; |
diff --git a/fs/hfsplus/dir.c b/fs/hfsplus/dir.c index 80b5682a2273..1955ee61251c 100644 --- a/fs/hfsplus/dir.c +++ b/fs/hfsplus/dir.c | |||
| @@ -36,6 +36,8 @@ static struct dentry *hfsplus_lookup(struct inode *dir, struct dentry *dentry, | |||
| 36 | u16 type; | 36 | u16 type; |
| 37 | 37 | ||
| 38 | sb = dir->i_sb; | 38 | sb = dir->i_sb; |
| 39 | |||
| 40 | dentry->d_op = &hfsplus_dentry_operations; | ||
| 39 | dentry->d_fsdata = NULL; | 41 | dentry->d_fsdata = NULL; |
| 40 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); | 42 | hfs_find_init(HFSPLUS_SB(sb).cat_tree, &fd); |
| 41 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); | 43 | hfsplus_cat_build_key(sb, fd.search_key, dir->i_ino, &dentry->d_name); |
diff --git a/fs/hfsplus/hfsplus_fs.h b/fs/hfsplus/hfsplus_fs.h index 3915635b4470..d9f5eda6d039 100644 --- a/fs/hfsplus/hfsplus_fs.h +++ b/fs/hfsplus/hfsplus_fs.h | |||
| @@ -150,6 +150,7 @@ struct hfsplus_sb_info { | |||
| 150 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 | 150 | #define HFSPLUS_SB_NODECOMPOSE 0x0002 |
| 151 | #define HFSPLUS_SB_FORCE 0x0004 | 151 | #define HFSPLUS_SB_FORCE 0x0004 |
| 152 | #define HFSPLUS_SB_HFSX 0x0008 | 152 | #define HFSPLUS_SB_HFSX 0x0008 |
| 153 | #define HFSPLUS_SB_CASEFOLD 0x0010 | ||
| 153 | 154 | ||
| 154 | 155 | ||
| 155 | struct hfsplus_inode_info { | 156 | struct hfsplus_inode_info { |
| @@ -321,6 +322,7 @@ void hfsplus_file_truncate(struct inode *); | |||
| 321 | /* inode.c */ | 322 | /* inode.c */ |
| 322 | extern const struct address_space_operations hfsplus_aops; | 323 | extern const struct address_space_operations hfsplus_aops; |
| 323 | extern const struct address_space_operations hfsplus_btree_aops; | 324 | extern const struct address_space_operations hfsplus_btree_aops; |
| 325 | extern struct dentry_operations hfsplus_dentry_operations; | ||
| 324 | 326 | ||
| 325 | void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); | 327 | void hfsplus_inode_read_fork(struct inode *, struct hfsplus_fork_raw *); |
| 326 | void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); | 328 | void hfsplus_inode_write_fork(struct inode *, struct hfsplus_fork_raw *); |
| @@ -353,6 +355,8 @@ int hfsplus_strcasecmp(const struct hfsplus_unistr *, const struct hfsplus_unist | |||
| 353 | int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); | 355 | int hfsplus_strcmp(const struct hfsplus_unistr *, const struct hfsplus_unistr *); |
| 354 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); | 356 | int hfsplus_uni2asc(struct super_block *, const struct hfsplus_unistr *, char *, int *); |
| 355 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); | 357 | int hfsplus_asc2uni(struct super_block *, struct hfsplus_unistr *, const char *, int); |
| 358 | int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str); | ||
| 359 | int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2); | ||
| 356 | 360 | ||
| 357 | /* wrapper.c */ | 361 | /* wrapper.c */ |
| 358 | int hfsplus_read_wrapper(struct super_block *); | 362 | int hfsplus_read_wrapper(struct super_block *); |
diff --git a/fs/hfsplus/inode.c b/fs/hfsplus/inode.c index 409ce5429c91..6f7c662174db 100644 --- a/fs/hfsplus/inode.c +++ b/fs/hfsplus/inode.c | |||
| @@ -131,6 +131,11 @@ const struct address_space_operations hfsplus_aops = { | |||
| 131 | .writepages = hfsplus_writepages, | 131 | .writepages = hfsplus_writepages, |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | struct dentry_operations hfsplus_dentry_operations = { | ||
| 135 | .d_hash = hfsplus_hash_dentry, | ||
| 136 | .d_compare = hfsplus_compare_dentry, | ||
| 137 | }; | ||
| 138 | |||
| 134 | static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, | 139 | static struct dentry *hfsplus_file_lookup(struct inode *dir, struct dentry *dentry, |
| 135 | struct nameidata *nd) | 140 | struct nameidata *nd) |
| 136 | { | 141 | { |
diff --git a/fs/hfsplus/super.c b/fs/hfsplus/super.c index ebd1b380cbbc..6d87a2a9534d 100644 --- a/fs/hfsplus/super.c +++ b/fs/hfsplus/super.c | |||
| @@ -283,11 +283,10 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 283 | struct nls_table *nls = NULL; | 283 | struct nls_table *nls = NULL; |
| 284 | int err = -EINVAL; | 284 | int err = -EINVAL; |
| 285 | 285 | ||
| 286 | sbi = kmalloc(sizeof(struct hfsplus_sb_info), GFP_KERNEL); | 286 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
| 287 | if (!sbi) | 287 | if (!sbi) |
| 288 | return -ENOMEM; | 288 | return -ENOMEM; |
| 289 | 289 | ||
| 290 | memset(sbi, 0, sizeof(HFSPLUS_SB(sb))); | ||
| 291 | sb->s_fs_info = sbi; | 290 | sb->s_fs_info = sbi; |
| 292 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); | 291 | INIT_HLIST_HEAD(&sbi->rsrc_inodes); |
| 293 | hfsplus_fill_defaults(sbi); | 292 | hfsplus_fill_defaults(sbi); |
| @@ -381,6 +380,7 @@ static int hfsplus_fill_super(struct super_block *sb, void *data, int silent) | |||
| 381 | iput(root); | 380 | iput(root); |
| 382 | goto cleanup; | 381 | goto cleanup; |
| 383 | } | 382 | } |
| 383 | sb->s_root->d_op = &hfsplus_dentry_operations; | ||
| 384 | 384 | ||
| 385 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; | 385 | str.len = sizeof(HFSP_HIDDENDIR_NAME) - 1; |
| 386 | str.name = HFSP_HIDDENDIR_NAME; | 386 | str.name = HFSP_HIDDENDIR_NAME; |
diff --git a/fs/hfsplus/unicode.c b/fs/hfsplus/unicode.c index 689c8bd721fb..9e10f9444b64 100644 --- a/fs/hfsplus/unicode.c +++ b/fs/hfsplus/unicode.c | |||
| @@ -239,61 +239,201 @@ out: | |||
| 239 | return res; | 239 | return res; |
| 240 | } | 240 | } |
| 241 | 241 | ||
| 242 | int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, const char *astr, int len) | 242 | /* |
| 243 | * Convert one or more ASCII characters into a single unicode character. | ||
| 244 | * Returns the number of ASCII characters corresponding to the unicode char. | ||
| 245 | */ | ||
| 246 | static inline int asc2unichar(struct super_block *sb, const char *astr, int len, | ||
| 247 | wchar_t *uc) | ||
| 243 | { | 248 | { |
| 244 | struct nls_table *nls = HFSPLUS_SB(sb).nls; | 249 | int size = HFSPLUS_SB(sb).nls->char2uni(astr, len, uc); |
| 245 | int size, off, decompose; | 250 | if (size <= 0) { |
| 251 | *uc = '?'; | ||
| 252 | size = 1; | ||
| 253 | } | ||
| 254 | switch (*uc) { | ||
| 255 | case 0x2400: | ||
| 256 | *uc = 0; | ||
| 257 | break; | ||
| 258 | case ':': | ||
| 259 | *uc = '/'; | ||
| 260 | break; | ||
| 261 | } | ||
| 262 | return size; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* Decomposes a single unicode character. */ | ||
| 266 | static inline u16 *decompose_unichar(wchar_t uc, int *size) | ||
| 267 | { | ||
| 268 | int off; | ||
| 269 | |||
| 270 | off = hfsplus_decompose_table[(uc >> 12) & 0xf]; | ||
| 271 | if (off == 0 || off == 0xffff) | ||
| 272 | return NULL; | ||
| 273 | |||
| 274 | off = hfsplus_decompose_table[off + ((uc >> 8) & 0xf)]; | ||
| 275 | if (!off) | ||
| 276 | return NULL; | ||
| 277 | |||
| 278 | off = hfsplus_decompose_table[off + ((uc >> 4) & 0xf)]; | ||
| 279 | if (!off) | ||
| 280 | return NULL; | ||
| 281 | |||
| 282 | off = hfsplus_decompose_table[off + (uc & 0xf)]; | ||
| 283 | *size = off & 3; | ||
| 284 | if (*size == 0) | ||
| 285 | return NULL; | ||
| 286 | return hfsplus_decompose_table + (off / 4); | ||
| 287 | } | ||
| 288 | |||
| 289 | int hfsplus_asc2uni(struct super_block *sb, struct hfsplus_unistr *ustr, | ||
| 290 | const char *astr, int len) | ||
| 291 | { | ||
| 292 | int size, dsize, decompose; | ||
| 293 | u16 *dstr, outlen = 0; | ||
| 246 | wchar_t c; | 294 | wchar_t c; |
| 247 | u16 outlen = 0; | ||
| 248 | 295 | ||
| 249 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | 296 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); |
| 250 | |||
| 251 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { | 297 | while (outlen < HFSPLUS_MAX_STRLEN && len > 0) { |
| 252 | size = nls->char2uni(astr, len, &c); | 298 | size = asc2unichar(sb, astr, len, &c); |
| 253 | if (size <= 0) { | 299 | |
| 254 | c = '?'; | 300 | if (decompose && (dstr = decompose_unichar(c, &dsize))) { |
| 255 | size = 1; | 301 | if (outlen + dsize > HFSPLUS_MAX_STRLEN) |
| 256 | } | ||
| 257 | astr += size; | ||
| 258 | len -= size; | ||
| 259 | switch (c) { | ||
| 260 | case 0x2400: | ||
| 261 | c = 0; | ||
| 262 | break; | ||
| 263 | case ':': | ||
| 264 | c = '/'; | ||
| 265 | break; | ||
| 266 | } | ||
| 267 | if (c >= 0xc0 && decompose) { | ||
| 268 | off = hfsplus_decompose_table[(c >> 12) & 0xf]; | ||
| 269 | if (!off) | ||
| 270 | goto done; | ||
| 271 | if (off == 0xffff) { | ||
| 272 | goto done; | ||
| 273 | } | ||
| 274 | off = hfsplus_decompose_table[off + ((c >> 8) & 0xf)]; | ||
| 275 | if (!off) | ||
| 276 | goto done; | ||
| 277 | off = hfsplus_decompose_table[off + ((c >> 4) & 0xf)]; | ||
| 278 | if (!off) | ||
| 279 | goto done; | ||
| 280 | off = hfsplus_decompose_table[off + (c & 0xf)]; | ||
| 281 | size = off & 3; | ||
| 282 | if (!size) | ||
| 283 | goto done; | ||
| 284 | off /= 4; | ||
| 285 | if (outlen + size > HFSPLUS_MAX_STRLEN) | ||
| 286 | break; | 302 | break; |
| 287 | do { | 303 | do { |
| 288 | ustr->unicode[outlen++] = cpu_to_be16(hfsplus_decompose_table[off++]); | 304 | ustr->unicode[outlen++] = cpu_to_be16(*dstr++); |
| 289 | } while (--size > 0); | 305 | } while (--dsize > 0); |
| 290 | continue; | 306 | } else |
| 291 | } | 307 | ustr->unicode[outlen++] = cpu_to_be16(c); |
| 292 | done: | 308 | |
| 293 | ustr->unicode[outlen++] = cpu_to_be16(c); | 309 | astr += size; |
| 310 | len -= size; | ||
| 294 | } | 311 | } |
| 295 | ustr->length = cpu_to_be16(outlen); | 312 | ustr->length = cpu_to_be16(outlen); |
| 296 | if (len > 0) | 313 | if (len > 0) |
| 297 | return -ENAMETOOLONG; | 314 | return -ENAMETOOLONG; |
| 298 | return 0; | 315 | return 0; |
| 299 | } | 316 | } |
| 317 | |||
| 318 | /* | ||
| 319 | * Hash a string to an integer as appropriate for the HFS+ filesystem. | ||
| 320 | * Composed unicode characters are decomposed and case-folding is performed | ||
| 321 | * if the appropriate bits are (un)set on the superblock. | ||
| 322 | */ | ||
| 323 | int hfsplus_hash_dentry(struct dentry *dentry, struct qstr *str) | ||
| 324 | { | ||
| 325 | struct super_block *sb = dentry->d_sb; | ||
| 326 | const char *astr; | ||
| 327 | const u16 *dstr; | ||
| 328 | int casefold, decompose, size, dsize, len; | ||
| 329 | unsigned long hash; | ||
| 330 | wchar_t c; | ||
| 331 | u16 c2; | ||
| 332 | |||
| 333 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | ||
| 334 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | ||
| 335 | hash = init_name_hash(); | ||
| 336 | astr = str->name; | ||
| 337 | len = str->len; | ||
| 338 | while (len > 0) { | ||
| 339 | size = asc2unichar(sb, astr, len, &c); | ||
| 340 | astr += size; | ||
| 341 | len -= size; | ||
| 342 | |||
| 343 | if (decompose && (dstr = decompose_unichar(c, &dsize))) { | ||
| 344 | do { | ||
| 345 | c2 = *dstr++; | ||
| 346 | if (!casefold || (c2 = case_fold(c2))) | ||
| 347 | hash = partial_name_hash(c2, hash); | ||
| 348 | } while (--dsize > 0); | ||
| 349 | } else { | ||
| 350 | c2 = c; | ||
| 351 | if (!casefold || (c2 = case_fold(c2))) | ||
| 352 | hash = partial_name_hash(c2, hash); | ||
| 353 | } | ||
| 354 | } | ||
| 355 | str->hash = end_name_hash(hash); | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Compare strings with HFS+ filename ordering. | ||
| 362 | * Composed unicode characters are decomposed and case-folding is performed | ||
| 363 | * if the appropriate bits are (un)set on the superblock. | ||
| 364 | */ | ||
| 365 | int hfsplus_compare_dentry(struct dentry *dentry, struct qstr *s1, struct qstr *s2) | ||
| 366 | { | ||
| 367 | struct super_block *sb = dentry->d_sb; | ||
| 368 | int casefold, decompose, size; | ||
| 369 | int dsize1, dsize2, len1, len2; | ||
| 370 | const u16 *dstr1, *dstr2; | ||
| 371 | const char *astr1, *astr2; | ||
| 372 | u16 c1, c2; | ||
| 373 | wchar_t c; | ||
| 374 | |||
| 375 | casefold = (HFSPLUS_SB(sb).flags & HFSPLUS_SB_CASEFOLD); | ||
| 376 | decompose = !(HFSPLUS_SB(sb).flags & HFSPLUS_SB_NODECOMPOSE); | ||
| 377 | astr1 = s1->name; | ||
| 378 | len1 = s1->len; | ||
| 379 | astr2 = s2->name; | ||
| 380 | len2 = s2->len; | ||
| 381 | dsize1 = dsize2 = 0; | ||
| 382 | dstr1 = dstr2 = NULL; | ||
| 383 | |||
| 384 | while (len1 > 0 && len2 > 0) { | ||
| 385 | if (!dsize1) { | ||
| 386 | size = asc2unichar(sb, astr1, len1, &c); | ||
| 387 | astr1 += size; | ||
| 388 | len1 -= size; | ||
| 389 | |||
| 390 | if (!decompose || !(dstr1 = decompose_unichar(c, &dsize1))) { | ||
| 391 | c1 = c; | ||
| 392 | dstr1 = &c1; | ||
| 393 | dsize1 = 1; | ||
| 394 | } | ||
| 395 | } | ||
| 396 | |||
| 397 | if (!dsize2) { | ||
| 398 | size = asc2unichar(sb, astr2, len2, &c); | ||
| 399 | astr2 += size; | ||
| 400 | len2 -= size; | ||
| 401 | |||
| 402 | if (!decompose || !(dstr2 = decompose_unichar(c, &dsize2))) { | ||
| 403 | c2 = c; | ||
| 404 | dstr2 = &c2; | ||
| 405 | dsize2 = 1; | ||
| 406 | } | ||
| 407 | } | ||
| 408 | |||
| 409 | c1 = *dstr1; | ||
| 410 | c2 = *dstr2; | ||
| 411 | if (casefold) { | ||
| 412 | if (!(c1 = case_fold(c1))) { | ||
| 413 | dstr1++; | ||
| 414 | dsize1--; | ||
| 415 | continue; | ||
| 416 | } | ||
| 417 | if (!(c2 = case_fold(c2))) { | ||
| 418 | dstr2++; | ||
| 419 | dsize2--; | ||
| 420 | continue; | ||
| 421 | } | ||
| 422 | } | ||
| 423 | if (c1 < c2) | ||
| 424 | return -1; | ||
| 425 | else if (c1 > c2) | ||
| 426 | return 1; | ||
| 427 | |||
| 428 | dstr1++; | ||
| 429 | dsize1--; | ||
| 430 | dstr2++; | ||
| 431 | dsize2--; | ||
| 432 | } | ||
| 433 | |||
| 434 | if (len1 < len2) | ||
| 435 | return -1; | ||
| 436 | if (len1 > len2) | ||
| 437 | return 1; | ||
| 438 | return 0; | ||
| 439 | } | ||
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index e6b46b3ac2fe..d145cb79c30a 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c | |||
| @@ -13,15 +13,18 @@ | |||
| 13 | #include <linux/fs.h> | 13 | #include <linux/fs.h> |
| 14 | #include <linux/mount.h> | 14 | #include <linux/mount.h> |
| 15 | #include <linux/file.h> | 15 | #include <linux/file.h> |
| 16 | #include <linux/kernel.h> | ||
| 16 | #include <linux/writeback.h> | 17 | #include <linux/writeback.h> |
| 17 | #include <linux/pagemap.h> | 18 | #include <linux/pagemap.h> |
| 18 | #include <linux/highmem.h> | 19 | #include <linux/highmem.h> |
| 19 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 20 | #include <linux/string.h> | 21 | #include <linux/string.h> |
| 21 | #include <linux/capability.h> | 22 | #include <linux/capability.h> |
| 23 | #include <linux/ctype.h> | ||
| 22 | #include <linux/backing-dev.h> | 24 | #include <linux/backing-dev.h> |
| 23 | #include <linux/hugetlb.h> | 25 | #include <linux/hugetlb.h> |
| 24 | #include <linux/pagevec.h> | 26 | #include <linux/pagevec.h> |
| 27 | #include <linux/parser.h> | ||
| 25 | #include <linux/mman.h> | 28 | #include <linux/mman.h> |
| 26 | #include <linux/quotaops.h> | 29 | #include <linux/quotaops.h> |
| 27 | #include <linux/slab.h> | 30 | #include <linux/slab.h> |
| @@ -47,6 +50,21 @@ static struct backing_dev_info hugetlbfs_backing_dev_info = { | |||
| 47 | 50 | ||
| 48 | int sysctl_hugetlb_shm_group; | 51 | int sysctl_hugetlb_shm_group; |
| 49 | 52 | ||
| 53 | enum { | ||
| 54 | Opt_size, Opt_nr_inodes, | ||
| 55 | Opt_mode, Opt_uid, Opt_gid, | ||
| 56 | Opt_err, | ||
| 57 | }; | ||
| 58 | |||
| 59 | static match_table_t tokens = { | ||
| 60 | {Opt_size, "size=%s"}, | ||
| 61 | {Opt_nr_inodes, "nr_inodes=%s"}, | ||
| 62 | {Opt_mode, "mode=%o"}, | ||
| 63 | {Opt_uid, "uid=%u"}, | ||
| 64 | {Opt_gid, "gid=%u"}, | ||
| 65 | {Opt_err, NULL}, | ||
| 66 | }; | ||
| 67 | |||
| 50 | static void huge_pagevec_release(struct pagevec *pvec) | 68 | static void huge_pagevec_release(struct pagevec *pvec) |
| 51 | { | 69 | { |
| 52 | int i; | 70 | int i; |
| @@ -594,46 +612,73 @@ static const struct super_operations hugetlbfs_ops = { | |||
| 594 | static int | 612 | static int |
| 595 | hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) | 613 | hugetlbfs_parse_options(char *options, struct hugetlbfs_config *pconfig) |
| 596 | { | 614 | { |
| 597 | char *opt, *value, *rest; | 615 | char *p, *rest; |
| 616 | substring_t args[MAX_OPT_ARGS]; | ||
| 617 | int option; | ||
| 598 | 618 | ||
| 599 | if (!options) | 619 | if (!options) |
| 600 | return 0; | 620 | return 0; |
| 601 | while ((opt = strsep(&options, ",")) != NULL) { | 621 | |
| 602 | if (!*opt) | 622 | while ((p = strsep(&options, ",")) != NULL) { |
| 623 | int token; | ||
| 624 | if (!*p) | ||
| 603 | continue; | 625 | continue; |
| 604 | 626 | ||
| 605 | value = strchr(opt, '='); | 627 | token = match_token(p, tokens, args); |
| 606 | if (!value || !*value) | 628 | switch (token) { |
| 607 | return -EINVAL; | 629 | case Opt_uid: |
| 608 | else | 630 | if (match_int(&args[0], &option)) |
| 609 | *value++ = '\0'; | 631 | goto bad_val; |
| 610 | 632 | pconfig->uid = option; | |
| 611 | if (!strcmp(opt, "uid")) | 633 | break; |
| 612 | pconfig->uid = simple_strtoul(value, &value, 0); | 634 | |
| 613 | else if (!strcmp(opt, "gid")) | 635 | case Opt_gid: |
| 614 | pconfig->gid = simple_strtoul(value, &value, 0); | 636 | if (match_int(&args[0], &option)) |
| 615 | else if (!strcmp(opt, "mode")) | 637 | goto bad_val; |
| 616 | pconfig->mode = simple_strtoul(value,&value,0) & 0777U; | 638 | pconfig->gid = option; |
| 617 | else if (!strcmp(opt, "size")) { | 639 | break; |
| 618 | unsigned long long size = memparse(value, &rest); | 640 | |
| 641 | case Opt_mode: | ||
| 642 | if (match_octal(&args[0], &option)) | ||
| 643 | goto bad_val; | ||
| 644 | pconfig->mode = option & 0777U; | ||
| 645 | break; | ||
| 646 | |||
| 647 | case Opt_size: { | ||
| 648 | unsigned long long size; | ||
| 649 | /* memparse() will accept a K/M/G without a digit */ | ||
| 650 | if (!isdigit(*args[0].from)) | ||
| 651 | goto bad_val; | ||
| 652 | size = memparse(args[0].from, &rest); | ||
| 619 | if (*rest == '%') { | 653 | if (*rest == '%') { |
| 620 | size <<= HPAGE_SHIFT; | 654 | size <<= HPAGE_SHIFT; |
| 621 | size *= max_huge_pages; | 655 | size *= max_huge_pages; |
| 622 | do_div(size, 100); | 656 | do_div(size, 100); |
| 623 | rest++; | ||
| 624 | } | 657 | } |
| 625 | pconfig->nr_blocks = (size >> HPAGE_SHIFT); | 658 | pconfig->nr_blocks = (size >> HPAGE_SHIFT); |
| 626 | value = rest; | 659 | break; |
| 627 | } else if (!strcmp(opt,"nr_inodes")) { | 660 | } |
| 628 | pconfig->nr_inodes = memparse(value, &rest); | 661 | |
| 629 | value = rest; | 662 | case Opt_nr_inodes: |
| 630 | } else | 663 | /* memparse() will accept a K/M/G without a digit */ |
| 631 | return -EINVAL; | 664 | if (!isdigit(*args[0].from)) |
| 665 | goto bad_val; | ||
| 666 | pconfig->nr_inodes = memparse(args[0].from, &rest); | ||
| 667 | break; | ||
| 632 | 668 | ||
| 633 | if (*value) | 669 | default: |
| 670 | printk(KERN_ERR "hugetlbfs: Bad mount option: \"%s\"\n", | ||
| 671 | p); | ||
| 634 | return -EINVAL; | 672 | return -EINVAL; |
| 673 | break; | ||
| 674 | } | ||
| 635 | } | 675 | } |
| 636 | return 0; | 676 | return 0; |
| 677 | |||
| 678 | bad_val: | ||
| 679 | printk(KERN_ERR "hugetlbfs: Bad value '%s' for mount option '%s'\n", | ||
| 680 | args[0].from, p); | ||
| 681 | return 1; | ||
| 637 | } | 682 | } |
| 638 | 683 | ||
| 639 | static int | 684 | static int |
| @@ -651,7 +696,6 @@ hugetlbfs_fill_super(struct super_block *sb, void *data, int silent) | |||
| 651 | config.gid = current->fsgid; | 696 | config.gid = current->fsgid; |
| 652 | config.mode = 0755; | 697 | config.mode = 0755; |
| 653 | ret = hugetlbfs_parse_options(data, &config); | 698 | ret = hugetlbfs_parse_options(data, &config); |
| 654 | |||
| 655 | if (ret) | 699 | if (ret) |
| 656 | return ret; | 700 | return ret; |
| 657 | 701 | ||
diff --git a/fs/ioctl.c b/fs/ioctl.c index 8c90cbc903fa..c2a773e8620b 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <linux/fs.h> | 12 | #include <linux/fs.h> |
| 13 | #include <linux/security.h> | 13 | #include <linux/security.h> |
| 14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
| 15 | #include <linux/kallsyms.h> | ||
| 16 | 15 | ||
| 17 | #include <asm/uaccess.h> | 16 | #include <asm/uaccess.h> |
| 18 | #include <asm/ioctls.h> | 17 | #include <asm/ioctls.h> |
| @@ -21,7 +20,6 @@ static long do_ioctl(struct file *filp, unsigned int cmd, | |||
| 21 | unsigned long arg) | 20 | unsigned long arg) |
| 22 | { | 21 | { |
| 23 | int error = -ENOTTY; | 22 | int error = -ENOTTY; |
| 24 | void *f; | ||
| 25 | 23 | ||
| 26 | if (!filp->f_op) | 24 | if (!filp->f_op) |
| 27 | goto out; | 25 | goto out; |
| @@ -31,16 +29,10 @@ static long do_ioctl(struct file *filp, unsigned int cmd, | |||
| 31 | if (error == -ENOIOCTLCMD) | 29 | if (error == -ENOIOCTLCMD) |
| 32 | error = -EINVAL; | 30 | error = -EINVAL; |
| 33 | goto out; | 31 | goto out; |
| 34 | } else if ((f = filp->f_op->ioctl)) { | 32 | } else if (filp->f_op->ioctl) { |
| 35 | lock_kernel(); | 33 | lock_kernel(); |
| 36 | if (!filp->f_op->ioctl) { | 34 | error = filp->f_op->ioctl(filp->f_path.dentry->d_inode, |
| 37 | printk("%s: ioctl %p disappeared\n", __FUNCTION__, f); | 35 | filp, cmd, arg); |
| 38 | print_symbol("symbol: %s\n", (unsigned long)f); | ||
| 39 | dump_stack(); | ||
| 40 | } else { | ||
| 41 | error = filp->f_op->ioctl(filp->f_path.dentry->d_inode, | ||
| 42 | filp, cmd, arg); | ||
| 43 | } | ||
| 44 | unlock_kernel(); | 36 | unlock_kernel(); |
| 45 | } | 37 | } |
| 46 | 38 | ||
| @@ -182,11 +174,3 @@ asmlinkage long sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg) | |||
| 182 | out: | 174 | out: |
| 183 | return error; | 175 | return error; |
| 184 | } | 176 | } |
| 185 | |||
| 186 | /* | ||
| 187 | * Platforms implementing 32 bit compatibility ioctl handlers in | ||
| 188 | * modules need this exported | ||
| 189 | */ | ||
| 190 | #ifdef CONFIG_COMPAT | ||
| 191 | EXPORT_SYMBOL(sys_ioctl); | ||
| 192 | #endif | ||
diff --git a/fs/isofs/dir.c b/fs/isofs/dir.c index 0e94c31cad9b..1ba407c64df1 100644 --- a/fs/isofs/dir.c +++ b/fs/isofs/dir.c | |||
| @@ -7,34 +7,18 @@ | |||
| 7 | * | 7 | * |
| 8 | * Steve Beynon : Missing last directory entries fixed | 8 | * Steve Beynon : Missing last directory entries fixed |
| 9 | * (stephen@askone.demon.co.uk) : 21st June 1996 | 9 | * (stephen@askone.demon.co.uk) : 21st June 1996 |
| 10 | * | 10 | * |
| 11 | * isofs directory handling functions | 11 | * isofs directory handling functions |
| 12 | */ | 12 | */ |
| 13 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
| 14 | #include "isofs.h" | 14 | #include "isofs.h" |
| 15 | 15 | ||
| 16 | static int isofs_readdir(struct file *, void *, filldir_t); | ||
| 17 | |||
| 18 | const struct file_operations isofs_dir_operations = | ||
| 19 | { | ||
| 20 | .read = generic_read_dir, | ||
| 21 | .readdir = isofs_readdir, | ||
| 22 | }; | ||
| 23 | |||
| 24 | /* | ||
| 25 | * directories can handle most operations... | ||
| 26 | */ | ||
| 27 | const struct inode_operations isofs_dir_inode_operations = | ||
| 28 | { | ||
| 29 | .lookup = isofs_lookup, | ||
| 30 | }; | ||
| 31 | |||
| 32 | int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode) | 16 | int isofs_name_translate(struct iso_directory_record *de, char *new, struct inode *inode) |
| 33 | { | 17 | { |
| 34 | char * old = de->name; | 18 | char * old = de->name; |
| 35 | int len = de->name_len[0]; | 19 | int len = de->name_len[0]; |
| 36 | int i; | 20 | int i; |
| 37 | 21 | ||
| 38 | for (i = 0; i < len; i++) { | 22 | for (i = 0; i < len; i++) { |
| 39 | unsigned char c = old[i]; | 23 | unsigned char c = old[i]; |
| 40 | if (!c) | 24 | if (!c) |
| @@ -62,22 +46,27 @@ int isofs_name_translate(struct iso_directory_record *de, char *new, struct inod | |||
| 62 | } | 46 | } |
| 63 | 47 | ||
| 64 | /* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */ | 48 | /* Acorn extensions written by Matthew Wilcox <willy@bofh.ai> 1998 */ |
| 65 | int get_acorn_filename(struct iso_directory_record * de, | 49 | int get_acorn_filename(struct iso_directory_record *de, |
| 66 | char * retname, struct inode * inode) | 50 | char *retname, struct inode *inode) |
| 67 | { | 51 | { |
| 68 | int std; | 52 | int std; |
| 69 | unsigned char * chr; | 53 | unsigned char *chr; |
| 70 | int retnamlen = isofs_name_translate(de, retname, inode); | 54 | int retnamlen = isofs_name_translate(de, retname, inode); |
| 71 | if (retnamlen == 0) return 0; | 55 | |
| 56 | if (retnamlen == 0) | ||
| 57 | return 0; | ||
| 72 | std = sizeof(struct iso_directory_record) + de->name_len[0]; | 58 | std = sizeof(struct iso_directory_record) + de->name_len[0]; |
| 73 | if (std & 1) std++; | 59 | if (std & 1) |
| 74 | if ((*((unsigned char *) de) - std) != 32) return retnamlen; | 60 | std++; |
| 61 | if ((*((unsigned char *) de) - std) != 32) | ||
| 62 | return retnamlen; | ||
| 75 | chr = ((unsigned char *) de) + std; | 63 | chr = ((unsigned char *) de) + std; |
| 76 | if (strncmp(chr, "ARCHIMEDES", 10)) return retnamlen; | 64 | if (strncmp(chr, "ARCHIMEDES", 10)) |
| 77 | if ((*retname == '_') && ((chr[19] & 1) == 1)) *retname = '!'; | 65 | return retnamlen; |
| 66 | if ((*retname == '_') && ((chr[19] & 1) == 1)) | ||
| 67 | *retname = '!'; | ||
| 78 | if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff) | 68 | if (((de->flags[0] & 2) == 0) && (chr[13] == 0xff) |
| 79 | && ((chr[12] & 0xf0) == 0xf0)) | 69 | && ((chr[12] & 0xf0) == 0xf0)) { |
| 80 | { | ||
| 81 | retname[retnamlen] = ','; | 70 | retname[retnamlen] = ','; |
| 82 | sprintf(retname+retnamlen+1, "%3.3x", | 71 | sprintf(retname+retnamlen+1, "%3.3x", |
| 83 | ((chr[12] & 0xf) << 8) | chr[11]); | 72 | ((chr[12] & 0xf) << 8) | chr[11]); |
| @@ -91,7 +80,7 @@ int get_acorn_filename(struct iso_directory_record * de, | |||
| 91 | */ | 80 | */ |
| 92 | static int do_isofs_readdir(struct inode *inode, struct file *filp, | 81 | static int do_isofs_readdir(struct inode *inode, struct file *filp, |
| 93 | void *dirent, filldir_t filldir, | 82 | void *dirent, filldir_t filldir, |
| 94 | char * tmpname, struct iso_directory_record * tmpde) | 83 | char *tmpname, struct iso_directory_record *tmpde) |
| 95 | { | 84 | { |
| 96 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); | 85 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); |
| 97 | unsigned char bufbits = ISOFS_BUFFER_BITS(inode); | 86 | unsigned char bufbits = ISOFS_BUFFER_BITS(inode); |
| @@ -121,9 +110,11 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
| 121 | 110 | ||
| 122 | de_len = *(unsigned char *) de; | 111 | de_len = *(unsigned char *) de; |
| 123 | 112 | ||
| 124 | /* If the length byte is zero, we should move on to the next | 113 | /* |
| 125 | CDROM sector. If we are at the end of the directory, we | 114 | * If the length byte is zero, we should move on to the next |
| 126 | kick out of the while loop. */ | 115 | * CDROM sector. If we are at the end of the directory, we |
| 116 | * kick out of the while loop. | ||
| 117 | */ | ||
| 127 | 118 | ||
| 128 | if (de_len == 0) { | 119 | if (de_len == 0) { |
| 129 | brelse(bh); | 120 | brelse(bh); |
| @@ -157,11 +148,10 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
| 157 | 148 | ||
| 158 | if (first_de) { | 149 | if (first_de) { |
| 159 | isofs_normalize_block_and_offset(de, | 150 | isofs_normalize_block_and_offset(de, |
| 160 | &block_saved, | 151 | &block_saved, |
| 161 | &offset_saved); | 152 | &offset_saved); |
| 162 | inode_number = isofs_get_ino(block_saved, | 153 | inode_number = isofs_get_ino(block_saved, |
| 163 | offset_saved, | 154 | offset_saved, bufbits); |
| 164 | bufbits); | ||
| 165 | } | 155 | } |
| 166 | 156 | ||
| 167 | if (de->flags[-sbi->s_high_sierra] & 0x80) { | 157 | if (de->flags[-sbi->s_high_sierra] & 0x80) { |
| @@ -199,7 +189,7 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
| 199 | */ | 189 | */ |
| 200 | if ((sbi->s_hide == 'y' && | 190 | if ((sbi->s_hide == 'y' && |
| 201 | (de->flags[-sbi->s_high_sierra] & 1)) || | 191 | (de->flags[-sbi->s_high_sierra] & 1)) || |
| 202 | (sbi->s_showassoc =='n' && | 192 | (sbi->s_showassoc =='n' && |
| 203 | (de->flags[-sbi->s_high_sierra] & 4))) { | 193 | (de->flags[-sbi->s_high_sierra] & 4))) { |
| 204 | filp->f_pos += de_len; | 194 | filp->f_pos += de_len; |
| 205 | continue; | 195 | continue; |
| @@ -240,7 +230,8 @@ static int do_isofs_readdir(struct inode *inode, struct file *filp, | |||
| 240 | 230 | ||
| 241 | continue; | 231 | continue; |
| 242 | } | 232 | } |
| 243 | if (bh) brelse(bh); | 233 | if (bh) |
| 234 | brelse(bh); | ||
| 244 | return 0; | 235 | return 0; |
| 245 | } | 236 | } |
| 246 | 237 | ||
| @@ -253,8 +244,8 @@ static int isofs_readdir(struct file *filp, | |||
| 253 | void *dirent, filldir_t filldir) | 244 | void *dirent, filldir_t filldir) |
| 254 | { | 245 | { |
| 255 | int result; | 246 | int result; |
| 256 | char * tmpname; | 247 | char *tmpname; |
| 257 | struct iso_directory_record * tmpde; | 248 | struct iso_directory_record *tmpde; |
| 258 | struct inode *inode = filp->f_path.dentry->d_inode; | 249 | struct inode *inode = filp->f_path.dentry->d_inode; |
| 259 | 250 | ||
| 260 | tmpname = (char *)__get_free_page(GFP_KERNEL); | 251 | tmpname = (char *)__get_free_page(GFP_KERNEL); |
| @@ -270,3 +261,19 @@ static int isofs_readdir(struct file *filp, | |||
| 270 | unlock_kernel(); | 261 | unlock_kernel(); |
| 271 | return result; | 262 | return result; |
| 272 | } | 263 | } |
| 264 | |||
| 265 | const struct file_operations isofs_dir_operations = | ||
| 266 | { | ||
| 267 | .read = generic_read_dir, | ||
| 268 | .readdir = isofs_readdir, | ||
| 269 | }; | ||
| 270 | |||
| 271 | /* | ||
| 272 | * directories can handle most operations... | ||
| 273 | */ | ||
| 274 | const struct inode_operations isofs_dir_inode_operations = | ||
| 275 | { | ||
| 276 | .lookup = isofs_lookup, | ||
| 277 | }; | ||
| 278 | |||
| 279 | |||
diff --git a/fs/isofs/inode.c b/fs/isofs/inode.c index 5c3eecf7542e..4f5418be0590 100644 --- a/fs/isofs/inode.c +++ b/fs/isofs/inode.c | |||
| @@ -73,20 +73,20 @@ static void isofs_destroy_inode(struct inode *inode) | |||
| 73 | kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); | 73 | kmem_cache_free(isofs_inode_cachep, ISOFS_I(inode)); |
| 74 | } | 74 | } |
| 75 | 75 | ||
| 76 | static void init_once(void *foo, struct kmem_cache * cachep, unsigned long flags) | 76 | static void init_once(void *foo, struct kmem_cache *cachep, unsigned long flags) |
| 77 | { | 77 | { |
| 78 | struct iso_inode_info *ei = foo; | 78 | struct iso_inode_info *ei = foo; |
| 79 | 79 | ||
| 80 | inode_init_once(&ei->vfs_inode); | 80 | inode_init_once(&ei->vfs_inode); |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | static int init_inodecache(void) | 83 | static int init_inodecache(void) |
| 84 | { | 84 | { |
| 85 | isofs_inode_cachep = kmem_cache_create("isofs_inode_cache", | 85 | isofs_inode_cachep = kmem_cache_create("isofs_inode_cache", |
| 86 | sizeof(struct iso_inode_info), | 86 | sizeof(struct iso_inode_info), |
| 87 | 0, (SLAB_RECLAIM_ACCOUNT| | 87 | 0, (SLAB_RECLAIM_ACCOUNT| |
| 88 | SLAB_MEM_SPREAD), | 88 | SLAB_MEM_SPREAD), |
| 89 | init_once, NULL); | 89 | init_once, NULL); |
| 90 | if (isofs_inode_cachep == NULL) | 90 | if (isofs_inode_cachep == NULL) |
| 91 | return -ENOMEM; | 91 | return -ENOMEM; |
| 92 | return 0; | 92 | return 0; |
| @@ -150,9 +150,9 @@ struct iso9660_options{ | |||
| 150 | uid_t uid; | 150 | uid_t uid; |
| 151 | char *iocharset; | 151 | char *iocharset; |
| 152 | unsigned char utf8; | 152 | unsigned char utf8; |
| 153 | /* LVE */ | 153 | /* LVE */ |
| 154 | s32 session; | 154 | s32 session; |
| 155 | s32 sbsector; | 155 | s32 sbsector; |
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | /* | 158 | /* |
| @@ -197,7 +197,7 @@ isofs_hashi_common(struct dentry *dentry, struct qstr *qstr, int ms) | |||
| 197 | hash = init_name_hash(); | 197 | hash = init_name_hash(); |
| 198 | while (len--) { | 198 | while (len--) { |
| 199 | c = tolower(*name++); | 199 | c = tolower(*name++); |
| 200 | hash = partial_name_hash(tolower(c), hash); | 200 | hash = partial_name_hash(c, hash); |
| 201 | } | 201 | } |
| 202 | qstr->hash = end_name_hash(hash); | 202 | qstr->hash = end_name_hash(hash); |
| 203 | 203 | ||
| @@ -360,10 +360,12 @@ static int parse_options(char *options, struct iso9660_options *popt) | |||
| 360 | popt->check = 'u'; /* unset */ | 360 | popt->check = 'u'; /* unset */ |
| 361 | popt->nocompress = 0; | 361 | popt->nocompress = 0; |
| 362 | popt->blocksize = 1024; | 362 | popt->blocksize = 1024; |
| 363 | popt->mode = S_IRUGO | S_IXUGO; /* r-x for all. The disc could | 363 | popt->mode = S_IRUGO | S_IXUGO; /* |
| 364 | be shared with DOS machines so | 364 | * r-x for all. The disc could |
| 365 | virtually anything could be | 365 | * be shared with DOS machines so |
| 366 | a valid executable. */ | 366 | * virtually anything could be |
| 367 | * a valid executable. | ||
| 368 | */ | ||
| 367 | popt->gid = 0; | 369 | popt->gid = 0; |
| 368 | popt->uid = 0; | 370 | popt->uid = 0; |
| 369 | popt->iocharset = NULL; | 371 | popt->iocharset = NULL; |
| @@ -503,30 +505,30 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session) | |||
| 503 | Te.cdte_format=CDROM_LBA; | 505 | Te.cdte_format=CDROM_LBA; |
| 504 | i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te); | 506 | i = ioctl_by_bdev(bdev, CDROMREADTOCENTRY, (unsigned long) &Te); |
| 505 | if (!i) { | 507 | if (!i) { |
| 506 | printk(KERN_DEBUG "Session %d start %d type %d\n", | 508 | printk(KERN_DEBUG "ISOFS: Session %d start %d type %d\n", |
| 507 | session, Te.cdte_addr.lba, | 509 | session, Te.cdte_addr.lba, |
| 508 | Te.cdte_ctrl&CDROM_DATA_TRACK); | 510 | Te.cdte_ctrl&CDROM_DATA_TRACK); |
| 509 | if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4) | 511 | if ((Te.cdte_ctrl&CDROM_DATA_TRACK) == 4) |
| 510 | return Te.cdte_addr.lba; | 512 | return Te.cdte_addr.lba; |
| 511 | } | 513 | } |
| 512 | 514 | ||
| 513 | printk(KERN_ERR "Invalid session number or type of track\n"); | 515 | printk(KERN_ERR "ISOFS: Invalid session number or type of track\n"); |
| 514 | } | 516 | } |
| 515 | i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info); | 517 | i = ioctl_by_bdev(bdev, CDROMMULTISESSION, (unsigned long) &ms_info); |
| 516 | if (session > 0) | 518 | if (session > 0) |
| 517 | printk(KERN_ERR "Invalid session number\n"); | 519 | printk(KERN_ERR "ISOFS: Invalid session number\n"); |
| 518 | #if 0 | 520 | #if 0 |
| 519 | printk("isofs.inode: CDROMMULTISESSION: rc=%d\n",i); | 521 | printk(KERN_DEBUG "isofs.inode: CDROMMULTISESSION: rc=%d\n",i); |
| 520 | if (i==0) { | 522 | if (i==0) { |
| 521 | printk("isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no"); | 523 | printk(KERN_DEBUG "isofs.inode: XA disk: %s\n",ms_info.xa_flag?"yes":"no"); |
| 522 | printk("isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba); | 524 | printk(KERN_DEBUG "isofs.inode: vol_desc_start = %d\n", ms_info.addr.lba); |
| 523 | } | 525 | } |
| 524 | #endif | 526 | #endif |
| 525 | if (i==0) | 527 | if (i==0) |
| 526 | #if WE_OBEY_THE_WRITTEN_STANDARDS | 528 | #if WE_OBEY_THE_WRITTEN_STANDARDS |
| 527 | if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ | 529 | if (ms_info.xa_flag) /* necessary for a valid ms_info.addr */ |
| 528 | #endif | 530 | #endif |
| 529 | vol_desc_start=ms_info.addr.lba; | 531 | vol_desc_start=ms_info.addr.lba; |
| 530 | return vol_desc_start; | 532 | return vol_desc_start; |
| 531 | } | 533 | } |
| 532 | 534 | ||
| @@ -538,20 +540,20 @@ static unsigned int isofs_get_last_session(struct super_block *sb, s32 session) | |||
| 538 | */ | 540 | */ |
| 539 | static int isofs_fill_super(struct super_block *s, void *data, int silent) | 541 | static int isofs_fill_super(struct super_block *s, void *data, int silent) |
| 540 | { | 542 | { |
| 541 | struct buffer_head * bh = NULL, *pri_bh = NULL; | 543 | struct buffer_head *bh = NULL, *pri_bh = NULL; |
| 542 | struct hs_primary_descriptor * h_pri = NULL; | 544 | struct hs_primary_descriptor *h_pri = NULL; |
| 543 | struct iso_primary_descriptor * pri = NULL; | 545 | struct iso_primary_descriptor *pri = NULL; |
| 544 | struct iso_supplementary_descriptor *sec = NULL; | 546 | struct iso_supplementary_descriptor *sec = NULL; |
| 545 | struct iso_directory_record * rootp; | 547 | struct iso_directory_record *rootp; |
| 546 | int joliet_level = 0; | 548 | struct inode *inode; |
| 547 | int iso_blknum, block; | 549 | struct iso9660_options opt; |
| 548 | int orig_zonesize; | 550 | struct isofs_sb_info *sbi; |
| 549 | int table; | 551 | unsigned long first_data_zone; |
| 550 | unsigned int vol_desc_start; | 552 | int joliet_level = 0; |
| 551 | unsigned long first_data_zone; | 553 | int iso_blknum, block; |
| 552 | struct inode * inode; | 554 | int orig_zonesize; |
| 553 | struct iso9660_options opt; | 555 | int table; |
| 554 | struct isofs_sb_info * sbi; | 556 | unsigned int vol_desc_start; |
| 555 | 557 | ||
| 556 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | 558 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); |
| 557 | if (!sbi) | 559 | if (!sbi) |
| @@ -577,72 +579,73 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) | |||
| 577 | vol_desc_start = (opt.sbsector != -1) ? | 579 | vol_desc_start = (opt.sbsector != -1) ? |
| 578 | opt.sbsector : isofs_get_last_session(s,opt.session); | 580 | opt.sbsector : isofs_get_last_session(s,opt.session); |
| 579 | 581 | ||
| 580 | for (iso_blknum = vol_desc_start+16; | 582 | for (iso_blknum = vol_desc_start+16; |
| 581 | iso_blknum < vol_desc_start+100; iso_blknum++) | 583 | iso_blknum < vol_desc_start+100; iso_blknum++) { |
| 582 | { | 584 | struct hs_volume_descriptor *hdp; |
| 583 | struct hs_volume_descriptor * hdp; | 585 | struct iso_volume_descriptor *vdp; |
| 584 | struct iso_volume_descriptor * vdp; | 586 | |
| 585 | 587 | block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits); | |
| 586 | block = iso_blknum << (ISOFS_BLOCK_BITS - s->s_blocksize_bits); | 588 | if (!(bh = sb_bread(s, block))) |
| 587 | if (!(bh = sb_bread(s, block))) | 589 | goto out_no_read; |
| 588 | goto out_no_read; | 590 | |
| 589 | 591 | vdp = (struct iso_volume_descriptor *)bh->b_data; | |
| 590 | vdp = (struct iso_volume_descriptor *)bh->b_data; | 592 | hdp = (struct hs_volume_descriptor *)bh->b_data; |
| 591 | hdp = (struct hs_volume_descriptor *)bh->b_data; | 593 | |
| 592 | 594 | /* | |
| 593 | /* Due to the overlapping physical location of the descriptors, | 595 | * Due to the overlapping physical location of the descriptors, |
| 594 | * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure | 596 | * ISO CDs can match hdp->id==HS_STANDARD_ID as well. To ensure |
| 595 | * proper identification in this case, we first check for ISO. | 597 | * proper identification in this case, we first check for ISO. |
| 596 | */ | 598 | */ |
| 597 | if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) { | 599 | if (strncmp (vdp->id, ISO_STANDARD_ID, sizeof vdp->id) == 0) { |
| 598 | if (isonum_711 (vdp->type) == ISO_VD_END) | 600 | if (isonum_711(vdp->type) == ISO_VD_END) |
| 599 | break; | 601 | break; |
| 600 | if (isonum_711 (vdp->type) == ISO_VD_PRIMARY) { | 602 | if (isonum_711(vdp->type) == ISO_VD_PRIMARY) { |
| 601 | if (pri == NULL) { | 603 | if (pri == NULL) { |
| 602 | pri = (struct iso_primary_descriptor *)vdp; | 604 | pri = (struct iso_primary_descriptor *)vdp; |
| 603 | /* Save the buffer in case we need it ... */ | 605 | /* Save the buffer in case we need it ... */ |
| 604 | pri_bh = bh; | 606 | pri_bh = bh; |
| 605 | bh = NULL; | 607 | bh = NULL; |
| 606 | } | 608 | } |
| 607 | } | 609 | } |
| 608 | #ifdef CONFIG_JOLIET | 610 | #ifdef CONFIG_JOLIET |
| 609 | else if (isonum_711 (vdp->type) == ISO_VD_SUPPLEMENTARY) { | 611 | else if (isonum_711(vdp->type) == ISO_VD_SUPPLEMENTARY) { |
| 610 | sec = (struct iso_supplementary_descriptor *)vdp; | 612 | sec = (struct iso_supplementary_descriptor *)vdp; |
| 611 | if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { | 613 | if (sec->escape[0] == 0x25 && sec->escape[1] == 0x2f) { |
| 612 | if (opt.joliet == 'y') { | 614 | if (opt.joliet == 'y') { |
| 613 | if (sec->escape[2] == 0x40) { | 615 | if (sec->escape[2] == 0x40) |
| 614 | joliet_level = 1; | 616 | joliet_level = 1; |
| 615 | } else if (sec->escape[2] == 0x43) { | 617 | else if (sec->escape[2] == 0x43) |
| 616 | joliet_level = 2; | 618 | joliet_level = 2; |
| 617 | } else if (sec->escape[2] == 0x45) { | 619 | else if (sec->escape[2] == 0x45) |
| 618 | joliet_level = 3; | 620 | joliet_level = 3; |
| 619 | } | 621 | |
| 620 | printk(KERN_DEBUG"ISO 9660 Extensions: Microsoft Joliet Level %d\n", | 622 | printk(KERN_DEBUG "ISO 9660 Extensions: " |
| 621 | joliet_level); | 623 | "Microsoft Joliet Level %d\n", |
| 624 | joliet_level); | ||
| 625 | } | ||
| 626 | goto root_found; | ||
| 627 | } else { | ||
| 628 | /* Unknown supplementary volume descriptor */ | ||
| 629 | sec = NULL; | ||
| 630 | } | ||
| 622 | } | 631 | } |
| 623 | goto root_found; | ||
| 624 | } else { | ||
| 625 | /* Unknown supplementary volume descriptor */ | ||
| 626 | sec = NULL; | ||
| 627 | } | ||
| 628 | } | ||
| 629 | #endif | 632 | #endif |
| 630 | } else { | 633 | } else { |
| 631 | if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { | 634 | if (strncmp (hdp->id, HS_STANDARD_ID, sizeof hdp->id) == 0) { |
| 632 | if (isonum_711 (hdp->type) != ISO_VD_PRIMARY) | 635 | if (isonum_711(hdp->type) != ISO_VD_PRIMARY) |
| 633 | goto out_freebh; | 636 | goto out_freebh; |
| 634 | 637 | ||
| 635 | sbi->s_high_sierra = 1; | 638 | sbi->s_high_sierra = 1; |
| 636 | opt.rock = 'n'; | 639 | opt.rock = 'n'; |
| 637 | h_pri = (struct hs_primary_descriptor *)vdp; | 640 | h_pri = (struct hs_primary_descriptor *)vdp; |
| 638 | goto root_found; | 641 | goto root_found; |
| 642 | } | ||
| 639 | } | 643 | } |
| 640 | } | ||
| 641 | 644 | ||
| 642 | /* Just skip any volume descriptors we don't recognize */ | 645 | /* Just skip any volume descriptors we don't recognize */ |
| 643 | 646 | ||
| 644 | brelse(bh); | 647 | brelse(bh); |
| 645 | bh = NULL; | 648 | bh = NULL; |
| 646 | } | 649 | } |
| 647 | /* | 650 | /* |
| 648 | * If we fall through, either no volume descriptor was found, | 651 | * If we fall through, either no volume descriptor was found, |
| @@ -657,24 +660,24 @@ static int isofs_fill_super(struct super_block *s, void *data, int silent) | |||
| 657 | root_found: | 660 | root_found: |
| 658 | 661 | ||
| 659 | if (joliet_level && (pri == NULL || opt.rock == 'n')) { | 662 | if (joliet_level && (pri == NULL || opt.rock == 'n')) { |
| 660 | /* This is the case of Joliet with the norock mount flag. | 663 | /* This is the case of Joliet with the norock mount flag. |
| 661 | * A disc with both Joliet and Rock Ridge is handled later | 664 | * A disc with both Joliet and Rock Ridge is handled later |
| 662 | */ | 665 | */ |
| 663 | pri = (struct iso_primary_descriptor *) sec; | 666 | pri = (struct iso_primary_descriptor *) sec; |
| 664 | } | 667 | } |
| 665 | 668 | ||
| 666 | if(sbi->s_high_sierra){ | 669 | if(sbi->s_high_sierra){ |
| 667 | rootp = (struct iso_directory_record *) h_pri->root_directory_record; | 670 | rootp = (struct iso_directory_record *) h_pri->root_directory_record; |
| 668 | sbi->s_nzones = isonum_733 (h_pri->volume_space_size); | 671 | sbi->s_nzones = isonum_733(h_pri->volume_space_size); |
| 669 | sbi->s_log_zone_size = isonum_723 (h_pri->logical_block_size); | 672 | sbi->s_log_zone_size = isonum_723(h_pri->logical_block_size); |
| 670 | sbi->s_max_size = isonum_733(h_pri->volume_space_size); | 673 | sbi->s_max_size = isonum_733(h_pri->volume_space_size); |
| 671 | } else { | 674 | } else { |
| 672 | if (!pri) | 675 | if (!pri) |
| 673 | goto out_freebh; | 676 | goto out_freebh; |
| 674 | rootp = (struct iso_directory_record *) pri->root_directory_record; | 677 | rootp = (struct iso_directory_record *) pri->root_directory_record; |
| 675 | sbi->s_nzones = isonum_733 (pri->volume_space_size); | 678 | sbi->s_nzones = isonum_733(pri->volume_space_size); |
| 676 | sbi->s_log_zone_size = isonum_723 (pri->logical_block_size); | 679 | sbi->s_log_zone_size = isonum_723(pri->logical_block_size); |
| 677 | sbi->s_max_size = isonum_733(pri->volume_space_size); | 680 | sbi->s_max_size = isonum_733(pri->volume_space_size); |
| 678 | } | 681 | } |
| 679 | 682 | ||
| 680 | sbi->s_ninodes = 0; /* No way to figure this out easily */ | 683 | sbi->s_ninodes = 0; /* No way to figure this out easily */ |
| @@ -687,42 +690,43 @@ root_found: | |||
| 687 | * blocks that were 512 bytes (which should only very rarely | 690 | * blocks that were 512 bytes (which should only very rarely |
| 688 | * happen.) | 691 | * happen.) |
| 689 | */ | 692 | */ |
| 690 | if(orig_zonesize < opt.blocksize) | 693 | if (orig_zonesize < opt.blocksize) |
| 691 | goto out_bad_size; | 694 | goto out_bad_size; |
| 692 | 695 | ||
| 693 | /* RDE: convert log zone size to bit shift */ | 696 | /* RDE: convert log zone size to bit shift */ |
| 694 | switch (sbi->s_log_zone_size) | 697 | switch (sbi->s_log_zone_size) { |
| 695 | { case 512: sbi->s_log_zone_size = 9; break; | 698 | case 512: sbi->s_log_zone_size = 9; break; |
| 696 | case 1024: sbi->s_log_zone_size = 10; break; | 699 | case 1024: sbi->s_log_zone_size = 10; break; |
| 697 | case 2048: sbi->s_log_zone_size = 11; break; | 700 | case 2048: sbi->s_log_zone_size = 11; break; |
| 698 | 701 | ||
| 699 | default: | 702 | default: |
| 700 | goto out_bad_zone_size; | 703 | goto out_bad_zone_size; |
| 701 | } | 704 | } |
| 702 | 705 | ||
| 703 | s->s_magic = ISOFS_SUPER_MAGIC; | 706 | s->s_magic = ISOFS_SUPER_MAGIC; |
| 704 | s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */ | 707 | s->s_maxbytes = 0xffffffff; /* We can handle files up to 4 GB */ |
| 705 | 708 | ||
| 706 | /* The CDROM is read-only, has no nodes (devices) on it, and since | 709 | /* |
| 707 | all of the files appear to be owned by root, we really do not want | 710 | * The CDROM is read-only, has no nodes (devices) on it, and since |
| 708 | to allow suid. (suid or devices will not show up unless we have | 711 | * all of the files appear to be owned by root, we really do not want |
| 709 | Rock Ridge extensions) */ | 712 | * to allow suid. (suid or devices will not show up unless we have |
| 713 | * Rock Ridge extensions) | ||
| 714 | */ | ||
| 710 | 715 | ||
| 711 | s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */; | 716 | s->s_flags |= MS_RDONLY /* | MS_NODEV | MS_NOSUID */; |
| 712 | 717 | ||
| 713 | /* Set this for reference. Its not currently used except on write | 718 | /* Set this for reference. Its not currently used except on write |
| 714 | which we don't have .. */ | 719 | which we don't have .. */ |
| 715 | 720 | ||
| 716 | first_data_zone = isonum_733 (rootp->extent) + | 721 | first_data_zone = isonum_733(rootp->extent) + |
| 717 | isonum_711 (rootp->ext_attr_length); | 722 | isonum_711(rootp->ext_attr_length); |
| 718 | sbi->s_firstdatazone = first_data_zone; | 723 | sbi->s_firstdatazone = first_data_zone; |
| 719 | #ifndef BEQUIET | 724 | #ifndef BEQUIET |
| 720 | printk(KERN_DEBUG "Max size:%ld Log zone size:%ld\n", | 725 | printk(KERN_DEBUG "ISOFS: Max size:%ld Log zone size:%ld\n", |
| 721 | sbi->s_max_size, | 726 | sbi->s_max_size, 1UL << sbi->s_log_zone_size); |
| 722 | 1UL << sbi->s_log_zone_size); | 727 | printk(KERN_DEBUG "ISOFS: First datazone:%ld\n", sbi->s_firstdatazone); |
| 723 | printk(KERN_DEBUG "First datazone:%ld\n", sbi->s_firstdatazone); | ||
| 724 | if(sbi->s_high_sierra) | 728 | if(sbi->s_high_sierra) |
| 725 | printk(KERN_DEBUG "Disc in High Sierra format.\n"); | 729 | printk(KERN_DEBUG "ISOFS: Disc in High Sierra format.\n"); |
| 726 | #endif | 730 | #endif |
| 727 | 731 | ||
| 728 | /* | 732 | /* |
| @@ -737,8 +741,8 @@ root_found: | |||
| 737 | pri = (struct iso_primary_descriptor *) sec; | 741 | pri = (struct iso_primary_descriptor *) sec; |
| 738 | rootp = (struct iso_directory_record *) | 742 | rootp = (struct iso_directory_record *) |
| 739 | pri->root_directory_record; | 743 | pri->root_directory_record; |
| 740 | first_data_zone = isonum_733 (rootp->extent) + | 744 | first_data_zone = isonum_733(rootp->extent) + |
| 741 | isonum_711 (rootp->ext_attr_length); | 745 | isonum_711(rootp->ext_attr_length); |
| 742 | } | 746 | } |
| 743 | 747 | ||
| 744 | /* | 748 | /* |
| @@ -771,7 +775,7 @@ root_found: | |||
| 771 | 775 | ||
| 772 | #ifdef CONFIG_JOLIET | 776 | #ifdef CONFIG_JOLIET |
| 773 | if (joliet_level && opt.utf8 == 0) { | 777 | if (joliet_level && opt.utf8 == 0) { |
| 774 | char * p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT; | 778 | char *p = opt.iocharset ? opt.iocharset : CONFIG_NLS_DEFAULT; |
| 775 | sbi->s_nls_iocharset = load_nls(p); | 779 | sbi->s_nls_iocharset = load_nls(p); |
| 776 | if (! sbi->s_nls_iocharset) { | 780 | if (! sbi->s_nls_iocharset) { |
| 777 | /* Fail only if explicit charset specified */ | 781 | /* Fail only if explicit charset specified */ |
| @@ -821,7 +825,7 @@ root_found: | |||
| 821 | sbi->s_rock = 0; | 825 | sbi->s_rock = 0; |
| 822 | if (sbi->s_firstdatazone != first_data_zone) { | 826 | if (sbi->s_firstdatazone != first_data_zone) { |
| 823 | sbi->s_firstdatazone = first_data_zone; | 827 | sbi->s_firstdatazone = first_data_zone; |
| 824 | printk(KERN_DEBUG | 828 | printk(KERN_DEBUG |
| 825 | "ISOFS: changing to secondary root\n"); | 829 | "ISOFS: changing to secondary root\n"); |
| 826 | iput(inode); | 830 | iput(inode); |
| 827 | inode = isofs_iget(s, sbi->s_firstdatazone, 0); | 831 | inode = isofs_iget(s, sbi->s_firstdatazone, 0); |
| @@ -830,8 +834,10 @@ root_found: | |||
| 830 | 834 | ||
| 831 | if (opt.check == 'u') { | 835 | if (opt.check == 'u') { |
| 832 | /* Only Joliet is case insensitive by default */ | 836 | /* Only Joliet is case insensitive by default */ |
| 833 | if (joliet_level) opt.check = 'r'; | 837 | if (joliet_level) |
| 834 | else opt.check = 's'; | 838 | opt.check = 'r'; |
| 839 | else | ||
| 840 | opt.check = 's'; | ||
| 835 | } | 841 | } |
| 836 | sbi->s_joliet_level = joliet_level; | 842 | sbi->s_joliet_level = joliet_level; |
| 837 | 843 | ||
| @@ -846,8 +852,10 @@ root_found: | |||
| 846 | goto out_no_root; | 852 | goto out_no_root; |
| 847 | 853 | ||
| 848 | table = 0; | 854 | table = 0; |
| 849 | if (joliet_level) table += 2; | 855 | if (joliet_level) |
| 850 | if (opt.check == 'r') table++; | 856 | table += 2; |
| 857 | if (opt.check == 'r') | ||
| 858 | table++; | ||
| 851 | s->s_root->d_op = &isofs_dentry_ops[table]; | 859 | s->s_root->d_op = &isofs_dentry_ops[table]; |
| 852 | 860 | ||
| 853 | kfree(opt.iocharset); | 861 | kfree(opt.iocharset); |
| @@ -858,10 +866,10 @@ root_found: | |||
| 858 | * Display error messages and free resources. | 866 | * Display error messages and free resources. |
| 859 | */ | 867 | */ |
| 860 | out_bad_root: | 868 | out_bad_root: |
| 861 | printk(KERN_WARNING "isofs_fill_super: root inode not initialized\n"); | 869 | printk(KERN_WARNING "%s: root inode not initialized\n", __func__); |
| 862 | goto out_iput; | 870 | goto out_iput; |
| 863 | out_no_root: | 871 | out_no_root: |
| 864 | printk(KERN_WARNING "isofs_fill_super: get root inode failed\n"); | 872 | printk(KERN_WARNING "%s: get root inode failed\n", __func__); |
| 865 | out_iput: | 873 | out_iput: |
| 866 | iput(inode); | 874 | iput(inode); |
| 867 | #ifdef CONFIG_JOLIET | 875 | #ifdef CONFIG_JOLIET |
| @@ -870,21 +878,20 @@ out_iput: | |||
| 870 | #endif | 878 | #endif |
| 871 | goto out_freesbi; | 879 | goto out_freesbi; |
| 872 | out_no_read: | 880 | out_no_read: |
| 873 | printk(KERN_WARNING "isofs_fill_super: " | 881 | printk(KERN_WARNING "%s: bread failed, dev=%s, iso_blknum=%d, block=%d\n", |
| 874 | "bread failed, dev=%s, iso_blknum=%d, block=%d\n", | 882 | __func__, s->s_id, iso_blknum, block); |
| 875 | s->s_id, iso_blknum, block); | ||
| 876 | goto out_freesbi; | 883 | goto out_freesbi; |
| 877 | out_bad_zone_size: | 884 | out_bad_zone_size: |
| 878 | printk(KERN_WARNING "Bad logical zone size %ld\n", | 885 | printk(KERN_WARNING "ISOFS: Bad logical zone size %ld\n", |
| 879 | sbi->s_log_zone_size); | 886 | sbi->s_log_zone_size); |
| 880 | goto out_freebh; | 887 | goto out_freebh; |
| 881 | out_bad_size: | 888 | out_bad_size: |
| 882 | printk(KERN_WARNING "Logical zone size(%d) < hardware blocksize(%u)\n", | 889 | printk(KERN_WARNING "ISOFS: Logical zone size(%d) < hardware blocksize(%u)\n", |
| 883 | orig_zonesize, opt.blocksize); | 890 | orig_zonesize, opt.blocksize); |
| 884 | goto out_freebh; | 891 | goto out_freebh; |
| 885 | out_unknown_format: | 892 | out_unknown_format: |
| 886 | if (!silent) | 893 | if (!silent) |
| 887 | printk(KERN_WARNING "Unable to identify CD-ROM format.\n"); | 894 | printk(KERN_WARNING "ISOFS: Unable to identify CD-ROM format.\n"); |
| 888 | 895 | ||
| 889 | out_freebh: | 896 | out_freebh: |
| 890 | brelse(bh); | 897 | brelse(bh); |
| @@ -902,7 +909,7 @@ static int isofs_statfs (struct dentry *dentry, struct kstatfs *buf) | |||
| 902 | buf->f_type = ISOFS_SUPER_MAGIC; | 909 | buf->f_type = ISOFS_SUPER_MAGIC; |
| 903 | buf->f_bsize = sb->s_blocksize; | 910 | buf->f_bsize = sb->s_blocksize; |
| 904 | buf->f_blocks = (ISOFS_SB(sb)->s_nzones | 911 | buf->f_blocks = (ISOFS_SB(sb)->s_nzones |
| 905 | << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits)); | 912 | << (ISOFS_SB(sb)->s_log_zone_size - sb->s_blocksize_bits)); |
| 906 | buf->f_bfree = 0; | 913 | buf->f_bfree = 0; |
| 907 | buf->f_bavail = 0; | 914 | buf->f_bavail = 0; |
| 908 | buf->f_files = ISOFS_SB(sb)->s_ninodes; | 915 | buf->f_files = ISOFS_SB(sb)->s_ninodes; |
| @@ -931,20 +938,20 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
| 931 | 938 | ||
| 932 | rv = 0; | 939 | rv = 0; |
| 933 | if (iblock < 0 || iblock != iblock_s) { | 940 | if (iblock < 0 || iblock != iblock_s) { |
| 934 | printk("isofs_get_blocks: block number too large\n"); | 941 | printk(KERN_DEBUG "%s: block number too large\n", __func__); |
| 935 | goto abort; | 942 | goto abort; |
| 936 | } | 943 | } |
| 937 | 944 | ||
| 938 | b_off = iblock; | 945 | b_off = iblock; |
| 939 | 946 | ||
| 940 | offset = 0; | 947 | offset = 0; |
| 941 | firstext = ei->i_first_extent; | 948 | firstext = ei->i_first_extent; |
| 942 | sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode); | 949 | sect_size = ei->i_section_size >> ISOFS_BUFFER_BITS(inode); |
| 943 | nextblk = ei->i_next_section_block; | 950 | nextblk = ei->i_next_section_block; |
| 944 | nextoff = ei->i_next_section_offset; | 951 | nextoff = ei->i_next_section_offset; |
| 945 | section = 0; | 952 | section = 0; |
| 946 | 953 | ||
| 947 | while ( nblocks ) { | 954 | while (nblocks) { |
| 948 | /* If we are *way* beyond the end of the file, print a message. | 955 | /* If we are *way* beyond the end of the file, print a message. |
| 949 | * Access beyond the end of the file up to the next page boundary | 956 | * Access beyond the end of the file up to the next page boundary |
| 950 | * is normal, however because of the way the page cache works. | 957 | * is normal, however because of the way the page cache works. |
| @@ -953,11 +960,11 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
| 953 | * I/O errors. | 960 | * I/O errors. |
| 954 | */ | 961 | */ |
| 955 | if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) { | 962 | if (b_off > ((inode->i_size + PAGE_CACHE_SIZE - 1) >> ISOFS_BUFFER_BITS(inode))) { |
| 956 | printk("isofs_get_blocks: block >= EOF (%ld, %ld)\n", | 963 | printk(KERN_DEBUG "%s: block >= EOF (%ld, %ld)\n", |
| 957 | iblock, (unsigned long) inode->i_size); | 964 | __func__, iblock, (unsigned long) inode->i_size); |
| 958 | goto abort; | 965 | goto abort; |
| 959 | } | 966 | } |
| 960 | 967 | ||
| 961 | /* On the last section, nextblk == 0, section size is likely to | 968 | /* On the last section, nextblk == 0, section size is likely to |
| 962 | * exceed sect_size by a partial block, and access beyond the | 969 | * exceed sect_size by a partial block, and access beyond the |
| 963 | * end of the file will reach beyond the section size, too. | 970 | * end of the file will reach beyond the section size, too. |
| @@ -976,20 +983,21 @@ int isofs_get_blocks(struct inode *inode, sector_t iblock_s, | |||
| 976 | iput(ninode); | 983 | iput(ninode); |
| 977 | 984 | ||
| 978 | if (++section > 100) { | 985 | if (++section > 100) { |
| 979 | printk("isofs_get_blocks: More than 100 file sections ?!?, aborting...\n"); | 986 | printk(KERN_DEBUG "%s: More than 100 file sections ?!?" |
| 980 | printk("isofs_get_blocks: block=%ld firstext=%u sect_size=%u " | 987 | " aborting...\n", __func__); |
| 981 | "nextblk=%lu nextoff=%lu\n", | 988 | printk(KERN_DEBUG "%s: block=%ld firstext=%u sect_size=%u " |
| 982 | iblock, firstext, (unsigned) sect_size, | 989 | "nextblk=%lu nextoff=%lu\n", __func__, |
| 983 | nextblk, nextoff); | 990 | iblock, firstext, (unsigned) sect_size, |
| 991 | nextblk, nextoff); | ||
| 984 | goto abort; | 992 | goto abort; |
| 985 | } | 993 | } |
| 986 | } | 994 | } |
| 987 | 995 | ||
| 988 | if ( *bh ) { | 996 | if (*bh) { |
| 989 | map_bh(*bh, inode->i_sb, firstext + b_off - offset); | 997 | map_bh(*bh, inode->i_sb, firstext + b_off - offset); |
| 990 | } else { | 998 | } else { |
| 991 | *bh = sb_getblk(inode->i_sb, firstext+b_off-offset); | 999 | *bh = sb_getblk(inode->i_sb, firstext+b_off-offset); |
| 992 | if ( !*bh ) | 1000 | if (!*bh) |
| 993 | goto abort; | 1001 | goto abort; |
| 994 | } | 1002 | } |
| 995 | bh++; /* Next buffer head */ | 1003 | bh++; /* Next buffer head */ |
| @@ -1010,7 +1018,7 @@ static int isofs_get_block(struct inode *inode, sector_t iblock, | |||
| 1010 | struct buffer_head *bh_result, int create) | 1018 | struct buffer_head *bh_result, int create) |
| 1011 | { | 1019 | { |
| 1012 | if (create) { | 1020 | if (create) { |
| 1013 | printk("isofs_get_block: Kernel tries to allocate a block\n"); | 1021 | printk(KERN_DEBUG "%s: Kernel tries to allocate a block\n", __func__); |
| 1014 | return -EROFS; | 1022 | return -EROFS; |
| 1015 | } | 1023 | } |
| 1016 | 1024 | ||
| @@ -1070,11 +1078,11 @@ static int isofs_read_level3_size(struct inode *inode) | |||
| 1070 | { | 1078 | { |
| 1071 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); | 1079 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); |
| 1072 | int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra; | 1080 | int high_sierra = ISOFS_SB(inode->i_sb)->s_high_sierra; |
| 1073 | struct buffer_head * bh = NULL; | 1081 | struct buffer_head *bh = NULL; |
| 1074 | unsigned long block, offset, block_saved, offset_saved; | 1082 | unsigned long block, offset, block_saved, offset_saved; |
| 1075 | int i = 0; | 1083 | int i = 0; |
| 1076 | int more_entries = 0; | 1084 | int more_entries = 0; |
| 1077 | struct iso_directory_record * tmpde = NULL; | 1085 | struct iso_directory_record *tmpde = NULL; |
| 1078 | struct iso_inode_info *ei = ISOFS_I(inode); | 1086 | struct iso_inode_info *ei = ISOFS_I(inode); |
| 1079 | 1087 | ||
| 1080 | inode->i_size = 0; | 1088 | inode->i_size = 0; |
| @@ -1089,7 +1097,7 @@ static int isofs_read_level3_size(struct inode *inode) | |||
| 1089 | offset = ei->i_iget5_offset; | 1097 | offset = ei->i_iget5_offset; |
| 1090 | 1098 | ||
| 1091 | do { | 1099 | do { |
| 1092 | struct iso_directory_record * de; | 1100 | struct iso_directory_record *de; |
| 1093 | unsigned int de_len; | 1101 | unsigned int de_len; |
| 1094 | 1102 | ||
| 1095 | if (!bh) { | 1103 | if (!bh) { |
| @@ -1163,10 +1171,9 @@ out_noread: | |||
| 1163 | return -EIO; | 1171 | return -EIO; |
| 1164 | 1172 | ||
| 1165 | out_toomany: | 1173 | out_toomany: |
| 1166 | printk(KERN_INFO "isofs_read_level3_size: " | 1174 | printk(KERN_INFO "%s: More than 100 file sections ?!?, aborting...\n" |
| 1167 | "More than 100 file sections ?!?, aborting...\n" | 1175 | "isofs_read_level3_size: inode=%lu\n", |
| 1168 | "isofs_read_level3_size: inode=%lu\n", | 1176 | __func__, inode->i_ino); |
| 1169 | inode->i_ino); | ||
| 1170 | goto out; | 1177 | goto out; |
| 1171 | } | 1178 | } |
| 1172 | 1179 | ||
| @@ -1177,9 +1184,9 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1177 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); | 1184 | unsigned long bufsize = ISOFS_BUFFER_SIZE(inode); |
| 1178 | unsigned long block; | 1185 | unsigned long block; |
| 1179 | int high_sierra = sbi->s_high_sierra; | 1186 | int high_sierra = sbi->s_high_sierra; |
| 1180 | struct buffer_head * bh = NULL; | 1187 | struct buffer_head *bh = NULL; |
| 1181 | struct iso_directory_record * de; | 1188 | struct iso_directory_record *de; |
| 1182 | struct iso_directory_record * tmpde = NULL; | 1189 | struct iso_directory_record *tmpde = NULL; |
| 1183 | unsigned int de_len; | 1190 | unsigned int de_len; |
| 1184 | unsigned long offset; | 1191 | unsigned long offset; |
| 1185 | struct iso_inode_info *ei = ISOFS_I(inode); | 1192 | struct iso_inode_info *ei = ISOFS_I(inode); |
| @@ -1199,7 +1206,7 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1199 | 1206 | ||
| 1200 | tmpde = kmalloc(de_len, GFP_KERNEL); | 1207 | tmpde = kmalloc(de_len, GFP_KERNEL); |
| 1201 | if (tmpde == NULL) { | 1208 | if (tmpde == NULL) { |
| 1202 | printk(KERN_INFO "isofs_read_inode: out of memory\n"); | 1209 | printk(KERN_INFO "%s: out of memory\n", __func__); |
| 1203 | goto fail; | 1210 | goto fail; |
| 1204 | } | 1211 | } |
| 1205 | memcpy(tmpde, bh->b_data + offset, frag1); | 1212 | memcpy(tmpde, bh->b_data + offset, frag1); |
| @@ -1212,24 +1219,26 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1212 | } | 1219 | } |
| 1213 | 1220 | ||
| 1214 | inode->i_ino = isofs_get_ino(ei->i_iget5_block, | 1221 | inode->i_ino = isofs_get_ino(ei->i_iget5_block, |
| 1215 | ei->i_iget5_offset, | 1222 | ei->i_iget5_offset, |
| 1216 | ISOFS_BUFFER_BITS(inode)); | 1223 | ISOFS_BUFFER_BITS(inode)); |
| 1217 | 1224 | ||
| 1218 | /* Assume it is a normal-format file unless told otherwise */ | 1225 | /* Assume it is a normal-format file unless told otherwise */ |
| 1219 | ei->i_file_format = isofs_file_normal; | 1226 | ei->i_file_format = isofs_file_normal; |
| 1220 | 1227 | ||
| 1221 | if (de->flags[-high_sierra] & 2) { | 1228 | if (de->flags[-high_sierra] & 2) { |
| 1222 | inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; | 1229 | inode->i_mode = S_IRUGO | S_IXUGO | S_IFDIR; |
| 1223 | inode->i_nlink = 1; /* Set to 1. We know there are 2, but | 1230 | inode->i_nlink = 1; /* |
| 1224 | the find utility tries to optimize | 1231 | * Set to 1. We know there are 2, but |
| 1225 | if it is 2, and it screws up. It is | 1232 | * the find utility tries to optimize |
| 1226 | easier to give 1 which tells find to | 1233 | * if it is 2, and it screws up. It is |
| 1227 | do it the hard way. */ | 1234 | * easier to give 1 which tells find to |
| 1235 | * do it the hard way. | ||
| 1236 | */ | ||
| 1228 | } else { | 1237 | } else { |
| 1229 | /* Everybody gets to read the file. */ | 1238 | /* Everybody gets to read the file. */ |
| 1230 | inode->i_mode = sbi->s_mode; | 1239 | inode->i_mode = sbi->s_mode; |
| 1231 | inode->i_nlink = 1; | 1240 | inode->i_nlink = 1; |
| 1232 | inode->i_mode |= S_IFREG; | 1241 | inode->i_mode |= S_IFREG; |
| 1233 | } | 1242 | } |
| 1234 | inode->i_uid = sbi->s_uid; | 1243 | inode->i_uid = sbi->s_uid; |
| 1235 | inode->i_gid = sbi->s_gid; | 1244 | inode->i_gid = sbi->s_gid; |
| @@ -1239,13 +1248,14 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1239 | ei->i_format_parm[1] = 0; | 1248 | ei->i_format_parm[1] = 0; |
| 1240 | ei->i_format_parm[2] = 0; | 1249 | ei->i_format_parm[2] = 0; |
| 1241 | 1250 | ||
| 1242 | ei->i_section_size = isonum_733 (de->size); | 1251 | ei->i_section_size = isonum_733(de->size); |
| 1243 | if (de->flags[-high_sierra] & 0x80) { | 1252 | if (de->flags[-high_sierra] & 0x80) { |
| 1244 | if(isofs_read_level3_size(inode)) goto fail; | 1253 | if(isofs_read_level3_size(inode)) |
| 1254 | goto fail; | ||
| 1245 | } else { | 1255 | } else { |
| 1246 | ei->i_next_section_block = 0; | 1256 | ei->i_next_section_block = 0; |
| 1247 | ei->i_next_section_offset = 0; | 1257 | ei->i_next_section_offset = 0; |
| 1248 | inode->i_size = isonum_733 (de->size); | 1258 | inode->i_size = isonum_733(de->size); |
| 1249 | } | 1259 | } |
| 1250 | 1260 | ||
| 1251 | /* | 1261 | /* |
| @@ -1258,23 +1268,24 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1258 | inode->i_size &= 0x00ffffff; | 1268 | inode->i_size &= 0x00ffffff; |
| 1259 | 1269 | ||
| 1260 | if (de->interleave[0]) { | 1270 | if (de->interleave[0]) { |
| 1261 | printk("Interleaved files not (yet) supported.\n"); | 1271 | printk(KERN_DEBUG "ISOFS: Interleaved files not (yet) supported.\n"); |
| 1262 | inode->i_size = 0; | 1272 | inode->i_size = 0; |
| 1263 | } | 1273 | } |
| 1264 | 1274 | ||
| 1265 | /* I have no idea what file_unit_size is used for, so | 1275 | /* I have no idea what file_unit_size is used for, so |
| 1266 | we will flag it for now */ | 1276 | we will flag it for now */ |
| 1267 | if (de->file_unit_size[0] != 0) { | 1277 | if (de->file_unit_size[0] != 0) { |
| 1268 | printk("File unit size != 0 for ISO file (%ld).\n", | 1278 | printk(KERN_DEBUG "ISOFS: File unit size != 0 for ISO file (%ld).\n", |
| 1269 | inode->i_ino); | 1279 | inode->i_ino); |
| 1270 | } | 1280 | } |
| 1271 | 1281 | ||
| 1272 | /* I have no idea what other flag bits are used for, so | 1282 | /* I have no idea what other flag bits are used for, so |
| 1273 | we will flag it for now */ | 1283 | we will flag it for now */ |
| 1274 | #ifdef DEBUG | 1284 | #ifdef DEBUG |
| 1275 | if((de->flags[-high_sierra] & ~2)!= 0){ | 1285 | if((de->flags[-high_sierra] & ~2)!= 0){ |
| 1276 | printk("Unusual flag settings for ISO file (%ld %x).\n", | 1286 | printk(KERN_DEBUG "ISOFS: Unusual flag settings for ISO file " |
| 1277 | inode->i_ino, de->flags[-high_sierra]); | 1287 | "(%ld %x).\n", |
| 1288 | inode->i_ino, de->flags[-high_sierra]); | ||
| 1278 | } | 1289 | } |
| 1279 | #endif | 1290 | #endif |
| 1280 | 1291 | ||
| @@ -1285,11 +1296,11 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1285 | inode->i_atime.tv_nsec = | 1296 | inode->i_atime.tv_nsec = |
| 1286 | inode->i_ctime.tv_nsec = 0; | 1297 | inode->i_ctime.tv_nsec = 0; |
| 1287 | 1298 | ||
| 1288 | ei->i_first_extent = (isonum_733 (de->extent) + | 1299 | ei->i_first_extent = (isonum_733(de->extent) + |
| 1289 | isonum_711 (de->ext_attr_length)); | 1300 | isonum_711(de->ext_attr_length)); |
| 1290 | 1301 | ||
| 1291 | /* Set the number of blocks for stat() - should be done before RR */ | 1302 | /* Set the number of blocks for stat() - should be done before RR */ |
| 1292 | inode->i_blocks = (inode->i_size + 511) >> 9; | 1303 | inode->i_blocks = (inode->i_size + 511) >> 9; |
| 1293 | 1304 | ||
| 1294 | /* | 1305 | /* |
| 1295 | * Now test for possible Rock Ridge extensions which will override | 1306 | * Now test for possible Rock Ridge extensions which will override |
| @@ -1306,7 +1317,7 @@ static void isofs_read_inode(struct inode *inode) | |||
| 1306 | /* Install the inode operations vector */ | 1317 | /* Install the inode operations vector */ |
| 1307 | if (S_ISREG(inode->i_mode)) { | 1318 | if (S_ISREG(inode->i_mode)) { |
| 1308 | inode->i_fop = &generic_ro_fops; | 1319 | inode->i_fop = &generic_ro_fops; |
| 1309 | switch ( ei->i_file_format ) { | 1320 | switch (ei->i_file_format) { |
| 1310 | #ifdef CONFIG_ZISOFS | 1321 | #ifdef CONFIG_ZISOFS |
| 1311 | case isofs_file_compressed: | 1322 | case isofs_file_compressed: |
| 1312 | inode->i_data.a_ops = &zisofs_aops; | 1323 | inode->i_data.a_ops = &zisofs_aops; |
| @@ -1350,7 +1361,7 @@ static int isofs_iget5_test(struct inode *ino, void *data) | |||
| 1350 | struct isofs_iget5_callback_data *d = | 1361 | struct isofs_iget5_callback_data *d = |
| 1351 | (struct isofs_iget5_callback_data*)data; | 1362 | (struct isofs_iget5_callback_data*)data; |
| 1352 | return (i->i_iget5_block == d->block) | 1363 | return (i->i_iget5_block == d->block) |
| 1353 | && (i->i_iget5_offset == d->offset); | 1364 | && (i->i_iget5_offset == d->offset); |
| 1354 | } | 1365 | } |
| 1355 | 1366 | ||
| 1356 | static int isofs_iget5_set(struct inode *ino, void *data) | 1367 | static int isofs_iget5_set(struct inode *ino, void *data) |
| @@ -1384,7 +1395,7 @@ struct inode *isofs_iget(struct super_block *sb, | |||
| 1384 | hashval = (block << sb->s_blocksize_bits) | offset; | 1395 | hashval = (block << sb->s_blocksize_bits) | offset; |
| 1385 | 1396 | ||
| 1386 | inode = iget5_locked(sb, hashval, &isofs_iget5_test, | 1397 | inode = iget5_locked(sb, hashval, &isofs_iget5_test, |
| 1387 | &isofs_iget5_set, &data); | 1398 | &isofs_iget5_set, &data); |
| 1388 | 1399 | ||
| 1389 | if (inode && (inode->i_state & I_NEW)) { | 1400 | if (inode && (inode->i_state & I_NEW)) { |
| 1390 | sb->s_op->read_inode(inode); | 1401 | sb->s_op->read_inode(inode); |
| @@ -1398,7 +1409,7 @@ static int isofs_get_sb(struct file_system_type *fs_type, | |||
| 1398 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) | 1409 | int flags, const char *dev_name, void *data, struct vfsmount *mnt) |
| 1399 | { | 1410 | { |
| 1400 | return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, | 1411 | return get_sb_bdev(fs_type, flags, dev_name, data, isofs_fill_super, |
| 1401 | mnt); | 1412 | mnt); |
| 1402 | } | 1413 | } |
| 1403 | 1414 | ||
| 1404 | static struct file_system_type iso9660_fs_type = { | 1415 | static struct file_system_type iso9660_fs_type = { |
diff --git a/fs/isofs/joliet.c b/fs/isofs/joliet.c index fb8fe7a9ddc6..92c14b850e9c 100644 --- a/fs/isofs/joliet.c +++ b/fs/isofs/joliet.c | |||
| @@ -80,22 +80,20 @@ get_joliet_filename(struct iso_directory_record * de, unsigned char *outname, st | |||
| 80 | 80 | ||
| 81 | if (utf8) { | 81 | if (utf8) { |
| 82 | len = wcsntombs_be(outname, de->name, | 82 | len = wcsntombs_be(outname, de->name, |
| 83 | de->name_len[0] >> 1, PAGE_SIZE); | 83 | de->name_len[0] >> 1, PAGE_SIZE); |
| 84 | } else { | 84 | } else { |
| 85 | len = uni16_to_x8(outname, (__be16 *) de->name, | 85 | len = uni16_to_x8(outname, (__be16 *) de->name, |
| 86 | de->name_len[0] >> 1, nls); | 86 | de->name_len[0] >> 1, nls); |
| 87 | } | 87 | } |
| 88 | if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) { | 88 | if ((len > 2) && (outname[len-2] == ';') && (outname[len-1] == '1')) |
| 89 | len -= 2; | 89 | len -= 2; |
| 90 | } | ||
| 91 | 90 | ||
| 92 | /* | 91 | /* |
| 93 | * Windows doesn't like periods at the end of a name, | 92 | * Windows doesn't like periods at the end of a name, |
| 94 | * so neither do we | 93 | * so neither do we |
| 95 | */ | 94 | */ |
| 96 | while (len >= 2 && (outname[len-1] == '.')) { | 95 | while (len >= 2 && (outname[len-1] == '.')) |
| 97 | len--; | 96 | len--; |
| 98 | } | ||
| 99 | 97 | ||
| 100 | return len; | 98 | return len; |
| 101 | } | 99 | } |
diff --git a/fs/isofs/namei.c b/fs/isofs/namei.c index c04b3a14a3e9..c8c7e5138a01 100644 --- a/fs/isofs/namei.c +++ b/fs/isofs/namei.c | |||
| @@ -15,7 +15,7 @@ | |||
| 15 | * some sanity tests. | 15 | * some sanity tests. |
| 16 | */ | 16 | */ |
| 17 | static int | 17 | static int |
| 18 | isofs_cmp(struct dentry * dentry, const char * compare, int dlen) | 18 | isofs_cmp(struct dentry *dentry, const char *compare, int dlen) |
| 19 | { | 19 | { |
| 20 | struct qstr qstr; | 20 | struct qstr qstr; |
| 21 | 21 | ||
| @@ -48,24 +48,24 @@ isofs_cmp(struct dentry * dentry, const char * compare, int dlen) | |||
| 48 | */ | 48 | */ |
| 49 | static unsigned long | 49 | static unsigned long |
| 50 | isofs_find_entry(struct inode *dir, struct dentry *dentry, | 50 | isofs_find_entry(struct inode *dir, struct dentry *dentry, |
| 51 | unsigned long *block_rv, unsigned long* offset_rv, | 51 | unsigned long *block_rv, unsigned long *offset_rv, |
| 52 | char * tmpname, struct iso_directory_record * tmpde) | 52 | char *tmpname, struct iso_directory_record *tmpde) |
| 53 | { | 53 | { |
| 54 | unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); | 54 | unsigned long bufsize = ISOFS_BUFFER_SIZE(dir); |
| 55 | unsigned char bufbits = ISOFS_BUFFER_BITS(dir); | 55 | unsigned char bufbits = ISOFS_BUFFER_BITS(dir); |
| 56 | unsigned long block, f_pos, offset, block_saved, offset_saved; | 56 | unsigned long block, f_pos, offset, block_saved, offset_saved; |
| 57 | struct buffer_head * bh = NULL; | 57 | struct buffer_head *bh = NULL; |
| 58 | struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb); | 58 | struct isofs_sb_info *sbi = ISOFS_SB(dir->i_sb); |
| 59 | 59 | ||
| 60 | if (!ISOFS_I(dir)->i_first_extent) | 60 | if (!ISOFS_I(dir)->i_first_extent) |
| 61 | return 0; | 61 | return 0; |
| 62 | 62 | ||
| 63 | f_pos = 0; | 63 | f_pos = 0; |
| 64 | offset = 0; | 64 | offset = 0; |
| 65 | block = 0; | 65 | block = 0; |
| 66 | 66 | ||
| 67 | while (f_pos < dir->i_size) { | 67 | while (f_pos < dir->i_size) { |
| 68 | struct iso_directory_record * de; | 68 | struct iso_directory_record *de; |
| 69 | int de_len, match, i, dlen; | 69 | int de_len, match, i, dlen; |
| 70 | char *dpnt; | 70 | char *dpnt; |
| 71 | 71 | ||
| @@ -114,7 +114,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, | |||
| 114 | 114 | ||
| 115 | if (sbi->s_rock && | 115 | if (sbi->s_rock && |
| 116 | ((i = get_rock_ridge_filename(de, tmpname, dir)))) { | 116 | ((i = get_rock_ridge_filename(de, tmpname, dir)))) { |
| 117 | dlen = i; /* possibly -1 */ | 117 | dlen = i; /* possibly -1 */ |
| 118 | dpnt = tmpname; | 118 | dpnt = tmpname; |
| 119 | #ifdef CONFIG_JOLIET | 119 | #ifdef CONFIG_JOLIET |
| 120 | } else if (sbi->s_joliet_level) { | 120 | } else if (sbi->s_joliet_level) { |
| @@ -145,8 +145,8 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, | |||
| 145 | isofs_normalize_block_and_offset(de, | 145 | isofs_normalize_block_and_offset(de, |
| 146 | &block_saved, | 146 | &block_saved, |
| 147 | &offset_saved); | 147 | &offset_saved); |
| 148 | *block_rv = block_saved; | 148 | *block_rv = block_saved; |
| 149 | *offset_rv = offset_saved; | 149 | *offset_rv = offset_saved; |
| 150 | brelse(bh); | 150 | brelse(bh); |
| 151 | return 1; | 151 | return 1; |
| 152 | } | 152 | } |
| @@ -155,7 +155,7 @@ isofs_find_entry(struct inode *dir, struct dentry *dentry, | |||
| 155 | return 0; | 155 | return 0; |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct nameidata *nd) | 158 | struct dentry *isofs_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd) |
| 159 | { | 159 | { |
| 160 | int found; | 160 | int found; |
| 161 | unsigned long block, offset; | 161 | unsigned long block, offset; |
| @@ -170,9 +170,9 @@ struct dentry *isofs_lookup(struct inode * dir, struct dentry * dentry, struct n | |||
| 170 | 170 | ||
| 171 | lock_kernel(); | 171 | lock_kernel(); |
| 172 | found = isofs_find_entry(dir, dentry, | 172 | found = isofs_find_entry(dir, dentry, |
| 173 | &block, &offset, | 173 | &block, &offset, |
| 174 | page_address(page), | 174 | page_address(page), |
| 175 | 1024 + page_address(page)); | 175 | 1024 + page_address(page)); |
| 176 | __free_page(page); | 176 | __free_page(page); |
| 177 | 177 | ||
| 178 | inode = NULL; | 178 | inode = NULL; |
diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index 1facfaff97cb..a003d50edcdb 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c | |||
| @@ -887,7 +887,8 @@ restart_loop: | |||
| 887 | journal->j_committing_transaction = NULL; | 887 | journal->j_committing_transaction = NULL; |
| 888 | spin_unlock(&journal->j_state_lock); | 888 | spin_unlock(&journal->j_state_lock); |
| 889 | 889 | ||
| 890 | if (commit_transaction->t_checkpoint_list == NULL) { | 890 | if (commit_transaction->t_checkpoint_list == NULL && |
| 891 | commit_transaction->t_checkpoint_io_list == NULL) { | ||
| 891 | __journal_drop_transaction(journal, commit_transaction); | 892 | __journal_drop_transaction(journal, commit_transaction); |
| 892 | } else { | 893 | } else { |
| 893 | if (journal->j_checkpoint_transactions == NULL) { | 894 | if (journal->j_checkpoint_transactions == NULL) { |
diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index 824e3b7d4ec1..8db2fa25170b 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #include <linux/list.h> | 68 | #include <linux/list.h> |
| 69 | #include <linux/init.h> | 69 | #include <linux/init.h> |
| 70 | #endif | 70 | #endif |
| 71 | #include <linux/log2.h> | ||
| 71 | 72 | ||
| 72 | static struct kmem_cache *revoke_record_cache; | 73 | static struct kmem_cache *revoke_record_cache; |
| 73 | static struct kmem_cache *revoke_table_cache; | 74 | static struct kmem_cache *revoke_table_cache; |
| @@ -211,7 +212,7 @@ int journal_init_revoke(journal_t *journal, int hash_size) | |||
| 211 | journal->j_revoke = journal->j_revoke_table[0]; | 212 | journal->j_revoke = journal->j_revoke_table[0]; |
| 212 | 213 | ||
| 213 | /* Check that the hash_size is a power of two */ | 214 | /* Check that the hash_size is a power of two */ |
| 214 | J_ASSERT ((hash_size & (hash_size-1)) == 0); | 215 | J_ASSERT(is_power_of_2(hash_size)); |
| 215 | 216 | ||
| 216 | journal->j_revoke->hash_size = hash_size; | 217 | journal->j_revoke->hash_size = hash_size; |
| 217 | 218 | ||
| @@ -238,7 +239,7 @@ int journal_init_revoke(journal_t *journal, int hash_size) | |||
| 238 | journal->j_revoke = journal->j_revoke_table[1]; | 239 | journal->j_revoke = journal->j_revoke_table[1]; |
| 239 | 240 | ||
| 240 | /* Check that the hash_size is a power of two */ | 241 | /* Check that the hash_size is a power of two */ |
| 241 | J_ASSERT ((hash_size & (hash_size-1)) == 0); | 242 | J_ASSERT(is_power_of_2(hash_size)); |
| 242 | 243 | ||
| 243 | journal->j_revoke->hash_size = hash_size; | 244 | journal->j_revoke->hash_size = hash_size; |
| 244 | 245 | ||
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c index 2856e1100a5f..c0f59d1b13dc 100644 --- a/fs/jbd2/commit.c +++ b/fs/jbd2/commit.c | |||
| @@ -896,7 +896,8 @@ restart_loop: | |||
| 896 | journal->j_committing_transaction = NULL; | 896 | journal->j_committing_transaction = NULL; |
| 897 | spin_unlock(&journal->j_state_lock); | 897 | spin_unlock(&journal->j_state_lock); |
| 898 | 898 | ||
| 899 | if (commit_transaction->t_checkpoint_list == NULL) { | 899 | if (commit_transaction->t_checkpoint_list == NULL && |
| 900 | commit_transaction->t_checkpoint_io_list == NULL) { | ||
| 900 | __jbd2_journal_drop_transaction(journal, commit_transaction); | 901 | __jbd2_journal_drop_transaction(journal, commit_transaction); |
| 901 | } else { | 902 | } else { |
| 902 | if (journal->j_checkpoint_transactions == NULL) { | 903 | if (journal->j_checkpoint_transactions == NULL) { |
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c index 9246e763da78..28cac049a56b 100644 --- a/fs/jbd2/revoke.c +++ b/fs/jbd2/revoke.c | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #include <linux/list.h> | 68 | #include <linux/list.h> |
| 69 | #include <linux/init.h> | 69 | #include <linux/init.h> |
| 70 | #endif | 70 | #endif |
| 71 | #include <linux/log2.h> | ||
| 71 | 72 | ||
| 72 | static struct kmem_cache *jbd2_revoke_record_cache; | 73 | static struct kmem_cache *jbd2_revoke_record_cache; |
| 73 | static struct kmem_cache *jbd2_revoke_table_cache; | 74 | static struct kmem_cache *jbd2_revoke_table_cache; |
| @@ -212,7 +213,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | |||
| 212 | journal->j_revoke = journal->j_revoke_table[0]; | 213 | journal->j_revoke = journal->j_revoke_table[0]; |
| 213 | 214 | ||
| 214 | /* Check that the hash_size is a power of two */ | 215 | /* Check that the hash_size is a power of two */ |
| 215 | J_ASSERT ((hash_size & (hash_size-1)) == 0); | 216 | J_ASSERT(is_power_of_2(hash_size)); |
| 216 | 217 | ||
| 217 | journal->j_revoke->hash_size = hash_size; | 218 | journal->j_revoke->hash_size = hash_size; |
| 218 | 219 | ||
| @@ -239,7 +240,7 @@ int jbd2_journal_init_revoke(journal_t *journal, int hash_size) | |||
| 239 | journal->j_revoke = journal->j_revoke_table[1]; | 240 | journal->j_revoke = journal->j_revoke_table[1]; |
| 240 | 241 | ||
| 241 | /* Check that the hash_size is a power of two */ | 242 | /* Check that the hash_size is a power of two */ |
| 242 | J_ASSERT ((hash_size & (hash_size-1)) == 0); | 243 | J_ASSERT(is_power_of_2(hash_size)); |
| 243 | 244 | ||
| 244 | journal->j_revoke->hash_size = hash_size; | 245 | journal->j_revoke->hash_size = hash_size; |
| 245 | 246 | ||
diff --git a/fs/namespace.c b/fs/namespace.c index b696e3a0d18f..4198003d7e18 100644 --- a/fs/namespace.c +++ b/fs/namespace.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <asm/uaccess.h> | 28 | #include <asm/uaccess.h> |
| 29 | #include <asm/unistd.h> | 29 | #include <asm/unistd.h> |
| 30 | #include "pnode.h" | 30 | #include "pnode.h" |
| 31 | #include "internal.h" | ||
| 31 | 32 | ||
| 32 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ | 33 | /* spinlock for vfsmount related operations, inplace of dcache_lock */ |
| 33 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); | 34 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(vfsmount_lock); |
| @@ -320,22 +321,16 @@ EXPORT_SYMBOL(mnt_unpin); | |||
| 320 | static void *m_start(struct seq_file *m, loff_t *pos) | 321 | static void *m_start(struct seq_file *m, loff_t *pos) |
| 321 | { | 322 | { |
| 322 | struct mnt_namespace *n = m->private; | 323 | struct mnt_namespace *n = m->private; |
| 323 | struct list_head *p; | ||
| 324 | loff_t l = *pos; | ||
| 325 | 324 | ||
| 326 | down_read(&namespace_sem); | 325 | down_read(&namespace_sem); |
| 327 | list_for_each(p, &n->list) | 326 | return seq_list_start(&n->list, *pos); |
| 328 | if (!l--) | ||
| 329 | return list_entry(p, struct vfsmount, mnt_list); | ||
| 330 | return NULL; | ||
| 331 | } | 327 | } |
| 332 | 328 | ||
| 333 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) | 329 | static void *m_next(struct seq_file *m, void *v, loff_t *pos) |
| 334 | { | 330 | { |
| 335 | struct mnt_namespace *n = m->private; | 331 | struct mnt_namespace *n = m->private; |
| 336 | struct list_head *p = ((struct vfsmount *)v)->mnt_list.next; | 332 | |
| 337 | (*pos)++; | 333 | return seq_list_next(v, &n->list, pos); |
| 338 | return p == &n->list ? NULL : list_entry(p, struct vfsmount, mnt_list); | ||
| 339 | } | 334 | } |
| 340 | 335 | ||
| 341 | static void m_stop(struct seq_file *m, void *v) | 336 | static void m_stop(struct seq_file *m, void *v) |
| @@ -350,7 +345,7 @@ static inline void mangle(struct seq_file *m, const char *s) | |||
| 350 | 345 | ||
| 351 | static int show_vfsmnt(struct seq_file *m, void *v) | 346 | static int show_vfsmnt(struct seq_file *m, void *v) |
| 352 | { | 347 | { |
| 353 | struct vfsmount *mnt = v; | 348 | struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); |
| 354 | int err = 0; | 349 | int err = 0; |
| 355 | static struct proc_fs_info { | 350 | static struct proc_fs_info { |
| 356 | int flag; | 351 | int flag; |
| @@ -405,7 +400,7 @@ struct seq_operations mounts_op = { | |||
| 405 | 400 | ||
| 406 | static int show_vfsstat(struct seq_file *m, void *v) | 401 | static int show_vfsstat(struct seq_file *m, void *v) |
| 407 | { | 402 | { |
| 408 | struct vfsmount *mnt = v; | 403 | struct vfsmount *mnt = list_entry(v, struct vfsmount, mnt_list); |
| 409 | int err = 0; | 404 | int err = 0; |
| 410 | 405 | ||
| 411 | /* device */ | 406 | /* device */ |
| @@ -1457,7 +1452,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
| 1457 | 1452 | ||
| 1458 | new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); | 1453 | new_ns = kmalloc(sizeof(struct mnt_namespace), GFP_KERNEL); |
| 1459 | if (!new_ns) | 1454 | if (!new_ns) |
| 1460 | return NULL; | 1455 | return ERR_PTR(-ENOMEM); |
| 1461 | 1456 | ||
| 1462 | atomic_set(&new_ns->count, 1); | 1457 | atomic_set(&new_ns->count, 1); |
| 1463 | INIT_LIST_HEAD(&new_ns->list); | 1458 | INIT_LIST_HEAD(&new_ns->list); |
| @@ -1471,7 +1466,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
| 1471 | if (!new_ns->root) { | 1466 | if (!new_ns->root) { |
| 1472 | up_write(&namespace_sem); | 1467 | up_write(&namespace_sem); |
| 1473 | kfree(new_ns); | 1468 | kfree(new_ns); |
| 1474 | return NULL; | 1469 | return ERR_PTR(-ENOMEM);; |
| 1475 | } | 1470 | } |
| 1476 | spin_lock(&vfsmount_lock); | 1471 | spin_lock(&vfsmount_lock); |
| 1477 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); | 1472 | list_add_tail(&new_ns->list, &new_ns->root->mnt_list); |
| @@ -1515,7 +1510,7 @@ static struct mnt_namespace *dup_mnt_ns(struct mnt_namespace *mnt_ns, | |||
| 1515 | return new_ns; | 1510 | return new_ns; |
| 1516 | } | 1511 | } |
| 1517 | 1512 | ||
| 1518 | struct mnt_namespace *copy_mnt_ns(int flags, struct mnt_namespace *ns, | 1513 | struct mnt_namespace *copy_mnt_ns(unsigned long flags, struct mnt_namespace *ns, |
| 1519 | struct fs_struct *new_fs) | 1514 | struct fs_struct *new_fs) |
| 1520 | { | 1515 | { |
| 1521 | struct mnt_namespace *new_ns; | 1516 | struct mnt_namespace *new_ns; |
diff --git a/fs/ncpfs/file.c b/fs/ncpfs/file.c index d3152f8d95c6..2b145de45b39 100644 --- a/fs/ncpfs/file.c +++ b/fs/ncpfs/file.c | |||
| @@ -203,7 +203,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
| 203 | 203 | ||
| 204 | if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { | 204 | if (pos + count > MAX_NON_LFS && !(file->f_flags&O_LARGEFILE)) { |
| 205 | if (pos >= MAX_NON_LFS) { | 205 | if (pos >= MAX_NON_LFS) { |
| 206 | send_sig(SIGXFSZ, current, 0); | ||
| 207 | return -EFBIG; | 206 | return -EFBIG; |
| 208 | } | 207 | } |
| 209 | if (count > MAX_NON_LFS - (u32)pos) { | 208 | if (count > MAX_NON_LFS - (u32)pos) { |
| @@ -212,7 +211,6 @@ ncp_file_write(struct file *file, const char __user *buf, size_t count, loff_t * | |||
| 212 | } | 211 | } |
| 213 | if (pos >= inode->i_sb->s_maxbytes) { | 212 | if (pos >= inode->i_sb->s_maxbytes) { |
| 214 | if (count || pos > inode->i_sb->s_maxbytes) { | 213 | if (count || pos > inode->i_sb->s_maxbytes) { |
| 215 | send_sig(SIGXFSZ, current, 0); | ||
| 216 | return -EFBIG; | 214 | return -EFBIG; |
| 217 | } | 215 | } |
| 218 | } | 216 | } |
diff --git a/fs/nfs/client.c b/fs/nfs/client.c index ccb455053ee4..a49f9feff776 100644 --- a/fs/nfs/client.c +++ b/fs/nfs/client.c | |||
| @@ -1206,23 +1206,9 @@ static int nfs_server_list_open(struct inode *inode, struct file *file) | |||
| 1206 | */ | 1206 | */ |
| 1207 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | 1207 | static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) |
| 1208 | { | 1208 | { |
| 1209 | struct list_head *_p; | ||
| 1210 | loff_t pos = *_pos; | ||
| 1211 | |||
| 1212 | /* lock the list against modification */ | 1209 | /* lock the list against modification */ |
| 1213 | spin_lock(&nfs_client_lock); | 1210 | spin_lock(&nfs_client_lock); |
| 1214 | 1211 | return seq_list_start_head(&nfs_client_list, *_pos); | |
| 1215 | /* allow for the header line */ | ||
| 1216 | if (!pos) | ||
| 1217 | return SEQ_START_TOKEN; | ||
| 1218 | pos--; | ||
| 1219 | |||
| 1220 | /* find the n'th element in the list */ | ||
| 1221 | list_for_each(_p, &nfs_client_list) | ||
| 1222 | if (!pos--) | ||
| 1223 | break; | ||
| 1224 | |||
| 1225 | return _p != &nfs_client_list ? _p : NULL; | ||
| 1226 | } | 1212 | } |
| 1227 | 1213 | ||
| 1228 | /* | 1214 | /* |
| @@ -1230,14 +1216,7 @@ static void *nfs_server_list_start(struct seq_file *m, loff_t *_pos) | |||
| 1230 | */ | 1216 | */ |
| 1231 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) | 1217 | static void *nfs_server_list_next(struct seq_file *p, void *v, loff_t *pos) |
| 1232 | { | 1218 | { |
| 1233 | struct list_head *_p; | 1219 | return seq_list_next(v, &nfs_client_list, pos); |
| 1234 | |||
| 1235 | (*pos)++; | ||
| 1236 | |||
| 1237 | _p = v; | ||
| 1238 | _p = (v == SEQ_START_TOKEN) ? nfs_client_list.next : _p->next; | ||
| 1239 | |||
| 1240 | return _p != &nfs_client_list ? _p : NULL; | ||
| 1241 | } | 1220 | } |
| 1242 | 1221 | ||
| 1243 | /* | 1222 | /* |
| @@ -1256,7 +1235,7 @@ static int nfs_server_list_show(struct seq_file *m, void *v) | |||
| 1256 | struct nfs_client *clp; | 1235 | struct nfs_client *clp; |
| 1257 | 1236 | ||
| 1258 | /* display header on line 1 */ | 1237 | /* display header on line 1 */ |
| 1259 | if (v == SEQ_START_TOKEN) { | 1238 | if (v == &nfs_client_list) { |
| 1260 | seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); | 1239 | seq_puts(m, "NV SERVER PORT USE HOSTNAME\n"); |
| 1261 | return 0; | 1240 | return 0; |
| 1262 | } | 1241 | } |
| @@ -1297,23 +1276,9 @@ static int nfs_volume_list_open(struct inode *inode, struct file *file) | |||
| 1297 | */ | 1276 | */ |
| 1298 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | 1277 | static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) |
| 1299 | { | 1278 | { |
| 1300 | struct list_head *_p; | ||
| 1301 | loff_t pos = *_pos; | ||
| 1302 | |||
| 1303 | /* lock the list against modification */ | 1279 | /* lock the list against modification */ |
| 1304 | spin_lock(&nfs_client_lock); | 1280 | spin_lock(&nfs_client_lock); |
| 1305 | 1281 | return seq_list_start_head(&nfs_volume_list, *_pos); | |
| 1306 | /* allow for the header line */ | ||
| 1307 | if (!pos) | ||
| 1308 | return SEQ_START_TOKEN; | ||
| 1309 | pos--; | ||
| 1310 | |||
| 1311 | /* find the n'th element in the list */ | ||
| 1312 | list_for_each(_p, &nfs_volume_list) | ||
| 1313 | if (!pos--) | ||
| 1314 | break; | ||
| 1315 | |||
| 1316 | return _p != &nfs_volume_list ? _p : NULL; | ||
| 1317 | } | 1282 | } |
| 1318 | 1283 | ||
| 1319 | /* | 1284 | /* |
| @@ -1321,14 +1286,7 @@ static void *nfs_volume_list_start(struct seq_file *m, loff_t *_pos) | |||
| 1321 | */ | 1286 | */ |
| 1322 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) | 1287 | static void *nfs_volume_list_next(struct seq_file *p, void *v, loff_t *pos) |
| 1323 | { | 1288 | { |
| 1324 | struct list_head *_p; | 1289 | return seq_list_next(v, &nfs_volume_list, pos); |
| 1325 | |||
| 1326 | (*pos)++; | ||
| 1327 | |||
| 1328 | _p = v; | ||
| 1329 | _p = (v == SEQ_START_TOKEN) ? nfs_volume_list.next : _p->next; | ||
| 1330 | |||
| 1331 | return _p != &nfs_volume_list ? _p : NULL; | ||
| 1332 | } | 1290 | } |
| 1333 | 1291 | ||
| 1334 | /* | 1292 | /* |
| @@ -1349,7 +1307,7 @@ static int nfs_volume_list_show(struct seq_file *m, void *v) | |||
| 1349 | char dev[8], fsid[17]; | 1307 | char dev[8], fsid[17]; |
| 1350 | 1308 | ||
| 1351 | /* display header on line 1 */ | 1309 | /* display header on line 1 */ |
| 1352 | if (v == SEQ_START_TOKEN) { | 1310 | if (v == &nfs_volume_list) { |
| 1353 | seq_puts(m, "NV SERVER PORT DEV FSID\n"); | 1311 | seq_puts(m, "NV SERVER PORT DEV FSID\n"); |
| 1354 | return 0; | 1312 | return 0; |
| 1355 | } | 1313 | } |
diff --git a/fs/nls/Makefile b/fs/nls/Makefile index a7ade138d684..f499dd7c3905 100644 --- a/fs/nls/Makefile +++ b/fs/nls/Makefile | |||
| @@ -36,11 +36,9 @@ obj-$(CONFIG_NLS_ISO8859_6) += nls_iso8859-6.o | |||
| 36 | obj-$(CONFIG_NLS_ISO8859_7) += nls_iso8859-7.o | 36 | obj-$(CONFIG_NLS_ISO8859_7) += nls_iso8859-7.o |
| 37 | obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o | 37 | obj-$(CONFIG_NLS_ISO8859_8) += nls_cp1255.o |
| 38 | obj-$(CONFIG_NLS_ISO8859_9) += nls_iso8859-9.o | 38 | obj-$(CONFIG_NLS_ISO8859_9) += nls_iso8859-9.o |
| 39 | obj-$(CONFIG_NLS_ISO8859_10) += nls_iso8859-10.o | ||
| 40 | obj-$(CONFIG_NLS_ISO8859_13) += nls_iso8859-13.o | 39 | obj-$(CONFIG_NLS_ISO8859_13) += nls_iso8859-13.o |
| 41 | obj-$(CONFIG_NLS_ISO8859_14) += nls_iso8859-14.o | 40 | obj-$(CONFIG_NLS_ISO8859_14) += nls_iso8859-14.o |
| 42 | obj-$(CONFIG_NLS_ISO8859_15) += nls_iso8859-15.o | 41 | obj-$(CONFIG_NLS_ISO8859_15) += nls_iso8859-15.o |
| 43 | obj-$(CONFIG_NLS_KOI8_R) += nls_koi8-r.o | 42 | obj-$(CONFIG_NLS_KOI8_R) += nls_koi8-r.o |
| 44 | obj-$(CONFIG_NLS_KOI8_U) += nls_koi8-u.o nls_koi8-ru.o | 43 | obj-$(CONFIG_NLS_KOI8_U) += nls_koi8-u.o nls_koi8-ru.o |
| 45 | obj-$(CONFIG_NLS_ABC) += nls_abc.o | ||
| 46 | obj-$(CONFIG_NLS_UTF8) += nls_utf8.o | 44 | obj-$(CONFIG_NLS_UTF8) += nls_utf8.o |
| @@ -855,7 +855,7 @@ EXPORT_SYMBOL(dentry_open); | |||
| 855 | /* | 855 | /* |
| 856 | * Find an empty file descriptor entry, and mark it busy. | 856 | * Find an empty file descriptor entry, and mark it busy. |
| 857 | */ | 857 | */ |
| 858 | int get_unused_fd(void) | 858 | int get_unused_fd_flags(int flags) |
| 859 | { | 859 | { |
| 860 | struct files_struct * files = current->files; | 860 | struct files_struct * files = current->files; |
| 861 | int fd, error; | 861 | int fd, error; |
| @@ -891,7 +891,10 @@ repeat: | |||
| 891 | } | 891 | } |
| 892 | 892 | ||
| 893 | FD_SET(fd, fdt->open_fds); | 893 | FD_SET(fd, fdt->open_fds); |
| 894 | FD_CLR(fd, fdt->close_on_exec); | 894 | if (flags & O_CLOEXEC) |
| 895 | FD_SET(fd, fdt->close_on_exec); | ||
| 896 | else | ||
| 897 | FD_CLR(fd, fdt->close_on_exec); | ||
| 895 | files->next_fd = fd + 1; | 898 | files->next_fd = fd + 1; |
| 896 | #if 1 | 899 | #if 1 |
| 897 | /* Sanity check */ | 900 | /* Sanity check */ |
| @@ -907,6 +910,11 @@ out: | |||
| 907 | return error; | 910 | return error; |
| 908 | } | 911 | } |
| 909 | 912 | ||
| 913 | int get_unused_fd(void) | ||
| 914 | { | ||
| 915 | return get_unused_fd_flags(0); | ||
| 916 | } | ||
| 917 | |||
| 910 | EXPORT_SYMBOL(get_unused_fd); | 918 | EXPORT_SYMBOL(get_unused_fd); |
| 911 | 919 | ||
| 912 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) | 920 | static void __put_unused_fd(struct files_struct *files, unsigned int fd) |
| @@ -959,7 +967,7 @@ long do_sys_open(int dfd, const char __user *filename, int flags, int mode) | |||
| 959 | int fd = PTR_ERR(tmp); | 967 | int fd = PTR_ERR(tmp); |
| 960 | 968 | ||
| 961 | if (!IS_ERR(tmp)) { | 969 | if (!IS_ERR(tmp)) { |
| 962 | fd = get_unused_fd(); | 970 | fd = get_unused_fd_flags(flags); |
| 963 | if (fd >= 0) { | 971 | if (fd >= 0) { |
| 964 | struct file *f = do_filp_open(dfd, tmp, flags, mode); | 972 | struct file *f = do_filp_open(dfd, tmp, flags, mode); |
| 965 | if (IS_ERR(f)) { | 973 | if (IS_ERR(f)) { |
diff --git a/fs/partitions/acorn.c b/fs/partitions/acorn.c index e3491328596b..3d3e16631472 100644 --- a/fs/partitions/acorn.c +++ b/fs/partitions/acorn.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #define PARTITION_RISCIX_SCSI 2 | 25 | #define PARTITION_RISCIX_SCSI 2 |
| 26 | #define PARTITION_LINUX 9 | 26 | #define PARTITION_LINUX 9 |
| 27 | 27 | ||
| 28 | #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ | ||
| 29 | defined(CONFIG_ACORN_PARTITION_ADFS) | ||
| 28 | static struct adfs_discrecord * | 30 | static struct adfs_discrecord * |
| 29 | adfs_partition(struct parsed_partitions *state, char *name, char *data, | 31 | adfs_partition(struct parsed_partitions *state, char *name, char *data, |
| 30 | unsigned long first_sector, int slot) | 32 | unsigned long first_sector, int slot) |
| @@ -48,6 +50,7 @@ adfs_partition(struct parsed_partitions *state, char *name, char *data, | |||
| 48 | put_partition(state, slot, first_sector, nr_sects); | 50 | put_partition(state, slot, first_sector, nr_sects); |
| 49 | return dr; | 51 | return dr; |
| 50 | } | 52 | } |
| 53 | #endif | ||
| 51 | 54 | ||
| 52 | #ifdef CONFIG_ACORN_PARTITION_RISCIX | 55 | #ifdef CONFIG_ACORN_PARTITION_RISCIX |
| 53 | 56 | ||
| @@ -65,6 +68,8 @@ struct riscix_record { | |||
| 65 | struct riscix_part part[8]; | 68 | struct riscix_part part[8]; |
| 66 | }; | 69 | }; |
| 67 | 70 | ||
| 71 | #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ | ||
| 72 | defined(CONFIG_ACORN_PARTITION_ADFS) | ||
| 68 | static int | 73 | static int |
| 69 | riscix_partition(struct parsed_partitions *state, struct block_device *bdev, | 74 | riscix_partition(struct parsed_partitions *state, struct block_device *bdev, |
| 70 | unsigned long first_sect, int slot, unsigned long nr_sects) | 75 | unsigned long first_sect, int slot, unsigned long nr_sects) |
| @@ -105,6 +110,7 @@ riscix_partition(struct parsed_partitions *state, struct block_device *bdev, | |||
| 105 | return slot; | 110 | return slot; |
| 106 | } | 111 | } |
| 107 | #endif | 112 | #endif |
| 113 | #endif | ||
| 108 | 114 | ||
| 109 | #define LINUX_NATIVE_MAGIC 0xdeafa1de | 115 | #define LINUX_NATIVE_MAGIC 0xdeafa1de |
| 110 | #define LINUX_SWAP_MAGIC 0xdeafab1e | 116 | #define LINUX_SWAP_MAGIC 0xdeafab1e |
| @@ -115,6 +121,8 @@ struct linux_part { | |||
| 115 | __le32 nr_sects; | 121 | __le32 nr_sects; |
| 116 | }; | 122 | }; |
| 117 | 123 | ||
| 124 | #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \ | ||
| 125 | defined(CONFIG_ACORN_PARTITION_ADFS) | ||
| 118 | static int | 126 | static int |
| 119 | linux_partition(struct parsed_partitions *state, struct block_device *bdev, | 127 | linux_partition(struct parsed_partitions *state, struct block_device *bdev, |
| 120 | unsigned long first_sect, int slot, unsigned long nr_sects) | 128 | unsigned long first_sect, int slot, unsigned long nr_sects) |
| @@ -146,6 +154,7 @@ linux_partition(struct parsed_partitions *state, struct block_device *bdev, | |||
| 146 | put_dev_sector(sect); | 154 | put_dev_sector(sect); |
| 147 | return slot; | 155 | return slot; |
| 148 | } | 156 | } |
| 157 | #endif | ||
| 149 | 158 | ||
| 150 | #ifdef CONFIG_ACORN_PARTITION_CUMANA | 159 | #ifdef CONFIG_ACORN_PARTITION_CUMANA |
| 151 | int | 160 | int |
diff --git a/fs/proc/array.c b/fs/proc/array.c index 98e78e2f18d6..9cbab7e93557 100644 --- a/fs/proc/array.c +++ b/fs/proc/array.c | |||
| @@ -289,6 +289,15 @@ static inline char *task_cap(struct task_struct *p, char *buffer) | |||
| 289 | cap_t(p->cap_effective)); | 289 | cap_t(p->cap_effective)); |
| 290 | } | 290 | } |
| 291 | 291 | ||
| 292 | static inline char *task_context_switch_counts(struct task_struct *p, | ||
| 293 | char *buffer) | ||
| 294 | { | ||
| 295 | return buffer + sprintf(buffer, "voluntary_ctxt_switches:\t%lu\n" | ||
| 296 | "nonvoluntary_ctxt_switches:\t%lu\n", | ||
| 297 | p->nvcsw, | ||
| 298 | p->nivcsw); | ||
| 299 | } | ||
| 300 | |||
| 292 | int proc_pid_status(struct task_struct *task, char * buffer) | 301 | int proc_pid_status(struct task_struct *task, char * buffer) |
| 293 | { | 302 | { |
| 294 | char * orig = buffer; | 303 | char * orig = buffer; |
| @@ -307,6 +316,7 @@ int proc_pid_status(struct task_struct *task, char * buffer) | |||
| 307 | #if defined(CONFIG_S390) | 316 | #if defined(CONFIG_S390) |
| 308 | buffer = task_show_regs(task, buffer); | 317 | buffer = task_show_regs(task, buffer); |
| 309 | #endif | 318 | #endif |
| 319 | buffer = task_context_switch_counts(task, buffer); | ||
| 310 | return buffer - orig; | 320 | return buffer - orig; |
| 311 | } | 321 | } |
| 312 | 322 | ||
| @@ -440,8 +450,9 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole) | |||
| 440 | 450 | ||
| 441 | /* Temporary variable needed for gcc-2.96 */ | 451 | /* Temporary variable needed for gcc-2.96 */ |
| 442 | /* convert timespec -> nsec*/ | 452 | /* convert timespec -> nsec*/ |
| 443 | start_time = (unsigned long long)task->start_time.tv_sec * NSEC_PER_SEC | 453 | start_time = |
| 444 | + task->start_time.tv_nsec; | 454 | (unsigned long long)task->real_start_time.tv_sec * NSEC_PER_SEC |
| 455 | + task->real_start_time.tv_nsec; | ||
| 445 | /* convert nsec -> ticks */ | 456 | /* convert nsec -> ticks */ |
| 446 | start_time = nsec_to_clock_t(start_time); | 457 | start_time = nsec_to_clock_t(start_time); |
| 447 | 458 | ||
diff --git a/fs/proc/base.c b/fs/proc/base.c index 46ea5d56e1bb..ae3627337a92 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
| @@ -67,7 +67,6 @@ | |||
| 67 | #include <linux/mount.h> | 67 | #include <linux/mount.h> |
| 68 | #include <linux/security.h> | 68 | #include <linux/security.h> |
| 69 | #include <linux/ptrace.h> | 69 | #include <linux/ptrace.h> |
| 70 | #include <linux/seccomp.h> | ||
| 71 | #include <linux/cpuset.h> | 70 | #include <linux/cpuset.h> |
| 72 | #include <linux/audit.h> | 71 | #include <linux/audit.h> |
| 73 | #include <linux/poll.h> | 72 | #include <linux/poll.h> |
| @@ -204,12 +203,17 @@ static int proc_pid_environ(struct task_struct *task, char * buffer) | |||
| 204 | int res = 0; | 203 | int res = 0; |
| 205 | struct mm_struct *mm = get_task_mm(task); | 204 | struct mm_struct *mm = get_task_mm(task); |
| 206 | if (mm) { | 205 | if (mm) { |
| 207 | unsigned int len = mm->env_end - mm->env_start; | 206 | unsigned int len; |
| 207 | |||
| 208 | res = -ESRCH; | ||
| 209 | if (!ptrace_may_attach(task)) | ||
| 210 | goto out; | ||
| 211 | |||
| 212 | len = mm->env_end - mm->env_start; | ||
| 208 | if (len > PAGE_SIZE) | 213 | if (len > PAGE_SIZE) |
| 209 | len = PAGE_SIZE; | 214 | len = PAGE_SIZE; |
| 210 | res = access_process_vm(task, mm->env_start, buffer, len, 0); | 215 | res = access_process_vm(task, mm->env_start, buffer, len, 0); |
| 211 | if (!ptrace_may_attach(task)) | 216 | out: |
| 212 | res = -ESRCH; | ||
| 213 | mmput(mm); | 217 | mmput(mm); |
| 214 | } | 218 | } |
| 215 | return res; | 219 | return res; |
| @@ -812,71 +816,6 @@ static const struct file_operations proc_loginuid_operations = { | |||
| 812 | }; | 816 | }; |
| 813 | #endif | 817 | #endif |
| 814 | 818 | ||
| 815 | #ifdef CONFIG_SECCOMP | ||
| 816 | static ssize_t seccomp_read(struct file *file, char __user *buf, | ||
| 817 | size_t count, loff_t *ppos) | ||
| 818 | { | ||
| 819 | struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); | ||
| 820 | char __buf[20]; | ||
| 821 | size_t len; | ||
| 822 | |||
| 823 | if (!tsk) | ||
| 824 | return -ESRCH; | ||
| 825 | /* no need to print the trailing zero, so use only len */ | ||
| 826 | len = sprintf(__buf, "%u\n", tsk->seccomp.mode); | ||
| 827 | put_task_struct(tsk); | ||
| 828 | |||
| 829 | return simple_read_from_buffer(buf, count, ppos, __buf, len); | ||
| 830 | } | ||
| 831 | |||
| 832 | static ssize_t seccomp_write(struct file *file, const char __user *buf, | ||
| 833 | size_t count, loff_t *ppos) | ||
| 834 | { | ||
| 835 | struct task_struct *tsk = get_proc_task(file->f_dentry->d_inode); | ||
| 836 | char __buf[20], *end; | ||
| 837 | unsigned int seccomp_mode; | ||
| 838 | ssize_t result; | ||
| 839 | |||
| 840 | result = -ESRCH; | ||
| 841 | if (!tsk) | ||
| 842 | goto out_no_task; | ||
| 843 | |||
| 844 | /* can set it only once to be even more secure */ | ||
| 845 | result = -EPERM; | ||
| 846 | if (unlikely(tsk->seccomp.mode)) | ||
| 847 | goto out; | ||
| 848 | |||
| 849 | result = -EFAULT; | ||
| 850 | memset(__buf, 0, sizeof(__buf)); | ||
| 851 | count = min(count, sizeof(__buf) - 1); | ||
| 852 | if (copy_from_user(__buf, buf, count)) | ||
| 853 | goto out; | ||
| 854 | |||
| 855 | seccomp_mode = simple_strtoul(__buf, &end, 0); | ||
| 856 | if (*end == '\n') | ||
| 857 | end++; | ||
| 858 | result = -EINVAL; | ||
| 859 | if (seccomp_mode && seccomp_mode <= NR_SECCOMP_MODES) { | ||
| 860 | tsk->seccomp.mode = seccomp_mode; | ||
| 861 | set_tsk_thread_flag(tsk, TIF_SECCOMP); | ||
| 862 | } else | ||
| 863 | goto out; | ||
| 864 | result = -EIO; | ||
| 865 | if (unlikely(!(end - __buf))) | ||
| 866 | goto out; | ||
| 867 | result = end - __buf; | ||
| 868 | out: | ||
| 869 | put_task_struct(tsk); | ||
| 870 | out_no_task: | ||
| 871 | return result; | ||
| 872 | } | ||
| 873 | |||
| 874 | static const struct file_operations proc_seccomp_operations = { | ||
| 875 | .read = seccomp_read, | ||
| 876 | .write = seccomp_write, | ||
| 877 | }; | ||
| 878 | #endif /* CONFIG_SECCOMP */ | ||
| 879 | |||
| 880 | #ifdef CONFIG_FAULT_INJECTION | 819 | #ifdef CONFIG_FAULT_INJECTION |
| 881 | static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, | 820 | static ssize_t proc_fault_inject_read(struct file * file, char __user * buf, |
| 882 | size_t count, loff_t *ppos) | 821 | size_t count, loff_t *ppos) |
| @@ -2037,9 +1976,6 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
| 2037 | REG("numa_maps", S_IRUGO, numa_maps), | 1976 | REG("numa_maps", S_IRUGO, numa_maps), |
| 2038 | #endif | 1977 | #endif |
| 2039 | REG("mem", S_IRUSR|S_IWUSR, mem), | 1978 | REG("mem", S_IRUSR|S_IWUSR, mem), |
| 2040 | #ifdef CONFIG_SECCOMP | ||
| 2041 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), | ||
| 2042 | #endif | ||
| 2043 | LNK("cwd", cwd), | 1979 | LNK("cwd", cwd), |
| 2044 | LNK("root", root), | 1980 | LNK("root", root), |
| 2045 | LNK("exe", exe), | 1981 | LNK("exe", exe), |
| @@ -2324,9 +2260,6 @@ static const struct pid_entry tid_base_stuff[] = { | |||
| 2324 | REG("numa_maps", S_IRUGO, numa_maps), | 2260 | REG("numa_maps", S_IRUGO, numa_maps), |
| 2325 | #endif | 2261 | #endif |
| 2326 | REG("mem", S_IRUSR|S_IWUSR, mem), | 2262 | REG("mem", S_IRUSR|S_IWUSR, mem), |
| 2327 | #ifdef CONFIG_SECCOMP | ||
| 2328 | REG("seccomp", S_IRUSR|S_IWUSR, seccomp), | ||
| 2329 | #endif | ||
| 2330 | LNK("cwd", cwd), | 2263 | LNK("cwd", cwd), |
| 2331 | LNK("root", root), | 2264 | LNK("root", root), |
| 2332 | LNK("exe", exe), | 2265 | LNK("exe", exe), |
diff --git a/fs/proc/generic.c b/fs/proc/generic.c index 8a40e15f5ecb..b5e7155d30d8 100644 --- a/fs/proc/generic.c +++ b/fs/proc/generic.c | |||
| @@ -20,6 +20,7 @@ | |||
| 20 | #include <linux/namei.h> | 20 | #include <linux/namei.h> |
| 21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
| 22 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| 23 | #include <linux/completion.h> | ||
| 23 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
| 24 | 25 | ||
| 25 | #include "internal.h" | 26 | #include "internal.h" |
| @@ -529,12 +530,6 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
| 529 | return -EAGAIN; | 530 | return -EAGAIN; |
| 530 | dp->low_ino = i; | 531 | dp->low_ino = i; |
| 531 | 532 | ||
| 532 | spin_lock(&proc_subdir_lock); | ||
| 533 | dp->next = dir->subdir; | ||
| 534 | dp->parent = dir; | ||
| 535 | dir->subdir = dp; | ||
| 536 | spin_unlock(&proc_subdir_lock); | ||
| 537 | |||
| 538 | if (S_ISDIR(dp->mode)) { | 533 | if (S_ISDIR(dp->mode)) { |
| 539 | if (dp->proc_iops == NULL) { | 534 | if (dp->proc_iops == NULL) { |
| 540 | dp->proc_fops = &proc_dir_operations; | 535 | dp->proc_fops = &proc_dir_operations; |
| @@ -550,6 +545,13 @@ static int proc_register(struct proc_dir_entry * dir, struct proc_dir_entry * dp | |||
| 550 | if (dp->proc_iops == NULL) | 545 | if (dp->proc_iops == NULL) |
| 551 | dp->proc_iops = &proc_file_inode_operations; | 546 | dp->proc_iops = &proc_file_inode_operations; |
| 552 | } | 547 | } |
| 548 | |||
| 549 | spin_lock(&proc_subdir_lock); | ||
| 550 | dp->next = dir->subdir; | ||
| 551 | dp->parent = dir; | ||
| 552 | dir->subdir = dp; | ||
| 553 | spin_unlock(&proc_subdir_lock); | ||
| 554 | |||
| 553 | return 0; | 555 | return 0; |
| 554 | } | 556 | } |
| 555 | 557 | ||
| @@ -613,6 +615,9 @@ static struct proc_dir_entry *proc_create(struct proc_dir_entry **parent, | |||
| 613 | ent->namelen = len; | 615 | ent->namelen = len; |
| 614 | ent->mode = mode; | 616 | ent->mode = mode; |
| 615 | ent->nlink = nlink; | 617 | ent->nlink = nlink; |
| 618 | ent->pde_users = 0; | ||
| 619 | spin_lock_init(&ent->pde_unload_lock); | ||
| 620 | ent->pde_unload_completion = NULL; | ||
| 616 | out: | 621 | out: |
| 617 | return ent; | 622 | return ent; |
| 618 | } | 623 | } |
| @@ -649,9 +654,6 @@ struct proc_dir_entry *proc_mkdir_mode(const char *name, mode_t mode, | |||
| 649 | 654 | ||
| 650 | ent = proc_create(&parent, name, S_IFDIR | mode, 2); | 655 | ent = proc_create(&parent, name, S_IFDIR | mode, 2); |
| 651 | if (ent) { | 656 | if (ent) { |
| 652 | ent->proc_fops = &proc_dir_operations; | ||
| 653 | ent->proc_iops = &proc_dir_inode_operations; | ||
| 654 | |||
| 655 | if (proc_register(parent, ent) < 0) { | 657 | if (proc_register(parent, ent) < 0) { |
| 656 | kfree(ent); | 658 | kfree(ent); |
| 657 | ent = NULL; | 659 | ent = NULL; |
| @@ -686,10 +688,6 @@ struct proc_dir_entry *create_proc_entry(const char *name, mode_t mode, | |||
| 686 | 688 | ||
| 687 | ent = proc_create(&parent,name,mode,nlink); | 689 | ent = proc_create(&parent,name,mode,nlink); |
| 688 | if (ent) { | 690 | if (ent) { |
| 689 | if (S_ISDIR(mode)) { | ||
| 690 | ent->proc_fops = &proc_dir_operations; | ||
| 691 | ent->proc_iops = &proc_dir_inode_operations; | ||
| 692 | } | ||
| 693 | if (proc_register(parent, ent) < 0) { | 691 | if (proc_register(parent, ent) < 0) { |
| 694 | kfree(ent); | 692 | kfree(ent); |
| 695 | ent = NULL; | 693 | ent = NULL; |
| @@ -734,9 +732,35 @@ void remove_proc_entry(const char *name, struct proc_dir_entry *parent) | |||
| 734 | de = *p; | 732 | de = *p; |
| 735 | *p = de->next; | 733 | *p = de->next; |
| 736 | de->next = NULL; | 734 | de->next = NULL; |
| 735 | |||
| 736 | spin_lock(&de->pde_unload_lock); | ||
| 737 | /* | ||
| 738 | * Stop accepting new callers into module. If you're | ||
| 739 | * dynamically allocating ->proc_fops, save a pointer somewhere. | ||
| 740 | */ | ||
| 741 | de->proc_fops = NULL; | ||
| 742 | /* Wait until all existing callers into module are done. */ | ||
| 743 | if (de->pde_users > 0) { | ||
| 744 | DECLARE_COMPLETION_ONSTACK(c); | ||
| 745 | |||
| 746 | if (!de->pde_unload_completion) | ||
| 747 | de->pde_unload_completion = &c; | ||
| 748 | |||
| 749 | spin_unlock(&de->pde_unload_lock); | ||
| 750 | spin_unlock(&proc_subdir_lock); | ||
| 751 | |||
| 752 | wait_for_completion(de->pde_unload_completion); | ||
| 753 | |||
| 754 | spin_lock(&proc_subdir_lock); | ||
| 755 | goto continue_removing; | ||
| 756 | } | ||
| 757 | spin_unlock(&de->pde_unload_lock); | ||
| 758 | |||
| 759 | continue_removing: | ||
| 737 | if (S_ISDIR(de->mode)) | 760 | if (S_ISDIR(de->mode)) |
| 738 | parent->nlink--; | 761 | parent->nlink--; |
| 739 | proc_kill_inodes(de); | 762 | if (!S_ISREG(de->mode)) |
| 763 | proc_kill_inodes(de); | ||
| 740 | de->nlink = 0; | 764 | de->nlink = 0; |
| 741 | WARN_ON(de->subdir); | 765 | WARN_ON(de->subdir); |
| 742 | if (!atomic_read(&de->count)) | 766 | if (!atomic_read(&de->count)) |
diff --git a/fs/proc/inode.c b/fs/proc/inode.c index d5ce65c68d7b..dd28e86ab422 100644 --- a/fs/proc/inode.c +++ b/fs/proc/inode.c | |||
| @@ -10,6 +10,7 @@ | |||
| 10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
| 11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
| 12 | #include <linux/stat.h> | 12 | #include <linux/stat.h> |
| 13 | #include <linux/completion.h> | ||
| 13 | #include <linux/file.h> | 14 | #include <linux/file.h> |
| 14 | #include <linux/limits.h> | 15 | #include <linux/limits.h> |
| 15 | #include <linux/init.h> | 16 | #include <linux/init.h> |
| @@ -140,6 +141,251 @@ static const struct super_operations proc_sops = { | |||
| 140 | .remount_fs = proc_remount, | 141 | .remount_fs = proc_remount, |
| 141 | }; | 142 | }; |
| 142 | 143 | ||
| 144 | static void pde_users_dec(struct proc_dir_entry *pde) | ||
| 145 | { | ||
| 146 | spin_lock(&pde->pde_unload_lock); | ||
| 147 | pde->pde_users--; | ||
| 148 | if (pde->pde_unload_completion && pde->pde_users == 0) | ||
| 149 | complete(pde->pde_unload_completion); | ||
| 150 | spin_unlock(&pde->pde_unload_lock); | ||
| 151 | } | ||
| 152 | |||
| 153 | static loff_t proc_reg_llseek(struct file *file, loff_t offset, int whence) | ||
| 154 | { | ||
| 155 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 156 | loff_t rv = -EINVAL; | ||
| 157 | loff_t (*llseek)(struct file *, loff_t, int); | ||
| 158 | |||
| 159 | spin_lock(&pde->pde_unload_lock); | ||
| 160 | /* | ||
| 161 | * remove_proc_entry() is going to delete PDE (as part of module | ||
| 162 | * cleanup sequence). No new callers into module allowed. | ||
| 163 | */ | ||
| 164 | if (!pde->proc_fops) { | ||
| 165 | spin_unlock(&pde->pde_unload_lock); | ||
| 166 | return rv; | ||
| 167 | } | ||
| 168 | /* | ||
| 169 | * Bump refcount so that remove_proc_entry will wail for ->llseek to | ||
| 170 | * complete. | ||
| 171 | */ | ||
| 172 | pde->pde_users++; | ||
| 173 | /* | ||
| 174 | * Save function pointer under lock, to protect against ->proc_fops | ||
| 175 | * NULL'ifying right after ->pde_unload_lock is dropped. | ||
| 176 | */ | ||
| 177 | llseek = pde->proc_fops->llseek; | ||
| 178 | spin_unlock(&pde->pde_unload_lock); | ||
| 179 | |||
| 180 | if (!llseek) | ||
| 181 | llseek = default_llseek; | ||
| 182 | rv = llseek(file, offset, whence); | ||
| 183 | |||
| 184 | pde_users_dec(pde); | ||
| 185 | return rv; | ||
| 186 | } | ||
| 187 | |||
| 188 | static ssize_t proc_reg_read(struct file *file, char __user *buf, size_t count, loff_t *ppos) | ||
| 189 | { | ||
| 190 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 191 | ssize_t rv = -EIO; | ||
| 192 | ssize_t (*read)(struct file *, char __user *, size_t, loff_t *); | ||
| 193 | |||
| 194 | spin_lock(&pde->pde_unload_lock); | ||
| 195 | if (!pde->proc_fops) { | ||
| 196 | spin_unlock(&pde->pde_unload_lock); | ||
| 197 | return rv; | ||
| 198 | } | ||
| 199 | pde->pde_users++; | ||
| 200 | read = pde->proc_fops->read; | ||
| 201 | spin_unlock(&pde->pde_unload_lock); | ||
| 202 | |||
| 203 | if (read) | ||
| 204 | rv = read(file, buf, count, ppos); | ||
| 205 | |||
| 206 | pde_users_dec(pde); | ||
| 207 | return rv; | ||
| 208 | } | ||
| 209 | |||
| 210 | static ssize_t proc_reg_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | ||
| 211 | { | ||
| 212 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 213 | ssize_t rv = -EIO; | ||
| 214 | ssize_t (*write)(struct file *, const char __user *, size_t, loff_t *); | ||
| 215 | |||
| 216 | spin_lock(&pde->pde_unload_lock); | ||
| 217 | if (!pde->proc_fops) { | ||
| 218 | spin_unlock(&pde->pde_unload_lock); | ||
| 219 | return rv; | ||
| 220 | } | ||
| 221 | pde->pde_users++; | ||
| 222 | write = pde->proc_fops->write; | ||
| 223 | spin_unlock(&pde->pde_unload_lock); | ||
| 224 | |||
| 225 | if (write) | ||
| 226 | rv = write(file, buf, count, ppos); | ||
| 227 | |||
| 228 | pde_users_dec(pde); | ||
| 229 | return rv; | ||
| 230 | } | ||
| 231 | |||
| 232 | static unsigned int proc_reg_poll(struct file *file, struct poll_table_struct *pts) | ||
| 233 | { | ||
| 234 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 235 | unsigned int rv = 0; | ||
| 236 | unsigned int (*poll)(struct file *, struct poll_table_struct *); | ||
| 237 | |||
| 238 | spin_lock(&pde->pde_unload_lock); | ||
| 239 | if (!pde->proc_fops) { | ||
| 240 | spin_unlock(&pde->pde_unload_lock); | ||
| 241 | return rv; | ||
| 242 | } | ||
| 243 | pde->pde_users++; | ||
| 244 | poll = pde->proc_fops->poll; | ||
| 245 | spin_unlock(&pde->pde_unload_lock); | ||
| 246 | |||
| 247 | if (poll) | ||
| 248 | rv = poll(file, pts); | ||
| 249 | |||
| 250 | pde_users_dec(pde); | ||
| 251 | return rv; | ||
| 252 | } | ||
| 253 | |||
| 254 | static long proc_reg_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 255 | { | ||
| 256 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 257 | long rv = -ENOTTY; | ||
| 258 | long (*unlocked_ioctl)(struct file *, unsigned int, unsigned long); | ||
| 259 | int (*ioctl)(struct inode *, struct file *, unsigned int, unsigned long); | ||
| 260 | |||
| 261 | spin_lock(&pde->pde_unload_lock); | ||
| 262 | if (!pde->proc_fops) { | ||
| 263 | spin_unlock(&pde->pde_unload_lock); | ||
| 264 | return rv; | ||
| 265 | } | ||
| 266 | pde->pde_users++; | ||
| 267 | unlocked_ioctl = pde->proc_fops->unlocked_ioctl; | ||
| 268 | ioctl = pde->proc_fops->ioctl; | ||
| 269 | spin_unlock(&pde->pde_unload_lock); | ||
| 270 | |||
| 271 | if (unlocked_ioctl) { | ||
| 272 | rv = unlocked_ioctl(file, cmd, arg); | ||
| 273 | if (rv == -ENOIOCTLCMD) | ||
| 274 | rv = -EINVAL; | ||
| 275 | } else if (ioctl) { | ||
| 276 | lock_kernel(); | ||
| 277 | rv = ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
| 278 | unlock_kernel(); | ||
| 279 | } | ||
| 280 | |||
| 281 | pde_users_dec(pde); | ||
| 282 | return rv; | ||
| 283 | } | ||
| 284 | |||
| 285 | #ifdef CONFIG_COMPAT | ||
| 286 | static long proc_reg_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
| 287 | { | ||
| 288 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 289 | long rv = -ENOTTY; | ||
| 290 | long (*compat_ioctl)(struct file *, unsigned int, unsigned long); | ||
| 291 | |||
| 292 | spin_lock(&pde->pde_unload_lock); | ||
| 293 | if (!pde->proc_fops) { | ||
| 294 | spin_unlock(&pde->pde_unload_lock); | ||
| 295 | return rv; | ||
| 296 | } | ||
| 297 | pde->pde_users++; | ||
| 298 | compat_ioctl = pde->proc_fops->compat_ioctl; | ||
| 299 | spin_unlock(&pde->pde_unload_lock); | ||
| 300 | |||
| 301 | if (compat_ioctl) | ||
| 302 | rv = compat_ioctl(file, cmd, arg); | ||
| 303 | |||
| 304 | pde_users_dec(pde); | ||
| 305 | return rv; | ||
| 306 | } | ||
| 307 | #endif | ||
| 308 | |||
| 309 | static int proc_reg_mmap(struct file *file, struct vm_area_struct *vma) | ||
| 310 | { | ||
| 311 | struct proc_dir_entry *pde = PDE(file->f_path.dentry->d_inode); | ||
| 312 | int rv = -EIO; | ||
| 313 | int (*mmap)(struct file *, struct vm_area_struct *); | ||
| 314 | |||
| 315 | spin_lock(&pde->pde_unload_lock); | ||
| 316 | if (!pde->proc_fops) { | ||
| 317 | spin_unlock(&pde->pde_unload_lock); | ||
| 318 | return rv; | ||
| 319 | } | ||
| 320 | pde->pde_users++; | ||
| 321 | mmap = pde->proc_fops->mmap; | ||
| 322 | spin_unlock(&pde->pde_unload_lock); | ||
| 323 | |||
| 324 | if (mmap) | ||
| 325 | rv = mmap(file, vma); | ||
| 326 | |||
| 327 | pde_users_dec(pde); | ||
| 328 | return rv; | ||
| 329 | } | ||
| 330 | |||
| 331 | static int proc_reg_open(struct inode *inode, struct file *file) | ||
| 332 | { | ||
| 333 | struct proc_dir_entry *pde = PDE(inode); | ||
| 334 | int rv = 0; | ||
| 335 | int (*open)(struct inode *, struct file *); | ||
| 336 | |||
| 337 | spin_lock(&pde->pde_unload_lock); | ||
| 338 | if (!pde->proc_fops) { | ||
| 339 | spin_unlock(&pde->pde_unload_lock); | ||
| 340 | return rv; | ||
| 341 | } | ||
| 342 | pde->pde_users++; | ||
| 343 | open = pde->proc_fops->open; | ||
| 344 | spin_unlock(&pde->pde_unload_lock); | ||
| 345 | |||
| 346 | if (open) | ||
| 347 | rv = open(inode, file); | ||
| 348 | |||
| 349 | pde_users_dec(pde); | ||
| 350 | return rv; | ||
| 351 | } | ||
| 352 | |||
| 353 | static int proc_reg_release(struct inode *inode, struct file *file) | ||
| 354 | { | ||
| 355 | struct proc_dir_entry *pde = PDE(inode); | ||
| 356 | int rv = 0; | ||
| 357 | int (*release)(struct inode *, struct file *); | ||
| 358 | |||
| 359 | spin_lock(&pde->pde_unload_lock); | ||
| 360 | if (!pde->proc_fops) { | ||
| 361 | spin_unlock(&pde->pde_unload_lock); | ||
| 362 | return rv; | ||
| 363 | } | ||
| 364 | pde->pde_users++; | ||
| 365 | release = pde->proc_fops->release; | ||
| 366 | spin_unlock(&pde->pde_unload_lock); | ||
| 367 | |||
| 368 | if (release) | ||
| 369 | rv = release(inode, file); | ||
| 370 | |||
| 371 | pde_users_dec(pde); | ||
| 372 | return rv; | ||
| 373 | } | ||
| 374 | |||
| 375 | static const struct file_operations proc_reg_file_ops = { | ||
| 376 | .llseek = proc_reg_llseek, | ||
| 377 | .read = proc_reg_read, | ||
| 378 | .write = proc_reg_write, | ||
| 379 | .poll = proc_reg_poll, | ||
| 380 | .unlocked_ioctl = proc_reg_unlocked_ioctl, | ||
| 381 | #ifdef CONFIG_COMPAT | ||
| 382 | .compat_ioctl = proc_reg_compat_ioctl, | ||
| 383 | #endif | ||
| 384 | .mmap = proc_reg_mmap, | ||
| 385 | .open = proc_reg_open, | ||
| 386 | .release = proc_reg_release, | ||
| 387 | }; | ||
| 388 | |||
| 143 | struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | 389 | struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, |
| 144 | struct proc_dir_entry *de) | 390 | struct proc_dir_entry *de) |
| 145 | { | 391 | { |
| @@ -166,8 +412,12 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino, | |||
| 166 | inode->i_nlink = de->nlink; | 412 | inode->i_nlink = de->nlink; |
| 167 | if (de->proc_iops) | 413 | if (de->proc_iops) |
| 168 | inode->i_op = de->proc_iops; | 414 | inode->i_op = de->proc_iops; |
| 169 | if (de->proc_fops) | 415 | if (de->proc_fops) { |
| 170 | inode->i_fop = de->proc_fops; | 416 | if (S_ISREG(inode->i_mode)) |
| 417 | inode->i_fop = &proc_reg_file_ops; | ||
| 418 | else | ||
| 419 | inode->i_fop = de->proc_fops; | ||
| 420 | } | ||
| 171 | } | 421 | } |
| 172 | 422 | ||
| 173 | return inode; | 423 | return inode; |
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 5fd49e47f83a..d24b8d46059a 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c | |||
| @@ -105,6 +105,7 @@ static int uptime_read_proc(char *page, char **start, off_t off, | |||
| 105 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); | 105 | cputime_t idletime = cputime_add(init_task.utime, init_task.stime); |
| 106 | 106 | ||
| 107 | do_posix_clock_monotonic_gettime(&uptime); | 107 | do_posix_clock_monotonic_gettime(&uptime); |
| 108 | monotonic_to_bootbased(&uptime); | ||
| 108 | cputime_to_timespec(idletime, &idle); | 109 | cputime_to_timespec(idletime, &idle); |
| 109 | len = sprintf(page,"%lu.%02lu %lu.%02lu\n", | 110 | len = sprintf(page,"%lu.%02lu %lu.%02lu\n", |
| 110 | (unsigned long) uptime.tv_sec, | 111 | (unsigned long) uptime.tv_sec, |
| @@ -443,12 +444,12 @@ static int show_stat(struct seq_file *p, void *v) | |||
| 443 | unsigned long jif; | 444 | unsigned long jif; |
| 444 | cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; | 445 | cputime64_t user, nice, system, idle, iowait, irq, softirq, steal; |
| 445 | u64 sum = 0; | 446 | u64 sum = 0; |
| 447 | struct timespec boottime; | ||
| 446 | 448 | ||
| 447 | user = nice = system = idle = iowait = | 449 | user = nice = system = idle = iowait = |
| 448 | irq = softirq = steal = cputime64_zero; | 450 | irq = softirq = steal = cputime64_zero; |
| 449 | jif = - wall_to_monotonic.tv_sec; | 451 | getboottime(&boottime); |
| 450 | if (wall_to_monotonic.tv_nsec) | 452 | jif = boottime.tv_sec; |
| 451 | --jif; | ||
| 452 | 453 | ||
| 453 | for_each_possible_cpu(i) { | 454 | for_each_possible_cpu(i) { |
| 454 | int j; | 455 | int j; |
diff --git a/fs/proc/proc_tty.c b/fs/proc/proc_tty.c index b3a473b0a191..22846225acfa 100644 --- a/fs/proc/proc_tty.c +++ b/fs/proc/proc_tty.c | |||
| @@ -69,7 +69,7 @@ static void show_tty_range(struct seq_file *m, struct tty_driver *p, | |||
| 69 | 69 | ||
| 70 | static int show_tty_driver(struct seq_file *m, void *v) | 70 | static int show_tty_driver(struct seq_file *m, void *v) |
| 71 | { | 71 | { |
| 72 | struct tty_driver *p = v; | 72 | struct tty_driver *p = list_entry(v, struct tty_driver, tty_drivers); |
| 73 | dev_t from = MKDEV(p->major, p->minor_start); | 73 | dev_t from = MKDEV(p->major, p->minor_start); |
| 74 | dev_t to = from + p->num; | 74 | dev_t to = from + p->num; |
| 75 | 75 | ||
| @@ -106,22 +106,13 @@ static int show_tty_driver(struct seq_file *m, void *v) | |||
| 106 | /* iterator */ | 106 | /* iterator */ |
| 107 | static void *t_start(struct seq_file *m, loff_t *pos) | 107 | static void *t_start(struct seq_file *m, loff_t *pos) |
| 108 | { | 108 | { |
| 109 | struct list_head *p; | ||
| 110 | loff_t l = *pos; | ||
| 111 | |||
| 112 | mutex_lock(&tty_mutex); | 109 | mutex_lock(&tty_mutex); |
| 113 | list_for_each(p, &tty_drivers) | 110 | return seq_list_start(&tty_drivers, *pos); |
| 114 | if (!l--) | ||
| 115 | return list_entry(p, struct tty_driver, tty_drivers); | ||
| 116 | return NULL; | ||
| 117 | } | 111 | } |
| 118 | 112 | ||
| 119 | static void *t_next(struct seq_file *m, void *v, loff_t *pos) | 113 | static void *t_next(struct seq_file *m, void *v, loff_t *pos) |
| 120 | { | 114 | { |
| 121 | struct list_head *p = ((struct tty_driver *)v)->tty_drivers.next; | 115 | return seq_list_next(v, &tty_drivers, pos); |
| 122 | (*pos)++; | ||
| 123 | return p==&tty_drivers ? NULL : | ||
| 124 | list_entry(p, struct tty_driver, tty_drivers); | ||
| 125 | } | 116 | } |
| 126 | 117 | ||
| 127 | static void t_stop(struct seq_file *m, void *v) | 118 | static void t_stop(struct seq_file *m, void *v) |
diff --git a/fs/quota.c b/fs/quota.c index 9f237d6182c9..e6577ac15a6c 100644 --- a/fs/quota.c +++ b/fs/quota.c | |||
| @@ -10,12 +10,14 @@ | |||
| 10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 11 | #include <asm/current.h> | 11 | #include <asm/current.h> |
| 12 | #include <asm/uaccess.h> | 12 | #include <asm/uaccess.h> |
| 13 | #include <linux/compat.h> | ||
| 13 | #include <linux/kernel.h> | 14 | #include <linux/kernel.h> |
| 14 | #include <linux/security.h> | 15 | #include <linux/security.h> |
| 15 | #include <linux/syscalls.h> | 16 | #include <linux/syscalls.h> |
| 16 | #include <linux/buffer_head.h> | 17 | #include <linux/buffer_head.h> |
| 17 | #include <linux/capability.h> | 18 | #include <linux/capability.h> |
| 18 | #include <linux/quotaops.h> | 19 | #include <linux/quotaops.h> |
| 20 | #include <linux/types.h> | ||
| 19 | 21 | ||
| 20 | /* Check validity of generic quotactl commands */ | 22 | /* Check validity of generic quotactl commands */ |
| 21 | static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) | 23 | static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid_t id) |
| @@ -384,3 +386,119 @@ asmlinkage long sys_quotactl(unsigned int cmd, const char __user *special, qid_t | |||
| 384 | 386 | ||
| 385 | return ret; | 387 | return ret; |
| 386 | } | 388 | } |
| 389 | |||
| 390 | #if defined(CONFIG_X86_64) || defined(CONFIG_IA64) | ||
| 391 | /* | ||
| 392 | * This code works only for 32 bit quota tools over 64 bit OS (x86_64, ia64) | ||
| 393 | * and is necessary due to alignment problems. | ||
| 394 | */ | ||
| 395 | struct compat_if_dqblk { | ||
| 396 | compat_u64 dqb_bhardlimit; | ||
| 397 | compat_u64 dqb_bsoftlimit; | ||
| 398 | compat_u64 dqb_curspace; | ||
| 399 | compat_u64 dqb_ihardlimit; | ||
| 400 | compat_u64 dqb_isoftlimit; | ||
| 401 | compat_u64 dqb_curinodes; | ||
| 402 | compat_u64 dqb_btime; | ||
| 403 | compat_u64 dqb_itime; | ||
| 404 | compat_uint_t dqb_valid; | ||
| 405 | }; | ||
| 406 | |||
| 407 | /* XFS structures */ | ||
| 408 | struct compat_fs_qfilestat { | ||
| 409 | compat_u64 dqb_bhardlimit; | ||
| 410 | compat_u64 qfs_nblks; | ||
| 411 | compat_uint_t qfs_nextents; | ||
| 412 | }; | ||
| 413 | |||
| 414 | struct compat_fs_quota_stat { | ||
| 415 | __s8 qs_version; | ||
| 416 | __u16 qs_flags; | ||
| 417 | __s8 qs_pad; | ||
| 418 | struct compat_fs_qfilestat qs_uquota; | ||
| 419 | struct compat_fs_qfilestat qs_gquota; | ||
| 420 | compat_uint_t qs_incoredqs; | ||
| 421 | compat_int_t qs_btimelimit; | ||
| 422 | compat_int_t qs_itimelimit; | ||
| 423 | compat_int_t qs_rtbtimelimit; | ||
| 424 | __u16 qs_bwarnlimit; | ||
| 425 | __u16 qs_iwarnlimit; | ||
| 426 | }; | ||
| 427 | |||
| 428 | asmlinkage long sys32_quotactl(unsigned int cmd, const char __user *special, | ||
| 429 | qid_t id, void __user *addr) | ||
| 430 | { | ||
| 431 | unsigned int cmds; | ||
| 432 | struct if_dqblk __user *dqblk; | ||
| 433 | struct compat_if_dqblk __user *compat_dqblk; | ||
| 434 | struct fs_quota_stat __user *fsqstat; | ||
| 435 | struct compat_fs_quota_stat __user *compat_fsqstat; | ||
| 436 | compat_uint_t data; | ||
| 437 | u16 xdata; | ||
| 438 | long ret; | ||
| 439 | |||
| 440 | cmds = cmd >> SUBCMDSHIFT; | ||
| 441 | |||
| 442 | switch (cmds) { | ||
| 443 | case Q_GETQUOTA: | ||
| 444 | dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); | ||
| 445 | compat_dqblk = addr; | ||
| 446 | ret = sys_quotactl(cmd, special, id, dqblk); | ||
| 447 | if (ret) | ||
| 448 | break; | ||
| 449 | if (copy_in_user(compat_dqblk, dqblk, sizeof(*compat_dqblk)) || | ||
| 450 | get_user(data, &dqblk->dqb_valid) || | ||
| 451 | put_user(data, &compat_dqblk->dqb_valid)) | ||
| 452 | ret = -EFAULT; | ||
| 453 | break; | ||
| 454 | case Q_SETQUOTA: | ||
| 455 | dqblk = compat_alloc_user_space(sizeof(struct if_dqblk)); | ||
| 456 | compat_dqblk = addr; | ||
| 457 | ret = -EFAULT; | ||
| 458 | if (copy_in_user(dqblk, compat_dqblk, sizeof(*compat_dqblk)) || | ||
| 459 | get_user(data, &compat_dqblk->dqb_valid) || | ||
| 460 | put_user(data, &dqblk->dqb_valid)) | ||
| 461 | break; | ||
| 462 | ret = sys_quotactl(cmd, special, id, dqblk); | ||
| 463 | break; | ||
| 464 | case Q_XGETQSTAT: | ||
| 465 | fsqstat = compat_alloc_user_space(sizeof(struct fs_quota_stat)); | ||
| 466 | compat_fsqstat = addr; | ||
| 467 | ret = sys_quotactl(cmd, special, id, fsqstat); | ||
| 468 | if (ret) | ||
| 469 | break; | ||
| 470 | ret = -EFAULT; | ||
| 471 | /* Copying qs_version, qs_flags, qs_pad */ | ||
| 472 | if (copy_in_user(compat_fsqstat, fsqstat, | ||
| 473 | offsetof(struct compat_fs_quota_stat, qs_uquota))) | ||
| 474 | break; | ||
| 475 | /* Copying qs_uquota */ | ||
| 476 | if (copy_in_user(&compat_fsqstat->qs_uquota, | ||
| 477 | &fsqstat->qs_uquota, | ||
| 478 | sizeof(compat_fsqstat->qs_uquota)) || | ||
| 479 | get_user(data, &fsqstat->qs_uquota.qfs_nextents) || | ||
| 480 | put_user(data, &compat_fsqstat->qs_uquota.qfs_nextents)) | ||
| 481 | break; | ||
| 482 | /* Copying qs_gquota */ | ||
| 483 | if (copy_in_user(&compat_fsqstat->qs_gquota, | ||
| 484 | &fsqstat->qs_gquota, | ||
| 485 | sizeof(compat_fsqstat->qs_gquota)) || | ||
| 486 | get_user(data, &fsqstat->qs_gquota.qfs_nextents) || | ||
| 487 | put_user(data, &compat_fsqstat->qs_gquota.qfs_nextents)) | ||
| 488 | break; | ||
| 489 | /* Copying the rest */ | ||
| 490 | if (copy_in_user(&compat_fsqstat->qs_incoredqs, | ||
| 491 | &fsqstat->qs_incoredqs, | ||
| 492 | sizeof(struct compat_fs_quota_stat) - | ||
| 493 | offsetof(struct compat_fs_quota_stat, qs_incoredqs)) || | ||
| 494 | get_user(xdata, &fsqstat->qs_iwarnlimit) || | ||
| 495 | put_user(xdata, &compat_fsqstat->qs_iwarnlimit)) | ||
| 496 | break; | ||
| 497 | ret = 0; | ||
| 498 | break; | ||
| 499 | default: | ||
| 500 | ret = sys_quotactl(cmd, special, id, addr); | ||
| 501 | } | ||
| 502 | return ret; | ||
| 503 | } | ||
| 504 | #endif | ||
diff --git a/fs/reiserfs/file.c b/fs/reiserfs/file.c index 30eebfb1b2d8..2070aeee2a52 100644 --- a/fs/reiserfs/file.c +++ b/fs/reiserfs/file.c | |||
| @@ -1305,7 +1305,6 @@ static ssize_t reiserfs_file_write(struct file *file, /* the file we are going t | |||
| 1305 | if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 && | 1305 | if (get_inode_item_key_version (inode) == KEY_FORMAT_3_5 && |
| 1306 | *ppos + count > MAX_NON_LFS) { | 1306 | *ppos + count > MAX_NON_LFS) { |
| 1307 | if (*ppos >= MAX_NON_LFS) { | 1307 | if (*ppos >= MAX_NON_LFS) { |
| 1308 | send_sig(SIGXFSZ, current, 0); | ||
| 1309 | return -EFBIG; | 1308 | return -EFBIG; |
| 1310 | } | 1309 | } |
| 1311 | if (count > MAX_NON_LFS - (unsigned long)*ppos) | 1310 | if (count > MAX_NON_LFS - (unsigned long)*ppos) |
diff --git a/fs/seq_file.c b/fs/seq_file.c index 49194a4e6b91..bbb19be260ce 100644 --- a/fs/seq_file.c +++ b/fs/seq_file.c | |||
| @@ -177,21 +177,23 @@ EXPORT_SYMBOL(seq_read); | |||
| 177 | 177 | ||
| 178 | static int traverse(struct seq_file *m, loff_t offset) | 178 | static int traverse(struct seq_file *m, loff_t offset) |
| 179 | { | 179 | { |
| 180 | loff_t pos = 0; | 180 | loff_t pos = 0, index; |
| 181 | int error = 0; | 181 | int error = 0; |
| 182 | void *p; | 182 | void *p; |
| 183 | 183 | ||
| 184 | m->version = 0; | 184 | m->version = 0; |
| 185 | m->index = 0; | 185 | index = 0; |
| 186 | m->count = m->from = 0; | 186 | m->count = m->from = 0; |
| 187 | if (!offset) | 187 | if (!offset) { |
| 188 | m->index = index; | ||
| 188 | return 0; | 189 | return 0; |
| 190 | } | ||
| 189 | if (!m->buf) { | 191 | if (!m->buf) { |
| 190 | m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); | 192 | m->buf = kmalloc(m->size = PAGE_SIZE, GFP_KERNEL); |
| 191 | if (!m->buf) | 193 | if (!m->buf) |
| 192 | return -ENOMEM; | 194 | return -ENOMEM; |
| 193 | } | 195 | } |
| 194 | p = m->op->start(m, &m->index); | 196 | p = m->op->start(m, &index); |
| 195 | while (p) { | 197 | while (p) { |
| 196 | error = PTR_ERR(p); | 198 | error = PTR_ERR(p); |
| 197 | if (IS_ERR(p)) | 199 | if (IS_ERR(p)) |
| @@ -204,15 +206,17 @@ static int traverse(struct seq_file *m, loff_t offset) | |||
| 204 | if (pos + m->count > offset) { | 206 | if (pos + m->count > offset) { |
| 205 | m->from = offset - pos; | 207 | m->from = offset - pos; |
| 206 | m->count -= m->from; | 208 | m->count -= m->from; |
| 209 | m->index = index; | ||
| 207 | break; | 210 | break; |
| 208 | } | 211 | } |
| 209 | pos += m->count; | 212 | pos += m->count; |
| 210 | m->count = 0; | 213 | m->count = 0; |
| 211 | if (pos == offset) { | 214 | if (pos == offset) { |
| 212 | m->index++; | 215 | index++; |
| 216 | m->index = index; | ||
| 213 | break; | 217 | break; |
| 214 | } | 218 | } |
| 215 | p = m->op->next(m, p, &m->index); | 219 | p = m->op->next(m, p, &index); |
| 216 | } | 220 | } |
| 217 | m->op->stop(m, p); | 221 | m->op->stop(m, p); |
| 218 | return error; | 222 | return error; |
| @@ -260,8 +264,8 @@ loff_t seq_lseek(struct file *file, loff_t offset, int origin) | |||
| 260 | } | 264 | } |
| 261 | } | 265 | } |
| 262 | } | 266 | } |
| 263 | mutex_unlock(&m->lock); | ||
| 264 | file->f_version = m->version; | 267 | file->f_version = m->version; |
| 268 | mutex_unlock(&m->lock); | ||
| 265 | return retval; | 269 | return retval; |
| 266 | } | 270 | } |
| 267 | EXPORT_SYMBOL(seq_lseek); | 271 | EXPORT_SYMBOL(seq_lseek); |
diff --git a/fs/splice.c b/fs/splice.c index 6c9828651e6f..53fc2082a468 100644 --- a/fs/splice.c +++ b/fs/splice.c | |||
| @@ -1061,8 +1061,9 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
| 1061 | 1061 | ||
| 1062 | while (len) { | 1062 | while (len) { |
| 1063 | size_t read_len; | 1063 | size_t read_len; |
| 1064 | loff_t pos = sd->pos; | ||
| 1064 | 1065 | ||
| 1065 | ret = do_splice_to(in, &sd->pos, pipe, len, flags); | 1066 | ret = do_splice_to(in, &pos, pipe, len, flags); |
| 1066 | if (unlikely(ret <= 0)) | 1067 | if (unlikely(ret <= 0)) |
| 1067 | goto out_release; | 1068 | goto out_release; |
| 1068 | 1069 | ||
| @@ -1080,6 +1081,7 @@ ssize_t splice_direct_to_actor(struct file *in, struct splice_desc *sd, | |||
| 1080 | 1081 | ||
| 1081 | bytes += ret; | 1082 | bytes += ret; |
| 1082 | len -= ret; | 1083 | len -= ret; |
| 1084 | sd->pos = pos; | ||
| 1083 | 1085 | ||
| 1084 | if (ret < read_len) | 1086 | if (ret < read_len) |
| 1085 | goto out_release; | 1087 | goto out_release; |
diff --git a/fs/super.c b/fs/super.c index 5260d620c555..fc8ebedc6bed 100644 --- a/fs/super.c +++ b/fs/super.c | |||
| @@ -884,6 +884,7 @@ vfs_kern_mount(struct file_system_type *type, int flags, const char *name, void | |||
| 884 | error = type->get_sb(type, flags, name, data, mnt); | 884 | error = type->get_sb(type, flags, name, data, mnt); |
| 885 | if (error < 0) | 885 | if (error < 0) |
| 886 | goto out_free_secdata; | 886 | goto out_free_secdata; |
| 887 | BUG_ON(!mnt->mnt_sb); | ||
| 887 | 888 | ||
| 888 | error = security_sb_kern_mount(mnt->mnt_sb, secdata); | 889 | error = security_sb_kern_mount(mnt->mnt_sb, secdata); |
| 889 | if (error) | 890 | if (error) |
diff --git a/fs/udf/crc.c b/fs/udf/crc.c index 1b82a4adc2f7..ef2bfaa19d75 100644 --- a/fs/udf/crc.c +++ b/fs/udf/crc.c | |||
| @@ -106,8 +106,8 @@ int main(void) | |||
| 106 | { | 106 | { |
| 107 | unsigned short x; | 107 | unsigned short x; |
| 108 | 108 | ||
| 109 | x = udf_crc16(bytes, sizeof bytes); | 109 | x = udf_crc(bytes, sizeof bytes); |
| 110 | printf("udf_crc16: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U); | 110 | printf("udf_crc: calculated = %4.4x, correct = %4.4x\n", x, 0x3299U); |
| 111 | 111 | ||
| 112 | return 0; | 112 | return 0; |
| 113 | } | 113 | } |
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 8206983f2ebf..10f3188738af 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c | |||
| @@ -50,7 +50,7 @@ void udf_free_inode(struct inode * inode) | |||
| 50 | else | 50 | else |
| 51 | UDF_SB_LVIDIU(sb)->numFiles = | 51 | UDF_SB_LVIDIU(sb)->numFiles = |
| 52 | cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1); | 52 | cpu_to_le32(le32_to_cpu(UDF_SB_LVIDIU(sb)->numFiles) - 1); |
| 53 | 53 | ||
| 54 | mark_buffer_dirty(sbi->s_lvidbh); | 54 | mark_buffer_dirty(sbi->s_lvidbh); |
| 55 | } | 55 | } |
| 56 | mutex_unlock(&sbi->s_alloc_mutex); | 56 | mutex_unlock(&sbi->s_alloc_mutex); |
| @@ -136,6 +136,13 @@ struct inode * udf_new_inode (struct inode *dir, int mode, int * err) | |||
| 136 | UDF_I_EFE(inode) = 0; | 136 | UDF_I_EFE(inode) = 0; |
| 137 | UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL); | 137 | UDF_I_DATA(inode) = kzalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL); |
| 138 | } | 138 | } |
| 139 | if (!UDF_I_DATA(inode)) | ||
| 140 | { | ||
| 141 | iput(inode); | ||
| 142 | *err = -ENOMEM; | ||
| 143 | mutex_unlock(&sbi->s_alloc_mutex); | ||
| 144 | return NULL; | ||
| 145 | } | ||
| 139 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) | 146 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_AD_IN_ICB)) |
| 140 | UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB; | 147 | UDF_I_ALLOCTYPE(inode) = ICBTAG_FLAG_AD_IN_ICB; |
| 141 | else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) | 148 | else if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_USE_SHORT_AD)) |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index bf7de0bdbab3..5b82e489af78 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
| @@ -49,6 +49,7 @@ MODULE_LICENSE("GPL"); | |||
| 49 | static mode_t udf_convert_permissions(struct fileEntry *); | 49 | static mode_t udf_convert_permissions(struct fileEntry *); |
| 50 | static int udf_update_inode(struct inode *, int); | 50 | static int udf_update_inode(struct inode *, int); |
| 51 | static void udf_fill_inode(struct inode *, struct buffer_head *); | 51 | static void udf_fill_inode(struct inode *, struct buffer_head *); |
| 52 | static int udf_alloc_i_data(struct inode *inode, size_t size); | ||
| 52 | static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, | 53 | static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, |
| 53 | long *, int *); | 54 | long *, int *); |
| 54 | static int8_t udf_insert_aext(struct inode *, struct extent_position, | 55 | static int8_t udf_insert_aext(struct inode *, struct extent_position, |
| @@ -734,7 +735,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, int newbl | |||
| 734 | (*c) ++; | 735 | (*c) ++; |
| 735 | (*endnum) ++; | 736 | (*endnum) ++; |
| 736 | } | 737 | } |
| 737 | 738 | ||
| 738 | laarr[curr].extLocation.logicalBlockNum = newblocknum; | 739 | laarr[curr].extLocation.logicalBlockNum = newblocknum; |
| 739 | if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) | 740 | if (etype == (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30)) |
| 740 | laarr[curr].extLocation.partitionReferenceNum = | 741 | laarr[curr].extLocation.partitionReferenceNum = |
| @@ -836,7 +837,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, | |||
| 836 | { | 837 | { |
| 837 | numalloc -= elen; | 838 | numalloc -= elen; |
| 838 | if (*endnum > (i+1)) | 839 | if (*endnum > (i+1)) |
| 839 | memmove(&laarr[i], &laarr[i+1], | 840 | memmove(&laarr[i], &laarr[i+1], |
| 840 | sizeof(long_ad) * (*endnum - (i+1))); | 841 | sizeof(long_ad) * (*endnum - (i+1))); |
| 841 | i --; | 842 | i --; |
| 842 | (*endnum) --; | 843 | (*endnum) --; |
| @@ -1024,7 +1025,7 @@ void udf_truncate(struct inode * inode) | |||
| 1024 | { | 1025 | { |
| 1025 | block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block); | 1026 | block_truncate_page(inode->i_mapping, inode->i_size, udf_get_block); |
| 1026 | udf_truncate_extents(inode); | 1027 | udf_truncate_extents(inode); |
| 1027 | } | 1028 | } |
| 1028 | 1029 | ||
| 1029 | inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb); | 1030 | inode->i_mtime = inode->i_ctime = current_fs_time(inode->i_sb); |
| 1030 | if (IS_SYNC(inode)) | 1031 | if (IS_SYNC(inode)) |
| @@ -1087,10 +1088,10 @@ __udf_read_inode(struct inode *inode) | |||
| 1087 | { | 1088 | { |
| 1088 | kernel_lb_addr loc; | 1089 | kernel_lb_addr loc; |
| 1089 | ie = (struct indirectEntry *)ibh->b_data; | 1090 | ie = (struct indirectEntry *)ibh->b_data; |
| 1090 | 1091 | ||
| 1091 | loc = lelb_to_cpu(ie->indirectICB.extLocation); | 1092 | loc = lelb_to_cpu(ie->indirectICB.extLocation); |
| 1092 | 1093 | ||
| 1093 | if (ie->indirectICB.extLength && | 1094 | if (ie->indirectICB.extLength && |
| 1094 | (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident))) | 1095 | (nbh = udf_read_ptagged(inode->i_sb, loc, 0, &ident))) |
| 1095 | { | 1096 | { |
| 1096 | if (ident == TAG_IDENT_FE || | 1097 | if (ident == TAG_IDENT_FE || |
| @@ -1156,14 +1157,22 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
| 1156 | { | 1157 | { |
| 1157 | UDF_I_EFE(inode) = 1; | 1158 | UDF_I_EFE(inode) = 1; |
| 1158 | UDF_I_USE(inode) = 0; | 1159 | UDF_I_USE(inode) = 0; |
| 1159 | UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry), GFP_KERNEL); | 1160 | if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry))) |
| 1161 | { | ||
| 1162 | make_bad_inode(inode); | ||
| 1163 | return; | ||
| 1164 | } | ||
| 1160 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); | 1165 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct extendedFileEntry), inode->i_sb->s_blocksize - sizeof(struct extendedFileEntry)); |
| 1161 | } | 1166 | } |
| 1162 | else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) | 1167 | else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_FE) |
| 1163 | { | 1168 | { |
| 1164 | UDF_I_EFE(inode) = 0; | 1169 | UDF_I_EFE(inode) = 0; |
| 1165 | UDF_I_USE(inode) = 0; | 1170 | UDF_I_USE(inode) = 0; |
| 1166 | UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct fileEntry), GFP_KERNEL); | 1171 | if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct fileEntry))) |
| 1172 | { | ||
| 1173 | make_bad_inode(inode); | ||
| 1174 | return; | ||
| 1175 | } | ||
| 1167 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry)); | 1176 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct fileEntry), inode->i_sb->s_blocksize - sizeof(struct fileEntry)); |
| 1168 | } | 1177 | } |
| 1169 | else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) | 1178 | else if (le16_to_cpu(fe->descTag.tagIdent) == TAG_IDENT_USE) |
| @@ -1173,7 +1182,11 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
| 1173 | UDF_I_LENALLOC(inode) = | 1182 | UDF_I_LENALLOC(inode) = |
| 1174 | le32_to_cpu( | 1183 | le32_to_cpu( |
| 1175 | ((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs); | 1184 | ((struct unallocSpaceEntry *)bh->b_data)->lengthAllocDescs); |
| 1176 | UDF_I_DATA(inode) = kmalloc(inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry), GFP_KERNEL); | 1185 | if (udf_alloc_i_data(inode, inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry))) |
| 1186 | { | ||
| 1187 | make_bad_inode(inode); | ||
| 1188 | return; | ||
| 1189 | } | ||
| 1177 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); | 1190 | memcpy(UDF_I_DATA(inode), bh->b_data + sizeof(struct unallocSpaceEntry), inode->i_sb->s_blocksize - sizeof(struct unallocSpaceEntry)); |
| 1178 | return; | 1191 | return; |
| 1179 | } | 1192 | } |
| @@ -1191,7 +1204,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
| 1191 | inode->i_nlink = le16_to_cpu(fe->fileLinkCount); | 1204 | inode->i_nlink = le16_to_cpu(fe->fileLinkCount); |
| 1192 | if (!inode->i_nlink) | 1205 | if (!inode->i_nlink) |
| 1193 | inode->i_nlink = 1; | 1206 | inode->i_nlink = 1; |
| 1194 | 1207 | ||
| 1195 | inode->i_size = le64_to_cpu(fe->informationLength); | 1208 | inode->i_size = le64_to_cpu(fe->informationLength); |
| 1196 | UDF_I_LENEXTENTS(inode) = inode->i_size; | 1209 | UDF_I_LENEXTENTS(inode) = inode->i_size; |
| 1197 | 1210 | ||
| @@ -1243,7 +1256,7 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
| 1243 | } | 1256 | } |
| 1244 | else | 1257 | else |
| 1245 | { | 1258 | { |
| 1246 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << | 1259 | inode->i_blocks = le64_to_cpu(efe->logicalBlocksRecorded) << |
| 1247 | (inode->i_sb->s_blocksize_bits - 9); | 1260 | (inode->i_sb->s_blocksize_bits - 9); |
| 1248 | 1261 | ||
| 1249 | if ( udf_stamp_to_time(&convtime, &convtime_usec, | 1262 | if ( udf_stamp_to_time(&convtime, &convtime_usec, |
| @@ -1374,6 +1387,20 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
| 1374 | } | 1387 | } |
| 1375 | } | 1388 | } |
| 1376 | 1389 | ||
| 1390 | static int udf_alloc_i_data(struct inode *inode, size_t size) | ||
| 1391 | { | ||
| 1392 | UDF_I_DATA(inode) = kmalloc(size, GFP_KERNEL); | ||
| 1393 | |||
| 1394 | if (!UDF_I_DATA(inode)) | ||
| 1395 | { | ||
| 1396 | printk(KERN_ERR "udf:udf_alloc_i_data (ino %ld) no free memory\n", | ||
| 1397 | inode->i_ino); | ||
| 1398 | return -ENOMEM; | ||
| 1399 | } | ||
| 1400 | |||
| 1401 | return 0; | ||
| 1402 | } | ||
| 1403 | |||
| 1377 | static mode_t | 1404 | static mode_t |
| 1378 | udf_convert_permissions(struct fileEntry *fe) | 1405 | udf_convert_permissions(struct fileEntry *fe) |
| 1379 | { | 1406 | { |
| @@ -2072,7 +2099,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
| 2072 | mark_buffer_dirty_inode(oepos.bh, inode); | 2099 | mark_buffer_dirty_inode(oepos.bh, inode); |
| 2073 | } | 2100 | } |
| 2074 | } | 2101 | } |
| 2075 | 2102 | ||
| 2076 | brelse(epos.bh); | 2103 | brelse(epos.bh); |
| 2077 | brelse(oepos.bh); | 2104 | brelse(oepos.bh); |
| 2078 | return (elen >> 30); | 2105 | return (elen >> 30); |
diff --git a/fs/ufs/super.c b/fs/ufs/super.c index 22ff6ed55ce9..2b3011689e89 100644 --- a/fs/ufs/super.c +++ b/fs/ufs/super.c | |||
| @@ -87,6 +87,7 @@ | |||
| 87 | #include <linux/smp_lock.h> | 87 | #include <linux/smp_lock.h> |
| 88 | #include <linux/buffer_head.h> | 88 | #include <linux/buffer_head.h> |
| 89 | #include <linux/vfs.h> | 89 | #include <linux/vfs.h> |
| 90 | #include <linux/log2.h> | ||
| 90 | 91 | ||
| 91 | #include "swab.h" | 92 | #include "swab.h" |
| 92 | #include "util.h" | 93 | #include "util.h" |
| @@ -854,7 +855,7 @@ magic_found: | |||
| 854 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); | 855 | uspi->s_fmask = fs32_to_cpu(sb, usb1->fs_fmask); |
| 855 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); | 856 | uspi->s_fshift = fs32_to_cpu(sb, usb1->fs_fshift); |
| 856 | 857 | ||
| 857 | if (uspi->s_fsize & (uspi->s_fsize - 1)) { | 858 | if (!is_power_of_2(uspi->s_fsize)) { |
| 858 | printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n", | 859 | printk(KERN_ERR "ufs_read_super: fragment size %u is not a power of 2\n", |
| 859 | uspi->s_fsize); | 860 | uspi->s_fsize); |
| 860 | goto failed; | 861 | goto failed; |
| @@ -869,7 +870,7 @@ magic_found: | |||
| 869 | uspi->s_fsize); | 870 | uspi->s_fsize); |
| 870 | goto failed; | 871 | goto failed; |
| 871 | } | 872 | } |
| 872 | if (uspi->s_bsize & (uspi->s_bsize - 1)) { | 873 | if (!is_power_of_2(uspi->s_bsize)) { |
| 873 | printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n", | 874 | printk(KERN_ERR "ufs_read_super: block size %u is not a power of 2\n", |
| 874 | uspi->s_bsize); | 875 | uspi->s_bsize); |
| 875 | goto failed; | 876 | goto failed; |
