Blame view
fs/logfs/super.c
16.3 KB
5db53f3e8 [LogFS] add new f... |
1 2 3 4 5 6 7 8 9 10 11 12 13 |
/* * fs/logfs/super.c * * As should be obvious for Linux kernel code, license is GPLv2 * * Copyright (c) 2005-2008 Joern Engel <joern@logfs.org> * * Generally contains mount/umount code and also serves as a dump area for * any functions that don't fit elsewhere and neither justify a file of their * own. */ #include "logfs.h" #include <linux/bio.h> |
5a0e3ad6a include cleanup: ... |
14 |
#include <linux/slab.h> |
b8639077a [LogFS] Set s_bdi |
15 |
#include <linux/blkdev.h> |
143cb494c fs: add module.h ... |
16 |
#include <linux/module.h> |
5db53f3e8 [LogFS] add new f... |
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 |
#include <linux/mtd/mtd.h> #include <linux/statfs.h> #include <linux/buffer_head.h> static DEFINE_MUTEX(emergency_mutex); static struct page *emergency_page; struct page *emergency_read_begin(struct address_space *mapping, pgoff_t index) { filler_t *filler = (filler_t *)mapping->a_ops->readpage; struct page *page; int err; page = read_cache_page(mapping, index, filler, NULL); if (page) return page; /* No more pages available, switch to emergency page */ printk(KERN_INFO"Logfs: Using emergency page "); mutex_lock(&emergency_mutex); err = filler(NULL, emergency_page); if (err) { mutex_unlock(&emergency_mutex); printk(KERN_EMERG"Logfs: Error reading emergency page "); return ERR_PTR(err); } return emergency_page; } void emergency_read_end(struct page *page) { if (page == emergency_page) mutex_unlock(&emergency_mutex); else |
09cbfeaf1 mm, fs: get rid o... |
53 |
put_page(page); |
5db53f3e8 [LogFS] add new f... |
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 |
} static void dump_segfile(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); struct logfs_segment_entry se; u32 segno; for (segno = 0; segno < super->s_no_segs; segno++) { logfs_get_segment_entry(sb, segno, &se); printk("%3x: %6x %8x", segno, be32_to_cpu(se.ec_level), be32_to_cpu(se.valid)); if (++segno < super->s_no_segs) { logfs_get_segment_entry(sb, segno, &se); printk(" %6x %8x", be32_to_cpu(se.ec_level), be32_to_cpu(se.valid)); } if (++segno < super->s_no_segs) { logfs_get_segment_entry(sb, segno, &se); printk(" %6x %8x", be32_to_cpu(se.ec_level), be32_to_cpu(se.valid)); } if (++segno < super->s_no_segs) { logfs_get_segment_entry(sb, segno, &se); printk(" %6x %8x", be32_to_cpu(se.ec_level), be32_to_cpu(se.valid)); } printk(" "); } } /* * logfs_crash_dump - dump debug information to device * * The LogFS superblock only occupies part of a segment. This function will * write as much debug information as it can gather into the spare space. */ void logfs_crash_dump(struct super_block *sb) { dump_segfile(sb); } /* |
5db53f3e8 [LogFS] add new f... |
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
* FIXME: There should be a reserve for root, similar to ext2. */ int logfs_statfs(struct dentry *dentry, struct kstatfs *stats) { struct super_block *sb = dentry->d_sb; struct logfs_super *super = logfs_super(sb); stats->f_type = LOGFS_MAGIC_U32; stats->f_bsize = sb->s_blocksize; stats->f_blocks = super->s_size >> LOGFS_BLOCK_BITS >> 3; stats->f_bfree = super->s_free_bytes >> sb->s_blocksize_bits; stats->f_bavail = super->s_free_bytes >> sb->s_blocksize_bits; stats->f_files = 0; stats->f_ffree = 0; stats->f_namelen = LOGFS_MAX_NAMELEN; return 0; } static int logfs_sb_set(struct super_block *sb, void *_super) { struct logfs_super *super = _super; sb->s_fs_info = super; sb->s_mtd = super->s_mtd; sb->s_bdev = super->s_bdev; |
bba0b5c2c logfs: fix compil... |
123 |
#ifdef CONFIG_BLOCK |
b8639077a [LogFS] Set s_bdi |
124 125 |
if (sb->s_bdev) sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info; |
bba0b5c2c logfs: fix compil... |
126 127 |
#endif #ifdef CONFIG_MTD |
b8639077a [LogFS] Set s_bdi |
128 129 |
if (sb->s_mtd) sb->s_bdi = sb->s_mtd->backing_dev_info; |
bba0b5c2c logfs: fix compil... |
130 |
#endif |
5db53f3e8 [LogFS] add new f... |
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 |
return 0; } static int logfs_sb_test(struct super_block *sb, void *_super) { struct logfs_super *super = _super; struct mtd_info *mtd = super->s_mtd; if (mtd && sb->s_mtd == mtd) return 1; if (super->s_bdev && sb->s_bdev == super->s_bdev) return 1; return 0; } static void set_segment_header(struct logfs_segment_header *sh, u8 type, u8 level, u32 segno, u32 ec) { sh->pad = 0; sh->type = type; sh->level = level; sh->segno = cpu_to_be32(segno); sh->ec = cpu_to_be32(ec); sh->gec = cpu_to_be64(segno); sh->crc = logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4); } static void logfs_write_ds(struct super_block *sb, struct logfs_disk_super *ds, u32 segno, u32 ec) { struct logfs_super *super = logfs_super(sb); struct logfs_segment_header *sh = &ds->ds_sh; int i; memset(ds, 0, sizeof(*ds)); set_segment_header(sh, SEG_SUPER, 0, segno, ec); ds->ds_ifile_levels = super->s_ifile_levels; ds->ds_iblock_levels = super->s_iblock_levels; ds->ds_data_levels = super->s_data_levels; /* XXX: Remove */ ds->ds_segment_shift = super->s_segshift; ds->ds_block_shift = sb->s_blocksize_bits; ds->ds_write_shift = super->s_writeshift; ds->ds_filesystem_size = cpu_to_be64(super->s_size); ds->ds_segment_size = cpu_to_be32(super->s_segsize); ds->ds_bad_seg_reserve = cpu_to_be32(super->s_bad_seg_reserve); ds->ds_feature_incompat = cpu_to_be64(super->s_feature_incompat); ds->ds_feature_ro_compat= cpu_to_be64(super->s_feature_ro_compat); ds->ds_feature_compat = cpu_to_be64(super->s_feature_compat); ds->ds_feature_flags = cpu_to_be64(super->s_feature_flags); ds->ds_root_reserve = cpu_to_be64(super->s_root_reserve); ds->ds_speed_reserve = cpu_to_be64(super->s_speed_reserve); journal_for_each(i) ds->ds_journal_seg[i] = cpu_to_be32(super->s_journal_seg[i]); ds->ds_magic = cpu_to_be64(LOGFS_MAGIC); ds->ds_crc = logfs_crc32(ds, sizeof(*ds), LOGFS_SEGMENT_HEADERSIZE + 12); } static int write_one_sb(struct super_block *sb, struct page *(*find_sb)(struct super_block *sb, u64 *ofs)) { struct logfs_super *super = logfs_super(sb); struct logfs_disk_super *ds; struct logfs_segment_entry se; struct page *page; u64 ofs; u32 ec, segno; int err; page = find_sb(sb, &ofs); if (!page) return -EIO; ds = page_address(page); segno = seg_no(sb, ofs); logfs_get_segment_entry(sb, segno, &se); ec = be32_to_cpu(se.ec_level) >> 4; ec++; logfs_set_segment_erased(sb, segno, ec, 0); logfs_write_ds(sb, ds, segno, ec); err = super->s_devops->write_sb(sb, page); |
09cbfeaf1 mm, fs: get rid o... |
212 |
put_page(page); |
5db53f3e8 [LogFS] add new f... |
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
return err; } int logfs_write_sb(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); int err; /* First superblock */ err = write_one_sb(sb, super->s_devops->find_first_sb); if (err) return err; /* Last superblock */ err = write_one_sb(sb, super->s_devops->find_last_sb); if (err) return err; return 0; } static int ds_cmp(const void *ds0, const void *ds1) { size_t len = sizeof(struct logfs_disk_super); /* We know the segment headers differ, so ignore them */ len -= LOGFS_SEGMENT_HEADERSIZE; ds0 += LOGFS_SEGMENT_HEADERSIZE; ds1 += LOGFS_SEGMENT_HEADERSIZE; return memcmp(ds0, ds1, len); } static int logfs_recover_sb(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); struct logfs_disk_super _ds0, *ds0 = &_ds0; struct logfs_disk_super _ds1, *ds1 = &_ds1; int err, valid0, valid1; /* read first superblock */ err = wbuf_read(sb, super->s_sb_ofs[0], sizeof(*ds0), ds0); if (err) return err; /* read last superblock */ err = wbuf_read(sb, super->s_sb_ofs[1], sizeof(*ds1), ds1); if (err) return err; valid0 = logfs_check_ds(ds0) == 0; valid1 = logfs_check_ds(ds1) == 0; if (!valid0 && valid1) { printk(KERN_INFO"First superblock is invalid - fixing. "); return write_one_sb(sb, super->s_devops->find_first_sb); } if (valid0 && !valid1) { printk(KERN_INFO"Last superblock is invalid - fixing. "); return write_one_sb(sb, super->s_devops->find_last_sb); } if (valid0 && valid1 && ds_cmp(ds0, ds1)) { printk(KERN_INFO"Superblocks don't match - fixing. "); |
faaa27ab9 Write out both su... |
275 |
return logfs_write_sb(sb); |
5db53f3e8 [LogFS] add new f... |
276 277 278 279 280 281 282 283 284 285 |
} /* If neither is valid now, something's wrong. Didn't we properly * check them before?!? */ BUG_ON(!valid0 && !valid1); return 0; } static int logfs_make_writeable(struct super_block *sb) { int err; |
49137f2ef Open segment file... |
286 287 288 |
err = logfs_open_segfile(sb); if (err) return err; |
5db53f3e8 [LogFS] add new f... |
289 290 291 292 293 294 295 296 297 |
/* Repair any broken superblock copies */ err = logfs_recover_sb(sb); if (err) return err; /* Check areas for trailing unaccounted data */ err = logfs_check_areas(sb); if (err) return err; |
5db53f3e8 [LogFS] add new f... |
298 299 300 301 302 303 304 305 306 307 308 |
/* Do one GC pass before any data gets dirtied */ logfs_gc_pass(sb); /* after all initializations are done, replay the journal * for rw-mounts, if necessary */ err = logfs_replay_journal(sb); if (err) return err; return 0; } |
a1da9e8ab switch logfs to -... |
309 |
static int logfs_get_sb_final(struct super_block *sb) |
5db53f3e8 [LogFS] add new f... |
310 |
{ |
9421502b4 [LogFS] Fix bdev ... |
311 |
struct logfs_super *super = logfs_super(sb); |
5db53f3e8 [LogFS] add new f... |
312 313 314 315 316 317 318 |
struct inode *rootdir; int err; /* root dir */ rootdir = logfs_iget(sb, LOGFS_INO_ROOT); if (IS_ERR(rootdir)) goto fail; |
48fde701a switch open-coded... |
319 320 |
sb->s_root = d_make_root(rootdir); if (!sb->s_root) |
265624495 Fix double-free i... |
321 |
goto fail; |
5db53f3e8 [LogFS] add new f... |
322 |
|
8e22c1a4e logfs: get rid of... |
323 |
/* at that point we know that ->put_super() will be called */ |
9421502b4 [LogFS] Fix bdev ... |
324 325 |
super->s_erase_page = alloc_pages(GFP_KERNEL, 0); if (!super->s_erase_page) |
8e22c1a4e logfs: get rid of... |
326 |
return -ENOMEM; |
9421502b4 [LogFS] Fix bdev ... |
327 |
memset(page_address(super->s_erase_page), 0xFF, PAGE_SIZE); |
5db53f3e8 [LogFS] add new f... |
328 329 |
/* FIXME: check for read-only mounts */ err = logfs_make_writeable(sb); |
8e22c1a4e logfs: get rid of... |
330 331 332 333 |
if (err) { __free_page(super->s_erase_page); return err; } |
5db53f3e8 [LogFS] add new f... |
334 335 336 |
log_super("LogFS: Finished mounting "); |
5db53f3e8 [LogFS] add new f... |
337 |
return 0; |
5db53f3e8 [LogFS] add new f... |
338 |
fail: |
8e22c1a4e logfs: get rid of... |
339 340 341 |
iput(super->s_master_inode); iput(super->s_segfile_inode); iput(super->s_mapping_inode); |
5db53f3e8 [LogFS] add new f... |
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 |
return -EIO; } int logfs_check_ds(struct logfs_disk_super *ds) { struct logfs_segment_header *sh = &ds->ds_sh; if (ds->ds_magic != cpu_to_be64(LOGFS_MAGIC)) return -EINVAL; if (sh->crc != logfs_crc32(sh, LOGFS_SEGMENT_HEADERSIZE, 4)) return -EINVAL; if (ds->ds_crc != logfs_crc32(ds, sizeof(*ds), LOGFS_SEGMENT_HEADERSIZE + 12)) return -EINVAL; return 0; } static struct page *find_super_block(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); struct page *first, *last; first = super->s_devops->find_first_sb(sb, &super->s_sb_ofs[0]); if (!first || IS_ERR(first)) return NULL; last = super->s_devops->find_last_sb(sb, &super->s_sb_ofs[1]); |
3272c8a57 logfs: testing th... |
368 |
if (!last || IS_ERR(last)) { |
09cbfeaf1 mm, fs: get rid o... |
369 |
put_page(first); |
5db53f3e8 [LogFS] add new f... |
370 371 372 373 |
return NULL; } if (!logfs_check_ds(page_address(first))) { |
09cbfeaf1 mm, fs: get rid o... |
374 |
put_page(last); |
5db53f3e8 [LogFS] add new f... |
375 376 377 378 379 |
return first; } /* First one didn't work, try the second superblock */ if (!logfs_check_ds(page_address(last))) { |
09cbfeaf1 mm, fs: get rid o... |
380 |
put_page(first); |
5db53f3e8 [LogFS] add new f... |
381 382 383 384 |
return last; } /* Neither worked, sorry folks */ |
09cbfeaf1 mm, fs: get rid o... |
385 386 |
put_page(first); put_page(last); |
5db53f3e8 [LogFS] add new f... |
387 388 389 390 391 392 393 394 395 396 397 398 |
return NULL; } static int __logfs_read_sb(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); struct page *page; struct logfs_disk_super *ds; int i; page = find_super_block(sb); if (!page) |
ad342631f logfs: Return -EI... |
399 |
return -EINVAL; |
5db53f3e8 [LogFS] add new f... |
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 |
ds = page_address(page); super->s_size = be64_to_cpu(ds->ds_filesystem_size); super->s_root_reserve = be64_to_cpu(ds->ds_root_reserve); super->s_speed_reserve = be64_to_cpu(ds->ds_speed_reserve); super->s_bad_seg_reserve = be32_to_cpu(ds->ds_bad_seg_reserve); super->s_segsize = 1 << ds->ds_segment_shift; super->s_segmask = (1 << ds->ds_segment_shift) - 1; super->s_segshift = ds->ds_segment_shift; sb->s_blocksize = 1 << ds->ds_block_shift; sb->s_blocksize_bits = ds->ds_block_shift; super->s_writesize = 1 << ds->ds_write_shift; super->s_writeshift = ds->ds_write_shift; super->s_no_segs = super->s_size >> super->s_segshift; super->s_no_blocks = super->s_segsize >> sb->s_blocksize_bits; super->s_feature_incompat = be64_to_cpu(ds->ds_feature_incompat); super->s_feature_ro_compat = be64_to_cpu(ds->ds_feature_ro_compat); super->s_feature_compat = be64_to_cpu(ds->ds_feature_compat); super->s_feature_flags = be64_to_cpu(ds->ds_feature_flags); journal_for_each(i) super->s_journal_seg[i] = be32_to_cpu(ds->ds_journal_seg[i]); super->s_ifile_levels = ds->ds_ifile_levels; super->s_iblock_levels = ds->ds_iblock_levels; super->s_data_levels = ds->ds_data_levels; super->s_total_levels = super->s_ifile_levels + super->s_iblock_levels + super->s_data_levels; |
09cbfeaf1 mm, fs: get rid o... |
428 |
put_page(page); |
5db53f3e8 [LogFS] add new f... |
429 430 |
return 0; } |
6a08ab846 [LogFS] Check fea... |
431 |
static int logfs_read_sb(struct super_block *sb, int read_only) |
5db53f3e8 [LogFS] add new f... |
432 433 434 435 436 437 438 439 440 441 |
{ struct logfs_super *super = logfs_super(sb); int ret; super->s_btree_pool = mempool_create(32, btree_alloc, btree_free, NULL); if (!super->s_btree_pool) return -ENOMEM; btree_init_mempool64(&super->s_shadow_tree.new, super->s_btree_pool); btree_init_mempool64(&super->s_shadow_tree.old, super->s_btree_pool); |
032d8f726 [LogFS] Prevent m... |
442 443 |
btree_init_mempool32(&super->s_shadow_tree.segment_map, super->s_btree_pool); |
5db53f3e8 [LogFS] add new f... |
444 445 446 447 448 449 450 451 |
ret = logfs_init_mapping(sb); if (ret) return ret; ret = __logfs_read_sb(sb); if (ret) return ret; |
6a08ab846 [LogFS] Check fea... |
452 453 454 455 456 |
if (super->s_feature_incompat & ~LOGFS_FEATURES_INCOMPAT) return -EIO; if ((super->s_feature_ro_compat & ~LOGFS_FEATURES_RO_COMPAT) && !read_only) return -EIO; |
5db53f3e8 [LogFS] add new f... |
457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 |
ret = logfs_init_rw(sb); if (ret) return ret; ret = logfs_init_areas(sb); if (ret) return ret; ret = logfs_init_gc(sb); if (ret) return ret; ret = logfs_init_journal(sb); if (ret) return ret; return 0; } static void logfs_kill_sb(struct super_block *sb) { struct logfs_super *super = logfs_super(sb); log_super("LogFS: Start unmounting "); /* Alias entries slow down mount, so evict as many as possible */ sync_filesystem(sb); |
c6d383014 [LogFS] Only writ... |
484 |
logfs_write_anchor(sb); |
1bcceaff8 logfs: Free areas... |
485 |
free_areas(sb); |
5db53f3e8 [LogFS] add new f... |
486 487 488 489 490 |
/* * From this point on alias entries are simply dropped - and any * writes to the object store are considered bugs. */ |
5db53f3e8 [LogFS] add new f... |
491 492 493 |
log_super("LogFS: Now in shutdown "); generic_shutdown_super(sb); |
ecfd89099 logfs: set superb... |
494 |
super->s_flags |= LOGFS_SB_FLAG_SHUTDOWN; |
5db53f3e8 [LogFS] add new f... |
495 496 497 498 499 500 501 |
BUG_ON(super->s_dirty_used_bytes || super->s_dirty_free_bytes); logfs_cleanup_gc(sb); logfs_cleanup_journal(sb); logfs_cleanup_areas(sb); logfs_cleanup_rw(sb); |
9421502b4 [LogFS] Fix bdev ... |
502 503 |
if (super->s_erase_page) __free_page(super->s_erase_page); |
e5a0726a9 logfs: fix a leak... |
504 |
super->s_devops->put_device(super); |
1f1b0008e [LogFS] Prevent m... |
505 506 |
logfs_mempool_destroy(super->s_btree_pool); logfs_mempool_destroy(super->s_alias_pool); |
5db53f3e8 [LogFS] add new f... |
507 508 509 510 |
kfree(super); log_super("LogFS: Finished unmounting "); } |
a1da9e8ab switch logfs to -... |
511 512 |
static struct dentry *logfs_get_sb_device(struct logfs_super *super, struct file_system_type *type, int flags) |
5db53f3e8 [LogFS] add new f... |
513 |
{ |
5db53f3e8 [LogFS] add new f... |
514 515 516 517 518 519 |
struct super_block *sb; int err = -ENOMEM; static int mount_count; log_super("LogFS: Start mount %x ", mount_count++); |
5db53f3e8 [LogFS] add new f... |
520 |
|
5db53f3e8 [LogFS] add new f... |
521 |
err = -EINVAL; |
9249e17fe VFS: Pass mount f... |
522 |
sb = sget(type, logfs_sb_test, logfs_sb_set, flags | MS_NOATIME, super); |
a1da9e8ab switch logfs to -... |
523 524 525 526 527 |
if (IS_ERR(sb)) { super->s_devops->put_device(super); kfree(super); return ERR_CAST(sb); } |
5db53f3e8 [LogFS] add new f... |
528 529 530 |
if (sb->s_root) { /* Device is already in use */ |
a1da9e8ab switch logfs to -... |
531 532 533 |
super->s_devops->put_device(super); kfree(super); return dget(sb->s_root); |
5db53f3e8 [LogFS] add new f... |
534 |
} |
5db53f3e8 [LogFS] add new f... |
535 536 537 538 539 540 541 |
/* * sb->s_maxbytes is limited to 8TB. On 32bit systems, the page cache * only covers 16TB and the upper 8TB are used for indirect blocks. * On 64bit system we could bump up the limit, but that would make * the filesystem incompatible with 32bit systems. */ sb->s_maxbytes = (1ull << 43) - 1; |
8de527787 vfs: check i_nlin... |
542 |
sb->s_max_links = LOGFS_LINK_MAX; |
5db53f3e8 [LogFS] add new f... |
543 |
sb->s_op = &logfs_super_operations; |
5db53f3e8 [LogFS] add new f... |
544 |
|
6a08ab846 [LogFS] Check fea... |
545 |
err = logfs_read_sb(sb, sb->s_flags & MS_RDONLY); |
5db53f3e8 [LogFS] add new f... |
546 547 548 549 |
if (err) goto err1; sb->s_flags |= MS_ACTIVE; |
a1da9e8ab switch logfs to -... |
550 551 |
err = logfs_get_sb_final(sb); if (err) { |
8e22c1a4e logfs: get rid of... |
552 |
deactivate_locked_super(sb); |
a1da9e8ab switch logfs to -... |
553 554 555 |
return ERR_PTR(err); } return dget(sb->s_root); |
5db53f3e8 [LogFS] add new f... |
556 557 |
err1: |
8e22c1a4e logfs: get rid of... |
558 559 560 561 |
/* no ->s_root, no ->put_super() */ iput(super->s_master_inode); iput(super->s_segfile_inode); iput(super->s_mapping_inode); |
6f2e9e6a9 Use deactivate_lo... |
562 |
deactivate_locked_super(sb); |
a1da9e8ab switch logfs to -... |
563 |
return ERR_PTR(err); |
5db53f3e8 [LogFS] add new f... |
564 |
} |
a1da9e8ab switch logfs to -... |
565 566 |
static struct dentry *logfs_mount(struct file_system_type *type, int flags, const char *devname, void *data) |
5db53f3e8 [LogFS] add new f... |
567 568 |
{ ulong mtdnr; |
71a1c0125 logfs get_sb mass... |
569 |
struct logfs_super *super; |
7d945a3aa logfs get_sb, part 3 |
570 |
int err; |
71a1c0125 logfs get_sb mass... |
571 572 573 |
super = kzalloc(sizeof(*super), GFP_KERNEL); if (!super) |
a1da9e8ab switch logfs to -... |
574 |
return ERR_PTR(-ENOMEM); |
5db53f3e8 [LogFS] add new f... |
575 |
|
cce2c56e7 logfs: initialize... |
576 577 578 |
mutex_init(&super->s_dirop_mutex); mutex_init(&super->s_object_alias_mutex); INIT_LIST_HEAD(&super->s_freeing_list); |
5db53f3e8 [LogFS] add new f... |
579 |
if (!devname) |
7d945a3aa logfs get_sb, part 3 |
580 581 582 583 |
err = logfs_get_sb_bdev(super, type, devname); else if (strncmp(devname, "mtd", 3)) err = logfs_get_sb_bdev(super, type, devname); else { |
5db53f3e8 [LogFS] add new f... |
584 585 |
char *garbage; mtdnr = simple_strtoul(devname+3, &garbage, 0); |
7d945a3aa logfs get_sb, part 3 |
586 587 588 589 590 591 592 593 |
if (*garbage) err = -EINVAL; else err = logfs_get_sb_mtd(super, mtdnr); } if (err) { kfree(super); |
a1da9e8ab switch logfs to -... |
594 |
return ERR_PTR(err); |
5db53f3e8 [LogFS] add new f... |
595 |
} |
a1da9e8ab switch logfs to -... |
596 |
return logfs_get_sb_device(super, type, flags); |
5db53f3e8 [LogFS] add new f... |
597 598 599 600 601 |
} static struct file_system_type logfs_fs_type = { .owner = THIS_MODULE, .name = "logfs", |
a1da9e8ab switch logfs to -... |
602 |
.mount = logfs_mount, |
5db53f3e8 [LogFS] add new f... |
603 604 605 606 |
.kill_sb = logfs_kill_sb, .fs_flags = FS_REQUIRES_DEV, }; |
7f78e0351 fs: Limit sys_mou... |
607 |
MODULE_ALIAS_FS("logfs"); |
5db53f3e8 [LogFS] add new f... |
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 |
static int __init logfs_init(void) { int ret; emergency_page = alloc_pages(GFP_KERNEL, 0); if (!emergency_page) return -ENOMEM; ret = logfs_compr_init(); if (ret) goto out1; ret = logfs_init_inode_cache(); if (ret) goto out2; |
03e897a1e logfs: missing cl... |
624 625 626 627 |
ret = register_filesystem(&logfs_fs_type); if (!ret) return 0; logfs_destroy_inode_cache(); |
5db53f3e8 [LogFS] add new f... |
628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 |
out2: logfs_compr_exit(); out1: __free_pages(emergency_page, 0); return ret; } static void __exit logfs_exit(void) { unregister_filesystem(&logfs_fs_type); logfs_destroy_inode_cache(); logfs_compr_exit(); __free_pages(emergency_page, 0); } module_init(logfs_init); module_exit(logfs_exit); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Joern Engel <joern@logfs.org>"); MODULE_DESCRIPTION("scalable flash filesystem"); |