diff options
Diffstat (limited to 'fs')
70 files changed, 2260 insertions, 767 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/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; |