1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * Copyright (C) International Business Machines Corp., 2000-2004 |
4 | * Portions Copyright (C) Christoph Hellwig, 2001-2002 |
5 | */ |
6 | |
7 | #include <linux/fs.h> |
8 | #include <linux/module.h> |
9 | #include <linux/parser.h> |
10 | #include <linux/completion.h> |
11 | #include <linux/vfs.h> |
12 | #include <linux/quotaops.h> |
13 | #include <linux/mount.h> |
14 | #include <linux/moduleparam.h> |
15 | #include <linux/kthread.h> |
16 | #include <linux/posix_acl.h> |
17 | #include <linux/buffer_head.h> |
18 | #include <linux/exportfs.h> |
19 | #include <linux/crc32.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/uaccess.h> |
22 | #include <linux/seq_file.h> |
23 | #include <linux/blkdev.h> |
24 | |
25 | #include "jfs_incore.h" |
26 | #include "jfs_filsys.h" |
27 | #include "jfs_inode.h" |
28 | #include "jfs_metapage.h" |
29 | #include "jfs_superblock.h" |
30 | #include "jfs_dmap.h" |
31 | #include "jfs_imap.h" |
32 | #include "jfs_acl.h" |
33 | #include "jfs_debug.h" |
34 | #include "jfs_xattr.h" |
35 | #include "jfs_dinode.h" |
36 | |
37 | MODULE_DESCRIPTION("The Journaled Filesystem (JFS)" ); |
38 | MODULE_AUTHOR("Steve Best/Dave Kleikamp/Barry Arndt, IBM" ); |
39 | MODULE_LICENSE("GPL" ); |
40 | |
41 | static struct kmem_cache *jfs_inode_cachep; |
42 | |
43 | static const struct super_operations jfs_super_operations; |
44 | static const struct export_operations jfs_export_operations; |
45 | static struct file_system_type jfs_fs_type; |
46 | |
47 | #define MAX_COMMIT_THREADS 64 |
48 | static int commit_threads; |
49 | module_param(commit_threads, int, 0); |
50 | MODULE_PARM_DESC(commit_threads, "Number of commit threads" ); |
51 | |
52 | static struct task_struct *jfsCommitThread[MAX_COMMIT_THREADS]; |
53 | struct task_struct *jfsIOthread; |
54 | struct task_struct *jfsSyncThread; |
55 | |
56 | #ifdef CONFIG_JFS_DEBUG |
57 | int jfsloglevel = JFS_LOGLEVEL_WARN; |
58 | module_param(jfsloglevel, int, 0644); |
59 | MODULE_PARM_DESC(jfsloglevel, "Specify JFS loglevel (0, 1 or 2)" ); |
60 | #endif |
61 | |
62 | static void jfs_handle_error(struct super_block *sb) |
63 | { |
64 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
65 | |
66 | if (sb_rdonly(sb)) |
67 | return; |
68 | |
69 | updateSuper(sb, FM_DIRTY); |
70 | |
71 | if (sbi->flag & JFS_ERR_PANIC) |
72 | panic(fmt: "JFS (device %s): panic forced after error\n" , |
73 | sb->s_id); |
74 | else if (sbi->flag & JFS_ERR_REMOUNT_RO) { |
75 | jfs_err("ERROR: (device %s): remounting filesystem as read-only" , |
76 | sb->s_id); |
77 | sb->s_flags |= SB_RDONLY; |
78 | } |
79 | |
80 | /* nothing is done for continue beyond marking the superblock dirty */ |
81 | } |
82 | |
83 | void jfs_error(struct super_block *sb, const char *fmt, ...) |
84 | { |
85 | struct va_format vaf; |
86 | va_list args; |
87 | |
88 | va_start(args, fmt); |
89 | |
90 | vaf.fmt = fmt; |
91 | vaf.va = &args; |
92 | |
93 | pr_err("ERROR: (device %s): %ps: %pV\n" , |
94 | sb->s_id, __builtin_return_address(0), &vaf); |
95 | |
96 | va_end(args); |
97 | |
98 | jfs_handle_error(sb); |
99 | } |
100 | |
101 | static struct inode *jfs_alloc_inode(struct super_block *sb) |
102 | { |
103 | struct jfs_inode_info *jfs_inode; |
104 | |
105 | jfs_inode = alloc_inode_sb(sb, cache: jfs_inode_cachep, GFP_NOFS); |
106 | if (!jfs_inode) |
107 | return NULL; |
108 | #ifdef CONFIG_QUOTA |
109 | memset(&jfs_inode->i_dquot, 0, sizeof(jfs_inode->i_dquot)); |
110 | #endif |
111 | return &jfs_inode->vfs_inode; |
112 | } |
113 | |
114 | static void jfs_free_inode(struct inode *inode) |
115 | { |
116 | kmem_cache_free(s: jfs_inode_cachep, objp: JFS_IP(inode)); |
117 | } |
118 | |
119 | static int jfs_statfs(struct dentry *dentry, struct kstatfs *buf) |
120 | { |
121 | struct jfs_sb_info *sbi = JFS_SBI(sb: dentry->d_sb); |
122 | s64 maxinodes; |
123 | struct inomap *imap = JFS_IP(inode: sbi->ipimap)->i_imap; |
124 | |
125 | jfs_info("In jfs_statfs" ); |
126 | buf->f_type = JFS_SUPER_MAGIC; |
127 | buf->f_bsize = sbi->bsize; |
128 | buf->f_blocks = sbi->bmap->db_mapsize; |
129 | buf->f_bfree = sbi->bmap->db_nfree; |
130 | buf->f_bavail = sbi->bmap->db_nfree; |
131 | /* |
132 | * If we really return the number of allocated & free inodes, some |
133 | * applications will fail because they won't see enough free inodes. |
134 | * We'll try to calculate some guess as to how many inodes we can |
135 | * really allocate |
136 | * |
137 | * buf->f_files = atomic_read(&imap->im_numinos); |
138 | * buf->f_ffree = atomic_read(&imap->im_numfree); |
139 | */ |
140 | maxinodes = min((s64) atomic_read(&imap->im_numinos) + |
141 | ((sbi->bmap->db_nfree >> imap->im_l2nbperiext) |
142 | << L2INOSPEREXT), (s64) 0xffffffffLL); |
143 | buf->f_files = maxinodes; |
144 | buf->f_ffree = maxinodes - (atomic_read(v: &imap->im_numinos) - |
145 | atomic_read(v: &imap->im_numfree)); |
146 | buf->f_fsid.val[0] = crc32_le(crc: 0, p: (char *)&sbi->uuid, |
147 | len: sizeof(sbi->uuid)/2); |
148 | buf->f_fsid.val[1] = crc32_le(crc: 0, |
149 | p: (char *)&sbi->uuid + sizeof(sbi->uuid)/2, |
150 | len: sizeof(sbi->uuid)/2); |
151 | |
152 | buf->f_namelen = JFS_NAME_MAX; |
153 | return 0; |
154 | } |
155 | |
156 | #ifdef CONFIG_QUOTA |
157 | static int jfs_quota_off(struct super_block *sb, int type); |
158 | static int jfs_quota_on(struct super_block *sb, int type, int format_id, |
159 | const struct path *path); |
160 | |
161 | static void jfs_quota_off_umount(struct super_block *sb) |
162 | { |
163 | int type; |
164 | |
165 | for (type = 0; type < MAXQUOTAS; type++) |
166 | jfs_quota_off(sb, type); |
167 | } |
168 | |
169 | static const struct quotactl_ops jfs_quotactl_ops = { |
170 | .quota_on = jfs_quota_on, |
171 | .quota_off = jfs_quota_off, |
172 | .quota_sync = dquot_quota_sync, |
173 | .get_state = dquot_get_state, |
174 | .set_info = dquot_set_dqinfo, |
175 | .get_dqblk = dquot_get_dqblk, |
176 | .set_dqblk = dquot_set_dqblk, |
177 | .get_nextdqblk = dquot_get_next_dqblk, |
178 | }; |
179 | #else |
180 | static inline void jfs_quota_off_umount(struct super_block *sb) |
181 | { |
182 | } |
183 | #endif |
184 | |
185 | static void jfs_put_super(struct super_block *sb) |
186 | { |
187 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
188 | int rc; |
189 | |
190 | jfs_info("In jfs_put_super" ); |
191 | |
192 | jfs_quota_off_umount(sb); |
193 | |
194 | rc = jfs_umount(sb); |
195 | if (rc) |
196 | jfs_err("jfs_umount failed with return code %d" , rc); |
197 | |
198 | unload_nls(sbi->nls_tab); |
199 | |
200 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); |
201 | iput(sbi->direct_inode); |
202 | |
203 | kfree(objp: sbi); |
204 | } |
205 | |
206 | enum { |
207 | Opt_integrity, Opt_nointegrity, Opt_iocharset, Opt_resize, |
208 | Opt_resize_nosize, Opt_errors, Opt_ignore, Opt_err, Opt_quota, |
209 | Opt_usrquota, Opt_grpquota, Opt_uid, Opt_gid, Opt_umask, |
210 | Opt_discard, Opt_nodiscard, Opt_discard_minblk |
211 | }; |
212 | |
213 | static const match_table_t tokens = { |
214 | {Opt_integrity, "integrity" }, |
215 | {Opt_nointegrity, "nointegrity" }, |
216 | {Opt_iocharset, "iocharset=%s" }, |
217 | {Opt_resize, "resize=%u" }, |
218 | {Opt_resize_nosize, "resize" }, |
219 | {Opt_errors, "errors=%s" }, |
220 | {Opt_ignore, "noquota" }, |
221 | {Opt_quota, "quota" }, |
222 | {Opt_usrquota, "usrquota" }, |
223 | {Opt_grpquota, "grpquota" }, |
224 | {Opt_uid, "uid=%u" }, |
225 | {Opt_gid, "gid=%u" }, |
226 | {Opt_umask, "umask=%u" }, |
227 | {Opt_discard, "discard" }, |
228 | {Opt_nodiscard, "nodiscard" }, |
229 | {Opt_discard_minblk, "discard=%u" }, |
230 | {Opt_err, NULL} |
231 | }; |
232 | |
233 | static int parse_options(char *options, struct super_block *sb, s64 *newLVSize, |
234 | int *flag) |
235 | { |
236 | void *nls_map = (void *)-1; /* -1: no change; NULL: none */ |
237 | char *p; |
238 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
239 | |
240 | *newLVSize = 0; |
241 | |
242 | if (!options) |
243 | return 1; |
244 | |
245 | while ((p = strsep(&options, "," )) != NULL) { |
246 | substring_t args[MAX_OPT_ARGS]; |
247 | int token; |
248 | if (!*p) |
249 | continue; |
250 | |
251 | token = match_token(p, table: tokens, args); |
252 | switch (token) { |
253 | case Opt_integrity: |
254 | *flag &= ~JFS_NOINTEGRITY; |
255 | break; |
256 | case Opt_nointegrity: |
257 | *flag |= JFS_NOINTEGRITY; |
258 | break; |
259 | case Opt_ignore: |
260 | /* Silently ignore the quota options */ |
261 | /* Don't do anything ;-) */ |
262 | break; |
263 | case Opt_iocharset: |
264 | if (nls_map && nls_map != (void *) -1) |
265 | unload_nls(nls_map); |
266 | if (!strcmp(args[0].from, "none" )) |
267 | nls_map = NULL; |
268 | else { |
269 | nls_map = load_nls(charset: args[0].from); |
270 | if (!nls_map) { |
271 | pr_err("JFS: charset not found\n" ); |
272 | goto cleanup; |
273 | } |
274 | } |
275 | break; |
276 | case Opt_resize: |
277 | { |
278 | char *resize = args[0].from; |
279 | int rc = kstrtoll(s: resize, base: 0, res: newLVSize); |
280 | |
281 | if (rc) |
282 | goto cleanup; |
283 | break; |
284 | } |
285 | case Opt_resize_nosize: |
286 | { |
287 | *newLVSize = sb_bdev_nr_blocks(sb); |
288 | if (*newLVSize == 0) |
289 | pr_err("JFS: Cannot determine volume size\n" ); |
290 | break; |
291 | } |
292 | case Opt_errors: |
293 | { |
294 | char *errors = args[0].from; |
295 | if (!errors || !*errors) |
296 | goto cleanup; |
297 | if (!strcmp(errors, "continue" )) { |
298 | *flag &= ~JFS_ERR_REMOUNT_RO; |
299 | *flag &= ~JFS_ERR_PANIC; |
300 | *flag |= JFS_ERR_CONTINUE; |
301 | } else if (!strcmp(errors, "remount-ro" )) { |
302 | *flag &= ~JFS_ERR_CONTINUE; |
303 | *flag &= ~JFS_ERR_PANIC; |
304 | *flag |= JFS_ERR_REMOUNT_RO; |
305 | } else if (!strcmp(errors, "panic" )) { |
306 | *flag &= ~JFS_ERR_CONTINUE; |
307 | *flag &= ~JFS_ERR_REMOUNT_RO; |
308 | *flag |= JFS_ERR_PANIC; |
309 | } else { |
310 | pr_err("JFS: %s is an invalid error handler\n" , |
311 | errors); |
312 | goto cleanup; |
313 | } |
314 | break; |
315 | } |
316 | |
317 | #ifdef CONFIG_QUOTA |
318 | case Opt_quota: |
319 | case Opt_usrquota: |
320 | *flag |= JFS_USRQUOTA; |
321 | break; |
322 | case Opt_grpquota: |
323 | *flag |= JFS_GRPQUOTA; |
324 | break; |
325 | #else |
326 | case Opt_usrquota: |
327 | case Opt_grpquota: |
328 | case Opt_quota: |
329 | pr_err("JFS: quota operations not supported\n" ); |
330 | break; |
331 | #endif |
332 | case Opt_uid: |
333 | { |
334 | char *uid = args[0].from; |
335 | uid_t val; |
336 | int rc = kstrtouint(s: uid, base: 0, res: &val); |
337 | |
338 | if (rc) |
339 | goto cleanup; |
340 | sbi->uid = make_kuid(current_user_ns(), uid: val); |
341 | if (!uid_valid(uid: sbi->uid)) |
342 | goto cleanup; |
343 | break; |
344 | } |
345 | |
346 | case Opt_gid: |
347 | { |
348 | char *gid = args[0].from; |
349 | gid_t val; |
350 | int rc = kstrtouint(s: gid, base: 0, res: &val); |
351 | |
352 | if (rc) |
353 | goto cleanup; |
354 | sbi->gid = make_kgid(current_user_ns(), gid: val); |
355 | if (!gid_valid(gid: sbi->gid)) |
356 | goto cleanup; |
357 | break; |
358 | } |
359 | |
360 | case Opt_umask: |
361 | { |
362 | char *umask = args[0].from; |
363 | int rc = kstrtouint(s: umask, base: 8, res: &sbi->umask); |
364 | |
365 | if (rc) |
366 | goto cleanup; |
367 | if (sbi->umask & ~0777) { |
368 | pr_err("JFS: Invalid value of umask\n" ); |
369 | goto cleanup; |
370 | } |
371 | break; |
372 | } |
373 | |
374 | case Opt_discard: |
375 | /* if set to 1, even copying files will cause |
376 | * trimming :O |
377 | * -> user has more control over the online trimming |
378 | */ |
379 | sbi->minblks_trim = 64; |
380 | if (bdev_max_discard_sectors(bdev: sb->s_bdev)) |
381 | *flag |= JFS_DISCARD; |
382 | else |
383 | pr_err("JFS: discard option not supported on device\n" ); |
384 | break; |
385 | |
386 | case Opt_nodiscard: |
387 | *flag &= ~JFS_DISCARD; |
388 | break; |
389 | |
390 | case Opt_discard_minblk: |
391 | { |
392 | char *minblks_trim = args[0].from; |
393 | int rc; |
394 | if (bdev_max_discard_sectors(bdev: sb->s_bdev)) { |
395 | *flag |= JFS_DISCARD; |
396 | rc = kstrtouint(s: minblks_trim, base: 0, |
397 | res: &sbi->minblks_trim); |
398 | if (rc) |
399 | goto cleanup; |
400 | } else |
401 | pr_err("JFS: discard option not supported on device\n" ); |
402 | break; |
403 | } |
404 | |
405 | default: |
406 | printk("jfs: Unrecognized mount option \"%s\" or missing value\n" , |
407 | p); |
408 | goto cleanup; |
409 | } |
410 | } |
411 | |
412 | if (nls_map != (void *) -1) { |
413 | /* Discard old (if remount) */ |
414 | unload_nls(sbi->nls_tab); |
415 | sbi->nls_tab = nls_map; |
416 | } |
417 | return 1; |
418 | |
419 | cleanup: |
420 | if (nls_map && nls_map != (void *) -1) |
421 | unload_nls(nls_map); |
422 | return 0; |
423 | } |
424 | |
425 | static int jfs_remount(struct super_block *sb, int *flags, char *data) |
426 | { |
427 | s64 newLVSize = 0; |
428 | int rc = 0; |
429 | int flag = JFS_SBI(sb)->flag; |
430 | int ret; |
431 | |
432 | sync_filesystem(sb); |
433 | if (!parse_options(options: data, sb, newLVSize: &newLVSize, flag: &flag)) |
434 | return -EINVAL; |
435 | |
436 | if (newLVSize) { |
437 | if (sb_rdonly(sb)) { |
438 | pr_err("JFS: resize requires volume to be mounted read-write\n" ); |
439 | return -EROFS; |
440 | } |
441 | rc = jfs_extendfs(sb, newLVSize, 0); |
442 | if (rc) |
443 | return rc; |
444 | } |
445 | |
446 | if (sb_rdonly(sb) && !(*flags & SB_RDONLY)) { |
447 | /* |
448 | * Invalidate any previously read metadata. fsck may have |
449 | * changed the on-disk data since we mounted r/o |
450 | */ |
451 | truncate_inode_pages(JFS_SBI(sb)->direct_inode->i_mapping, 0); |
452 | |
453 | JFS_SBI(sb)->flag = flag; |
454 | ret = jfs_mount_rw(sb, 1); |
455 | |
456 | /* mark the fs r/w for quota activity */ |
457 | sb->s_flags &= ~SB_RDONLY; |
458 | |
459 | dquot_resume(sb, type: -1); |
460 | return ret; |
461 | } |
462 | if (!sb_rdonly(sb) && (*flags & SB_RDONLY)) { |
463 | rc = dquot_suspend(sb, type: -1); |
464 | if (rc < 0) |
465 | return rc; |
466 | rc = jfs_umount_rw(sb); |
467 | JFS_SBI(sb)->flag = flag; |
468 | return rc; |
469 | } |
470 | if ((JFS_SBI(sb)->flag & JFS_NOINTEGRITY) != (flag & JFS_NOINTEGRITY)) |
471 | if (!sb_rdonly(sb)) { |
472 | rc = jfs_umount_rw(sb); |
473 | if (rc) |
474 | return rc; |
475 | |
476 | JFS_SBI(sb)->flag = flag; |
477 | ret = jfs_mount_rw(sb, 1); |
478 | return ret; |
479 | } |
480 | JFS_SBI(sb)->flag = flag; |
481 | |
482 | return 0; |
483 | } |
484 | |
485 | static int jfs_fill_super(struct super_block *sb, void *data, int silent) |
486 | { |
487 | struct jfs_sb_info *sbi; |
488 | struct inode *inode; |
489 | int rc; |
490 | s64 newLVSize = 0; |
491 | int flag, ret = -EINVAL; |
492 | |
493 | jfs_info("In jfs_read_super: s_flags=0x%lx" , sb->s_flags); |
494 | |
495 | sbi = kzalloc(size: sizeof(struct jfs_sb_info), GFP_KERNEL); |
496 | if (!sbi) |
497 | return -ENOMEM; |
498 | |
499 | sb->s_fs_info = sbi; |
500 | sb->s_max_links = JFS_LINK_MAX; |
501 | sb->s_time_min = 0; |
502 | sb->s_time_max = U32_MAX; |
503 | sbi->sb = sb; |
504 | sbi->uid = INVALID_UID; |
505 | sbi->gid = INVALID_GID; |
506 | sbi->umask = -1; |
507 | |
508 | /* initialize the mount flag and determine the default error handler */ |
509 | flag = JFS_ERR_REMOUNT_RO; |
510 | |
511 | if (!parse_options(options: (char *) data, sb, newLVSize: &newLVSize, flag: &flag)) |
512 | goto out_kfree; |
513 | sbi->flag = flag; |
514 | |
515 | #ifdef CONFIG_JFS_POSIX_ACL |
516 | sb->s_flags |= SB_POSIXACL; |
517 | #endif |
518 | |
519 | if (newLVSize) { |
520 | pr_err("resize option for remount only\n" ); |
521 | goto out_kfree; |
522 | } |
523 | |
524 | /* |
525 | * Initialize blocksize to 4K. |
526 | */ |
527 | sb_set_blocksize(sb, PSIZE); |
528 | |
529 | /* |
530 | * Set method vectors. |
531 | */ |
532 | sb->s_op = &jfs_super_operations; |
533 | sb->s_export_op = &jfs_export_operations; |
534 | sb->s_xattr = jfs_xattr_handlers; |
535 | #ifdef CONFIG_QUOTA |
536 | sb->dq_op = &dquot_operations; |
537 | sb->s_qcop = &jfs_quotactl_ops; |
538 | sb->s_quota_types = QTYPE_MASK_USR | QTYPE_MASK_GRP; |
539 | #endif |
540 | |
541 | /* |
542 | * Initialize direct-mapping inode/address-space |
543 | */ |
544 | inode = new_inode(sb); |
545 | if (inode == NULL) { |
546 | ret = -ENOMEM; |
547 | goto out_unload; |
548 | } |
549 | inode->i_size = bdev_nr_bytes(bdev: sb->s_bdev); |
550 | inode->i_mapping->a_ops = &jfs_metapage_aops; |
551 | inode_fake_hash(inode); |
552 | mapping_set_gfp_mask(m: inode->i_mapping, GFP_NOFS); |
553 | |
554 | sbi->direct_inode = inode; |
555 | |
556 | rc = jfs_mount(sb); |
557 | if (rc) { |
558 | if (!silent) |
559 | jfs_err("jfs_mount failed w/return code = %d" , rc); |
560 | goto out_mount_failed; |
561 | } |
562 | if (sb_rdonly(sb)) |
563 | sbi->log = NULL; |
564 | else { |
565 | rc = jfs_mount_rw(sb, 0); |
566 | if (rc) { |
567 | if (!silent) { |
568 | jfs_err("jfs_mount_rw failed, return code = %d" , |
569 | rc); |
570 | } |
571 | goto out_no_rw; |
572 | } |
573 | } |
574 | |
575 | sb->s_magic = JFS_SUPER_MAGIC; |
576 | |
577 | if (sbi->mntflag & JFS_OS2) |
578 | sb->s_d_op = &jfs_ci_dentry_operations; |
579 | |
580 | inode = jfs_iget(sb, ROOT_I); |
581 | if (IS_ERR(ptr: inode)) { |
582 | ret = PTR_ERR(ptr: inode); |
583 | goto out_no_rw; |
584 | } |
585 | sb->s_root = d_make_root(inode); |
586 | if (!sb->s_root) |
587 | goto out_no_root; |
588 | |
589 | /* logical blocks are represented by 40 bits in pxd_t, etc. |
590 | * and page cache is indexed by long |
591 | */ |
592 | sb->s_maxbytes = min(((loff_t)sb->s_blocksize) << 40, MAX_LFS_FILESIZE); |
593 | sb->s_time_gran = 1; |
594 | return 0; |
595 | |
596 | out_no_root: |
597 | jfs_err("jfs_read_super: get root dentry failed" ); |
598 | |
599 | out_no_rw: |
600 | rc = jfs_umount(sb); |
601 | if (rc) |
602 | jfs_err("jfs_umount failed with return code %d" , rc); |
603 | out_mount_failed: |
604 | filemap_write_and_wait(mapping: sbi->direct_inode->i_mapping); |
605 | truncate_inode_pages(sbi->direct_inode->i_mapping, 0); |
606 | make_bad_inode(sbi->direct_inode); |
607 | iput(sbi->direct_inode); |
608 | sbi->direct_inode = NULL; |
609 | out_unload: |
610 | unload_nls(sbi->nls_tab); |
611 | out_kfree: |
612 | kfree(objp: sbi); |
613 | return ret; |
614 | } |
615 | |
616 | static int jfs_freeze(struct super_block *sb) |
617 | { |
618 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
619 | struct jfs_log *log = sbi->log; |
620 | int rc = 0; |
621 | |
622 | if (!sb_rdonly(sb)) { |
623 | txQuiesce(sb); |
624 | rc = lmLogShutdown(log); |
625 | if (rc) { |
626 | jfs_error(sb, fmt: "lmLogShutdown failed\n" ); |
627 | |
628 | /* let operations fail rather than hang */ |
629 | txResume(sb); |
630 | |
631 | return rc; |
632 | } |
633 | rc = updateSuper(sb, FM_CLEAN); |
634 | if (rc) { |
635 | jfs_err("jfs_freeze: updateSuper failed" ); |
636 | /* |
637 | * Don't fail here. Everything succeeded except |
638 | * marking the superblock clean, so there's really |
639 | * no harm in leaving it frozen for now. |
640 | */ |
641 | } |
642 | } |
643 | return 0; |
644 | } |
645 | |
646 | static int jfs_unfreeze(struct super_block *sb) |
647 | { |
648 | struct jfs_sb_info *sbi = JFS_SBI(sb); |
649 | struct jfs_log *log = sbi->log; |
650 | int rc = 0; |
651 | |
652 | if (!sb_rdonly(sb)) { |
653 | rc = updateSuper(sb, FM_MOUNT); |
654 | if (rc) { |
655 | jfs_error(sb, fmt: "updateSuper failed\n" ); |
656 | goto out; |
657 | } |
658 | rc = lmLogInit(log); |
659 | if (rc) |
660 | jfs_error(sb, fmt: "lmLogInit failed\n" ); |
661 | out: |
662 | txResume(sb); |
663 | } |
664 | return rc; |
665 | } |
666 | |
667 | static struct dentry *jfs_do_mount(struct file_system_type *fs_type, |
668 | int flags, const char *dev_name, void *data) |
669 | { |
670 | return mount_bdev(fs_type, flags, dev_name, data, fill_super: jfs_fill_super); |
671 | } |
672 | |
673 | static int jfs_sync_fs(struct super_block *sb, int wait) |
674 | { |
675 | struct jfs_log *log = JFS_SBI(sb)->log; |
676 | |
677 | /* log == NULL indicates read-only mount */ |
678 | if (log) { |
679 | /* |
680 | * Write quota structures to quota file, sync_blockdev() will |
681 | * write them to disk later |
682 | */ |
683 | dquot_writeback_dquots(sb, type: -1); |
684 | jfs_flush_journal(log, wait); |
685 | jfs_syncpt(log, hard_sync: 0); |
686 | } |
687 | |
688 | return 0; |
689 | } |
690 | |
691 | static int jfs_show_options(struct seq_file *seq, struct dentry *root) |
692 | { |
693 | struct jfs_sb_info *sbi = JFS_SBI(sb: root->d_sb); |
694 | |
695 | if (uid_valid(uid: sbi->uid)) |
696 | seq_printf(m: seq, fmt: ",uid=%d" , from_kuid(to: &init_user_ns, uid: sbi->uid)); |
697 | if (gid_valid(gid: sbi->gid)) |
698 | seq_printf(m: seq, fmt: ",gid=%d" , from_kgid(to: &init_user_ns, gid: sbi->gid)); |
699 | if (sbi->umask != -1) |
700 | seq_printf(m: seq, fmt: ",umask=%03o" , sbi->umask); |
701 | if (sbi->flag & JFS_NOINTEGRITY) |
702 | seq_puts(m: seq, s: ",nointegrity" ); |
703 | if (sbi->flag & JFS_DISCARD) |
704 | seq_printf(m: seq, fmt: ",discard=%u" , sbi->minblks_trim); |
705 | if (sbi->nls_tab) |
706 | seq_printf(m: seq, fmt: ",iocharset=%s" , sbi->nls_tab->charset); |
707 | if (sbi->flag & JFS_ERR_CONTINUE) |
708 | seq_printf(m: seq, fmt: ",errors=continue" ); |
709 | if (sbi->flag & JFS_ERR_PANIC) |
710 | seq_printf(m: seq, fmt: ",errors=panic" ); |
711 | |
712 | #ifdef CONFIG_QUOTA |
713 | if (sbi->flag & JFS_USRQUOTA) |
714 | seq_puts(m: seq, s: ",usrquota" ); |
715 | |
716 | if (sbi->flag & JFS_GRPQUOTA) |
717 | seq_puts(m: seq, s: ",grpquota" ); |
718 | #endif |
719 | |
720 | return 0; |
721 | } |
722 | |
723 | #ifdef CONFIG_QUOTA |
724 | |
725 | /* Read data from quotafile - avoid pagecache and such because we cannot afford |
726 | * acquiring the locks... As quota files are never truncated and quota code |
727 | * itself serializes the operations (and no one else should touch the files) |
728 | * we don't have to be afraid of races */ |
729 | static ssize_t jfs_quota_read(struct super_block *sb, int type, char *data, |
730 | size_t len, loff_t off) |
731 | { |
732 | struct inode *inode = sb_dqopt(sb)->files[type]; |
733 | sector_t blk = off >> sb->s_blocksize_bits; |
734 | int err = 0; |
735 | int offset = off & (sb->s_blocksize - 1); |
736 | int tocopy; |
737 | size_t toread; |
738 | struct buffer_head tmp_bh; |
739 | struct buffer_head *bh; |
740 | loff_t i_size = i_size_read(inode); |
741 | |
742 | if (off > i_size) |
743 | return 0; |
744 | if (off+len > i_size) |
745 | len = i_size-off; |
746 | toread = len; |
747 | while (toread > 0) { |
748 | tocopy = min_t(size_t, sb->s_blocksize - offset, toread); |
749 | |
750 | tmp_bh.b_state = 0; |
751 | tmp_bh.b_size = i_blocksize(node: inode); |
752 | err = jfs_get_block(inode, blk, &tmp_bh, 0); |
753 | if (err) |
754 | return err; |
755 | if (!buffer_mapped(bh: &tmp_bh)) /* A hole? */ |
756 | memset(data, 0, tocopy); |
757 | else { |
758 | bh = sb_bread(sb, block: tmp_bh.b_blocknr); |
759 | if (!bh) |
760 | return -EIO; |
761 | memcpy(data, bh->b_data+offset, tocopy); |
762 | brelse(bh); |
763 | } |
764 | offset = 0; |
765 | toread -= tocopy; |
766 | data += tocopy; |
767 | blk++; |
768 | } |
769 | return len; |
770 | } |
771 | |
772 | /* Write to quotafile */ |
773 | static ssize_t jfs_quota_write(struct super_block *sb, int type, |
774 | const char *data, size_t len, loff_t off) |
775 | { |
776 | struct inode *inode = sb_dqopt(sb)->files[type]; |
777 | sector_t blk = off >> sb->s_blocksize_bits; |
778 | int err = 0; |
779 | int offset = off & (sb->s_blocksize - 1); |
780 | int tocopy; |
781 | size_t towrite = len; |
782 | struct buffer_head tmp_bh; |
783 | struct buffer_head *bh; |
784 | |
785 | inode_lock(inode); |
786 | while (towrite > 0) { |
787 | tocopy = min_t(size_t, sb->s_blocksize - offset, towrite); |
788 | |
789 | tmp_bh.b_state = 0; |
790 | tmp_bh.b_size = i_blocksize(node: inode); |
791 | err = jfs_get_block(inode, blk, &tmp_bh, 1); |
792 | if (err) |
793 | goto out; |
794 | if (offset || tocopy != sb->s_blocksize) |
795 | bh = sb_bread(sb, block: tmp_bh.b_blocknr); |
796 | else |
797 | bh = sb_getblk(sb, block: tmp_bh.b_blocknr); |
798 | if (!bh) { |
799 | err = -EIO; |
800 | goto out; |
801 | } |
802 | lock_buffer(bh); |
803 | memcpy(bh->b_data+offset, data, tocopy); |
804 | flush_dcache_page(page: bh->b_page); |
805 | set_buffer_uptodate(bh); |
806 | mark_buffer_dirty(bh); |
807 | unlock_buffer(bh); |
808 | brelse(bh); |
809 | offset = 0; |
810 | towrite -= tocopy; |
811 | data += tocopy; |
812 | blk++; |
813 | } |
814 | out: |
815 | if (len == towrite) { |
816 | inode_unlock(inode); |
817 | return err; |
818 | } |
819 | if (inode->i_size < off+len-towrite) |
820 | i_size_write(inode, i_size: off+len-towrite); |
821 | inode_set_mtime_to_ts(inode, ts: inode_set_ctime_current(inode)); |
822 | mark_inode_dirty(inode); |
823 | inode_unlock(inode); |
824 | return len - towrite; |
825 | } |
826 | |
827 | static struct dquot **jfs_get_dquots(struct inode *inode) |
828 | { |
829 | return JFS_IP(inode)->i_dquot; |
830 | } |
831 | |
832 | static int jfs_quota_on(struct super_block *sb, int type, int format_id, |
833 | const struct path *path) |
834 | { |
835 | int err; |
836 | struct inode *inode; |
837 | |
838 | err = dquot_quota_on(sb, type, format_id, path); |
839 | if (err) |
840 | return err; |
841 | |
842 | inode = d_inode(dentry: path->dentry); |
843 | inode_lock(inode); |
844 | JFS_IP(inode)->mode2 |= JFS_NOATIME_FL | JFS_IMMUTABLE_FL; |
845 | inode_set_flags(inode, S_NOATIME | S_IMMUTABLE, |
846 | S_NOATIME | S_IMMUTABLE); |
847 | inode_unlock(inode); |
848 | mark_inode_dirty(inode); |
849 | |
850 | return 0; |
851 | } |
852 | |
853 | static int jfs_quota_off(struct super_block *sb, int type) |
854 | { |
855 | struct inode *inode = sb_dqopt(sb)->files[type]; |
856 | int err; |
857 | |
858 | if (!inode || !igrab(inode)) |
859 | goto out; |
860 | |
861 | err = dquot_quota_off(sb, type); |
862 | if (err) |
863 | goto out_put; |
864 | |
865 | inode_lock(inode); |
866 | JFS_IP(inode)->mode2 &= ~(JFS_NOATIME_FL | JFS_IMMUTABLE_FL); |
867 | inode_set_flags(inode, flags: 0, S_NOATIME | S_IMMUTABLE); |
868 | inode_unlock(inode); |
869 | mark_inode_dirty(inode); |
870 | out_put: |
871 | iput(inode); |
872 | return err; |
873 | out: |
874 | return dquot_quota_off(sb, type); |
875 | } |
876 | #endif |
877 | |
878 | static const struct super_operations jfs_super_operations = { |
879 | .alloc_inode = jfs_alloc_inode, |
880 | .free_inode = jfs_free_inode, |
881 | .dirty_inode = jfs_dirty_inode, |
882 | .write_inode = jfs_write_inode, |
883 | .evict_inode = jfs_evict_inode, |
884 | .put_super = jfs_put_super, |
885 | .sync_fs = jfs_sync_fs, |
886 | .freeze_fs = jfs_freeze, |
887 | .unfreeze_fs = jfs_unfreeze, |
888 | .statfs = jfs_statfs, |
889 | .remount_fs = jfs_remount, |
890 | .show_options = jfs_show_options, |
891 | #ifdef CONFIG_QUOTA |
892 | .quota_read = jfs_quota_read, |
893 | .quota_write = jfs_quota_write, |
894 | .get_dquots = jfs_get_dquots, |
895 | #endif |
896 | }; |
897 | |
898 | static const struct export_operations jfs_export_operations = { |
899 | .encode_fh = generic_encode_ino32_fh, |
900 | .fh_to_dentry = jfs_fh_to_dentry, |
901 | .fh_to_parent = jfs_fh_to_parent, |
902 | .get_parent = jfs_get_parent, |
903 | }; |
904 | |
905 | static struct file_system_type jfs_fs_type = { |
906 | .owner = THIS_MODULE, |
907 | .name = "jfs" , |
908 | .mount = jfs_do_mount, |
909 | .kill_sb = kill_block_super, |
910 | .fs_flags = FS_REQUIRES_DEV, |
911 | }; |
912 | MODULE_ALIAS_FS("jfs" ); |
913 | |
914 | static void init_once(void *foo) |
915 | { |
916 | struct jfs_inode_info *jfs_ip = (struct jfs_inode_info *) foo; |
917 | |
918 | memset(jfs_ip, 0, sizeof(struct jfs_inode_info)); |
919 | INIT_LIST_HEAD(list: &jfs_ip->anon_inode_list); |
920 | init_rwsem(&jfs_ip->rdwrlock); |
921 | mutex_init(&jfs_ip->commit_mutex); |
922 | init_rwsem(&jfs_ip->xattr_sem); |
923 | spin_lock_init(&jfs_ip->ag_lock); |
924 | jfs_ip->active_ag = -1; |
925 | inode_init_once(&jfs_ip->vfs_inode); |
926 | } |
927 | |
928 | static int __init init_jfs_fs(void) |
929 | { |
930 | int i; |
931 | int rc; |
932 | |
933 | jfs_inode_cachep = |
934 | kmem_cache_create_usercopy(name: "jfs_ip" , size: sizeof(struct jfs_inode_info), |
935 | align: 0, SLAB_RECLAIM_ACCOUNT|SLAB_MEM_SPREAD|SLAB_ACCOUNT, |
936 | offsetof(struct jfs_inode_info, i_inline_all), |
937 | sizeof_field(struct jfs_inode_info, i_inline_all), |
938 | ctor: init_once); |
939 | if (jfs_inode_cachep == NULL) |
940 | return -ENOMEM; |
941 | |
942 | /* |
943 | * Metapage initialization |
944 | */ |
945 | rc = metapage_init(); |
946 | if (rc) { |
947 | jfs_err("metapage_init failed w/rc = %d" , rc); |
948 | goto free_slab; |
949 | } |
950 | |
951 | /* |
952 | * Transaction Manager initialization |
953 | */ |
954 | rc = txInit(); |
955 | if (rc) { |
956 | jfs_err("txInit failed w/rc = %d" , rc); |
957 | goto free_metapage; |
958 | } |
959 | |
960 | /* |
961 | * I/O completion thread (endio) |
962 | */ |
963 | jfsIOthread = kthread_run(jfsIOWait, NULL, "jfsIO" ); |
964 | if (IS_ERR(ptr: jfsIOthread)) { |
965 | rc = PTR_ERR(ptr: jfsIOthread); |
966 | jfs_err("init_jfs_fs: fork failed w/rc = %d" , rc); |
967 | goto end_txmngr; |
968 | } |
969 | |
970 | if (commit_threads < 1) |
971 | commit_threads = num_online_cpus(); |
972 | if (commit_threads > MAX_COMMIT_THREADS) |
973 | commit_threads = MAX_COMMIT_THREADS; |
974 | |
975 | for (i = 0; i < commit_threads; i++) { |
976 | jfsCommitThread[i] = kthread_run(jfs_lazycommit, NULL, |
977 | "jfsCommit" ); |
978 | if (IS_ERR(ptr: jfsCommitThread[i])) { |
979 | rc = PTR_ERR(ptr: jfsCommitThread[i]); |
980 | jfs_err("init_jfs_fs: fork failed w/rc = %d" , rc); |
981 | commit_threads = i; |
982 | goto kill_committask; |
983 | } |
984 | } |
985 | |
986 | jfsSyncThread = kthread_run(jfs_sync, NULL, "jfsSync" ); |
987 | if (IS_ERR(ptr: jfsSyncThread)) { |
988 | rc = PTR_ERR(ptr: jfsSyncThread); |
989 | jfs_err("init_jfs_fs: fork failed w/rc = %d" , rc); |
990 | goto kill_committask; |
991 | } |
992 | |
993 | #ifdef PROC_FS_JFS |
994 | jfs_proc_init(); |
995 | #endif |
996 | |
997 | rc = register_filesystem(&jfs_fs_type); |
998 | if (!rc) |
999 | return 0; |
1000 | |
1001 | #ifdef PROC_FS_JFS |
1002 | jfs_proc_clean(); |
1003 | #endif |
1004 | kthread_stop(k: jfsSyncThread); |
1005 | kill_committask: |
1006 | for (i = 0; i < commit_threads; i++) |
1007 | kthread_stop(k: jfsCommitThread[i]); |
1008 | kthread_stop(k: jfsIOthread); |
1009 | end_txmngr: |
1010 | txExit(); |
1011 | free_metapage: |
1012 | metapage_exit(); |
1013 | free_slab: |
1014 | kmem_cache_destroy(s: jfs_inode_cachep); |
1015 | return rc; |
1016 | } |
1017 | |
1018 | static void __exit exit_jfs_fs(void) |
1019 | { |
1020 | int i; |
1021 | |
1022 | jfs_info("exit_jfs_fs called" ); |
1023 | |
1024 | txExit(); |
1025 | metapage_exit(); |
1026 | |
1027 | kthread_stop(k: jfsIOthread); |
1028 | for (i = 0; i < commit_threads; i++) |
1029 | kthread_stop(k: jfsCommitThread[i]); |
1030 | kthread_stop(k: jfsSyncThread); |
1031 | #ifdef PROC_FS_JFS |
1032 | jfs_proc_clean(); |
1033 | #endif |
1034 | unregister_filesystem(&jfs_fs_type); |
1035 | |
1036 | /* |
1037 | * Make sure all delayed rcu free inodes are flushed before we |
1038 | * destroy cache. |
1039 | */ |
1040 | rcu_barrier(); |
1041 | kmem_cache_destroy(s: jfs_inode_cachep); |
1042 | } |
1043 | |
1044 | module_init(init_jfs_fs) |
1045 | module_exit(exit_jfs_fs) |
1046 | |