11da177e4SLinus Torvalds /* 21da177e4SLinus Torvalds * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README 31da177e4SLinus Torvalds * 41da177e4SLinus Torvalds * Trivial changes by Alan Cox to add the LFS fixes 51da177e4SLinus Torvalds * 61da177e4SLinus Torvalds * Trivial Changes: 71da177e4SLinus Torvalds * Rights granted to Hans Reiser to redistribute under other terms providing 81da177e4SLinus Torvalds * he accepts all liability including but not limited to patent, fitness 91da177e4SLinus Torvalds * for purpose, and direct or indirect claims arising from failure to perform. 101da177e4SLinus Torvalds * 111da177e4SLinus Torvalds * NO WARRANTY 121da177e4SLinus Torvalds */ 131da177e4SLinus Torvalds 141da177e4SLinus Torvalds #include <linux/module.h> 155a0e3ad6STejun Heo #include <linux/slab.h> 161da177e4SLinus Torvalds #include <linux/vmalloc.h> 171da177e4SLinus Torvalds #include <linux/time.h> 181da177e4SLinus Torvalds #include <asm/uaccess.h> 19f466c6fdSAl Viro #include "reiserfs.h" 20a3063ab8SAl Viro #include "acl.h" 21c45ac888SAl Viro #include "xattr.h" 221da177e4SLinus Torvalds #include <linux/init.h> 231da177e4SLinus Torvalds #include <linux/blkdev.h> 241da177e4SLinus Torvalds #include <linux/buffer_head.h> 25a5694255SChristoph Hellwig #include <linux/exportfs.h> 2674abb989SJan Kara #include <linux/quotaops.h> 271da177e4SLinus Torvalds #include <linux/vfs.h> 281da177e4SLinus Torvalds #include <linux/mount.h> 291da177e4SLinus Torvalds #include <linux/namei.h> 30651d0623SColy Li #include <linux/crc32.h> 31c3aa0776SJan Kara #include <linux/seq_file.h> 321da177e4SLinus Torvalds 331da177e4SLinus Torvalds struct file_system_type reiserfs_fs_type; 341da177e4SLinus Torvalds 351da177e4SLinus Torvalds static const char reiserfs_3_5_magic_string[] = REISERFS_SUPER_MAGIC_STRING; 361da177e4SLinus Torvalds static const char reiserfs_3_6_magic_string[] = REISER2FS_SUPER_MAGIC_STRING; 371da177e4SLinus Torvalds static const char reiserfs_jr_magic_string[] = REISER2FS_JR_SUPER_MAGIC_STRING; 381da177e4SLinus Torvalds 391da177e4SLinus Torvalds int is_reiserfs_3_5(struct reiserfs_super_block *rs) 401da177e4SLinus Torvalds { 411da177e4SLinus Torvalds return !strncmp(rs->s_v1.s_magic, reiserfs_3_5_magic_string, 421da177e4SLinus Torvalds strlen(reiserfs_3_5_magic_string)); 431da177e4SLinus Torvalds } 441da177e4SLinus Torvalds 451da177e4SLinus Torvalds int is_reiserfs_3_6(struct reiserfs_super_block *rs) 461da177e4SLinus Torvalds { 471da177e4SLinus Torvalds return !strncmp(rs->s_v1.s_magic, reiserfs_3_6_magic_string, 481da177e4SLinus Torvalds strlen(reiserfs_3_6_magic_string)); 491da177e4SLinus Torvalds } 501da177e4SLinus Torvalds 511da177e4SLinus Torvalds int is_reiserfs_jr(struct reiserfs_super_block *rs) 521da177e4SLinus Torvalds { 531da177e4SLinus Torvalds return !strncmp(rs->s_v1.s_magic, reiserfs_jr_magic_string, 541da177e4SLinus Torvalds strlen(reiserfs_jr_magic_string)); 551da177e4SLinus Torvalds } 561da177e4SLinus Torvalds 571da177e4SLinus Torvalds static int is_any_reiserfs_magic_string(struct reiserfs_super_block *rs) 581da177e4SLinus Torvalds { 591da177e4SLinus Torvalds return (is_reiserfs_3_5(rs) || is_reiserfs_3_6(rs) || 601da177e4SLinus Torvalds is_reiserfs_jr(rs)); 611da177e4SLinus Torvalds } 621da177e4SLinus Torvalds 631da177e4SLinus Torvalds static int reiserfs_remount(struct super_block *s, int *flags, char *data); 64726c3342SDavid Howells static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf); 65c3aa0776SJan Kara void show_alloc_options(struct seq_file *seq, struct super_block *s); 661da177e4SLinus Torvalds 671da177e4SLinus Torvalds static int reiserfs_sync_fs(struct super_block *s, int wait) 681da177e4SLinus Torvalds { 691da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 705af7926fSChristoph Hellwig 71a1177825SJan Kara /* 72a1177825SJan Kara * Writeback quota in non-journalled quota case - journalled quota has 73a1177825SJan Kara * no dirty dquots 74a1177825SJan Kara */ 75a1177825SJan Kara dquot_writeback_dquots(s, -1); 761da177e4SLinus Torvalds reiserfs_write_lock(s); 771da177e4SLinus Torvalds if (!journal_begin(&th, s, 1)) 781da177e4SLinus Torvalds if (!journal_end_sync(&th, s, 1)) 791da177e4SLinus Torvalds reiserfs_flush_old_commits(s); 801da177e4SLinus Torvalds reiserfs_write_unlock(s); 811da177e4SLinus Torvalds return 0; 821da177e4SLinus Torvalds } 831da177e4SLinus Torvalds 84033369d1SArtem Bityutskiy static void flush_old_commits(struct work_struct *work) 851da177e4SLinus Torvalds { 86033369d1SArtem Bityutskiy struct reiserfs_sb_info *sbi; 87033369d1SArtem Bityutskiy struct super_block *s; 88033369d1SArtem Bityutskiy 89033369d1SArtem Bityutskiy sbi = container_of(work, struct reiserfs_sb_info, old_work.work); 90033369d1SArtem Bityutskiy s = sbi->s_journal->j_work_sb; 91033369d1SArtem Bityutskiy 92033369d1SArtem Bityutskiy spin_lock(&sbi->old_work_lock); 93033369d1SArtem Bityutskiy sbi->work_queued = 0; 94033369d1SArtem Bityutskiy spin_unlock(&sbi->old_work_lock); 95033369d1SArtem Bityutskiy 961da177e4SLinus Torvalds reiserfs_sync_fs(s, 1); 971da177e4SLinus Torvalds } 981da177e4SLinus Torvalds 99033369d1SArtem Bityutskiy void reiserfs_schedule_old_flush(struct super_block *s) 100033369d1SArtem Bityutskiy { 101033369d1SArtem Bityutskiy struct reiserfs_sb_info *sbi = REISERFS_SB(s); 102033369d1SArtem Bityutskiy unsigned long delay; 103033369d1SArtem Bityutskiy 104033369d1SArtem Bityutskiy if (s->s_flags & MS_RDONLY) 105033369d1SArtem Bityutskiy return; 106033369d1SArtem Bityutskiy 107033369d1SArtem Bityutskiy spin_lock(&sbi->old_work_lock); 108033369d1SArtem Bityutskiy if (!sbi->work_queued) { 109033369d1SArtem Bityutskiy delay = msecs_to_jiffies(dirty_writeback_interval * 10); 110033369d1SArtem Bityutskiy queue_delayed_work(system_long_wq, &sbi->old_work, delay); 111033369d1SArtem Bityutskiy sbi->work_queued = 1; 112033369d1SArtem Bityutskiy } 113033369d1SArtem Bityutskiy spin_unlock(&sbi->old_work_lock); 114033369d1SArtem Bityutskiy } 115033369d1SArtem Bityutskiy 116033369d1SArtem Bityutskiy static void cancel_old_flush(struct super_block *s) 117033369d1SArtem Bityutskiy { 118033369d1SArtem Bityutskiy struct reiserfs_sb_info *sbi = REISERFS_SB(s); 119033369d1SArtem Bityutskiy 120033369d1SArtem Bityutskiy cancel_delayed_work_sync(&REISERFS_SB(s)->old_work); 121033369d1SArtem Bityutskiy spin_lock(&sbi->old_work_lock); 122033369d1SArtem Bityutskiy sbi->work_queued = 0; 123033369d1SArtem Bityutskiy spin_unlock(&sbi->old_work_lock); 124033369d1SArtem Bityutskiy } 125033369d1SArtem Bityutskiy 126c4be0c1dSTakashi Sato static int reiserfs_freeze(struct super_block *s) 1271da177e4SLinus Torvalds { 1281da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 129033369d1SArtem Bityutskiy 130033369d1SArtem Bityutskiy cancel_old_flush(s); 131033369d1SArtem Bityutskiy 1321da177e4SLinus Torvalds reiserfs_write_lock(s); 1331da177e4SLinus Torvalds if (!(s->s_flags & MS_RDONLY)) { 1341da177e4SLinus Torvalds int err = journal_begin(&th, s, 1); 1351da177e4SLinus Torvalds if (err) { 1361da177e4SLinus Torvalds reiserfs_block_writes(&th); 1371da177e4SLinus Torvalds } else { 138bd4c625cSLinus Torvalds reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 139bd4c625cSLinus Torvalds 1); 1401da177e4SLinus Torvalds journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); 1411da177e4SLinus Torvalds reiserfs_block_writes(&th); 1421da177e4SLinus Torvalds journal_end_sync(&th, s, 1); 1431da177e4SLinus Torvalds } 1441da177e4SLinus Torvalds } 1451da177e4SLinus Torvalds reiserfs_write_unlock(s); 146c4be0c1dSTakashi Sato return 0; 1471da177e4SLinus Torvalds } 1481da177e4SLinus Torvalds 149c4be0c1dSTakashi Sato static int reiserfs_unfreeze(struct super_block *s) 150bd4c625cSLinus Torvalds { 1511da177e4SLinus Torvalds reiserfs_allow_writes(s); 152c4be0c1dSTakashi Sato return 0; 1531da177e4SLinus Torvalds } 1541da177e4SLinus Torvalds 1556a3a16f2SAl Viro extern const struct in_core_key MAX_IN_CORE_KEY; 1561da177e4SLinus Torvalds 1571da177e4SLinus Torvalds /* this is used to delete "save link" when there are no items of a 1581da177e4SLinus Torvalds file it points to. It can either happen if unlink is completed but 1591da177e4SLinus Torvalds "save unlink" removal, or if file has both unlink and truncate 1601da177e4SLinus Torvalds pending and as unlink completes first (because key of "save link" 1611da177e4SLinus Torvalds protecting unlink is bigger that a key lf "save link" which 1621da177e4SLinus Torvalds protects truncate), so there left no items to make truncate 1631da177e4SLinus Torvalds completion on */ 164bd4c625cSLinus Torvalds static int remove_save_link_only(struct super_block *s, 165bd4c625cSLinus Torvalds struct reiserfs_key *key, int oid_free) 1661da177e4SLinus Torvalds { 1671da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 1681da177e4SLinus Torvalds int err; 1691da177e4SLinus Torvalds 1701da177e4SLinus Torvalds /* we are going to do one balancing */ 1711da177e4SLinus Torvalds err = journal_begin(&th, s, JOURNAL_PER_BALANCE_CNT); 1721da177e4SLinus Torvalds if (err) 1731da177e4SLinus Torvalds return err; 1741da177e4SLinus Torvalds 1751da177e4SLinus Torvalds reiserfs_delete_solid_item(&th, NULL, key); 1761da177e4SLinus Torvalds if (oid_free) 1771da177e4SLinus Torvalds /* removals are protected by direct items */ 1781da177e4SLinus Torvalds reiserfs_release_objectid(&th, le32_to_cpu(key->k_objectid)); 1791da177e4SLinus Torvalds 1801da177e4SLinus Torvalds return journal_end(&th, s, JOURNAL_PER_BALANCE_CNT); 1811da177e4SLinus Torvalds } 1821da177e4SLinus Torvalds 1831da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 1841da177e4SLinus Torvalds static int reiserfs_quota_on_mount(struct super_block *, int); 1851da177e4SLinus Torvalds #endif 1861da177e4SLinus Torvalds 1871da177e4SLinus Torvalds /* look for uncompleted unlinks and truncates and complete them */ 1881da177e4SLinus Torvalds static int finish_unfinished(struct super_block *s) 1891da177e4SLinus Torvalds { 1901da177e4SLinus Torvalds INITIALIZE_PATH(path); 1911da177e4SLinus Torvalds struct cpu_key max_cpu_key, obj_key; 192fb46f341SLepton Wu struct reiserfs_key save_link_key, last_inode_key; 1931da177e4SLinus Torvalds int retval = 0; 1941da177e4SLinus Torvalds struct item_head *ih; 1951da177e4SLinus Torvalds struct buffer_head *bh; 1961da177e4SLinus Torvalds int item_pos; 1971da177e4SLinus Torvalds char *item; 1981da177e4SLinus Torvalds int done; 1991da177e4SLinus Torvalds struct inode *inode; 2001da177e4SLinus Torvalds int truncate; 2011da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 2021da177e4SLinus Torvalds int i; 2031da177e4SLinus Torvalds int ms_active_set; 204f4b113aeSJan Kara int quota_enabled[MAXQUOTAS]; 2051da177e4SLinus Torvalds #endif 2061da177e4SLinus Torvalds 2071da177e4SLinus Torvalds /* compose key to look for "save" links */ 2081da177e4SLinus Torvalds max_cpu_key.version = KEY_FORMAT_3_5; 209f359b74cSVladimir Saveliev max_cpu_key.on_disk_key.k_dir_id = ~0U; 210f359b74cSVladimir Saveliev max_cpu_key.on_disk_key.k_objectid = ~0U; 211f359b74cSVladimir Saveliev set_cpu_key_k_offset(&max_cpu_key, ~0U); 2121da177e4SLinus Torvalds max_cpu_key.key_length = 3; 2131da177e4SLinus Torvalds 214fb46f341SLepton Wu memset(&last_inode_key, 0, sizeof(last_inode_key)); 215fb46f341SLepton Wu 2161da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 2171da177e4SLinus Torvalds /* Needed for iput() to work correctly and not trash data */ 2181da177e4SLinus Torvalds if (s->s_flags & MS_ACTIVE) { 2191da177e4SLinus Torvalds ms_active_set = 0; 2201da177e4SLinus Torvalds } else { 2211da177e4SLinus Torvalds ms_active_set = 1; 2221da177e4SLinus Torvalds s->s_flags |= MS_ACTIVE; 2231da177e4SLinus Torvalds } 2241da177e4SLinus Torvalds /* Turn on quotas so that they are updated correctly */ 2251da177e4SLinus Torvalds for (i = 0; i < MAXQUOTAS; i++) { 226f4b113aeSJan Kara quota_enabled[i] = 1; 2271da177e4SLinus Torvalds if (REISERFS_SB(s)->s_qf_names[i]) { 228f4b113aeSJan Kara int ret; 229f4b113aeSJan Kara 230f4b113aeSJan Kara if (sb_has_quota_active(s, i)) { 231f4b113aeSJan Kara quota_enabled[i] = 0; 232f4b113aeSJan Kara continue; 233f4b113aeSJan Kara } 234f4b113aeSJan Kara ret = reiserfs_quota_on_mount(s, i); 2351da177e4SLinus Torvalds if (ret < 0) 23645b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2500", 23745b03d5eSJeff Mahoney "cannot turn on journaled " 23845b03d5eSJeff Mahoney "quota: error %d", ret); 2391da177e4SLinus Torvalds } 2401da177e4SLinus Torvalds } 2411da177e4SLinus Torvalds #endif 2421da177e4SLinus Torvalds 2431da177e4SLinus Torvalds done = 0; 2441da177e4SLinus Torvalds REISERFS_SB(s)->s_is_unlinked_ok = 1; 2451da177e4SLinus Torvalds while (!retval) { 2461da177e4SLinus Torvalds retval = search_item(s, &max_cpu_key, &path); 2471da177e4SLinus Torvalds if (retval != ITEM_NOT_FOUND) { 2480030b645SJeff Mahoney reiserfs_error(s, "vs-2140", 2490030b645SJeff Mahoney "search_by_key returned %d", retval); 2501da177e4SLinus Torvalds break; 2511da177e4SLinus Torvalds } 2521da177e4SLinus Torvalds 2531da177e4SLinus Torvalds bh = get_last_bh(&path); 2541da177e4SLinus Torvalds item_pos = get_item_pos(&path); 2551da177e4SLinus Torvalds if (item_pos != B_NR_ITEMS(bh)) { 25645b03d5eSJeff Mahoney reiserfs_warning(s, "vs-2060", 25745b03d5eSJeff Mahoney "wrong position found"); 2581da177e4SLinus Torvalds break; 2591da177e4SLinus Torvalds } 2601da177e4SLinus Torvalds item_pos--; 2611da177e4SLinus Torvalds ih = B_N_PITEM_HEAD(bh, item_pos); 2621da177e4SLinus Torvalds 2631da177e4SLinus Torvalds if (le32_to_cpu(ih->ih_key.k_dir_id) != MAX_KEY_OBJECTID) 2641da177e4SLinus Torvalds /* there are no "save" links anymore */ 2651da177e4SLinus Torvalds break; 2661da177e4SLinus Torvalds 2671da177e4SLinus Torvalds save_link_key = ih->ih_key; 2681da177e4SLinus Torvalds if (is_indirect_le_ih(ih)) 2691da177e4SLinus Torvalds truncate = 1; 2701da177e4SLinus Torvalds else 2711da177e4SLinus Torvalds truncate = 0; 2721da177e4SLinus Torvalds 2731da177e4SLinus Torvalds /* reiserfs_iget needs k_dirid and k_objectid only */ 2741da177e4SLinus Torvalds item = B_I_PITEM(bh, ih); 2753e8962beSAl Viro obj_key.on_disk_key.k_dir_id = le32_to_cpu(*(__le32 *) item); 276bd4c625cSLinus Torvalds obj_key.on_disk_key.k_objectid = 277bd4c625cSLinus Torvalds le32_to_cpu(ih->ih_key.k_objectid); 2786b9f5829SAl Viro obj_key.on_disk_key.k_offset = 0; 2796b9f5829SAl Viro obj_key.on_disk_key.k_type = 0; 2801da177e4SLinus Torvalds 2811da177e4SLinus Torvalds pathrelse(&path); 2821da177e4SLinus Torvalds 2831da177e4SLinus Torvalds inode = reiserfs_iget(s, &obj_key); 2841da177e4SLinus Torvalds if (!inode) { 2851da177e4SLinus Torvalds /* the unlink almost completed, it just did not manage to remove 2861da177e4SLinus Torvalds "save" link and release objectid */ 28745b03d5eSJeff Mahoney reiserfs_warning(s, "vs-2180", "iget failed for %K", 2881da177e4SLinus Torvalds &obj_key); 2891da177e4SLinus Torvalds retval = remove_save_link_only(s, &save_link_key, 1); 2901da177e4SLinus Torvalds continue; 2911da177e4SLinus Torvalds } 2921da177e4SLinus Torvalds 2931da177e4SLinus Torvalds if (!truncate && inode->i_nlink) { 2941da177e4SLinus Torvalds /* file is not unlinked */ 29545b03d5eSJeff Mahoney reiserfs_warning(s, "vs-2185", 29645b03d5eSJeff Mahoney "file %K is not unlinked", 2971da177e4SLinus Torvalds &obj_key); 2981da177e4SLinus Torvalds retval = remove_save_link_only(s, &save_link_key, 0); 2991da177e4SLinus Torvalds continue; 3001da177e4SLinus Torvalds } 301871a2931SChristoph Hellwig dquot_initialize(inode); 3021da177e4SLinus Torvalds 3031da177e4SLinus Torvalds if (truncate && S_ISDIR(inode->i_mode)) { 3041da177e4SLinus Torvalds /* We got a truncate request for a dir which is impossible. 3051da177e4SLinus Torvalds The only imaginable way is to execute unfinished truncate request 3061da177e4SLinus Torvalds then boot into old kernel, remove the file and create dir with 3071da177e4SLinus Torvalds the same key. */ 30845b03d5eSJeff Mahoney reiserfs_warning(s, "green-2101", 30945b03d5eSJeff Mahoney "impossible truncate on a " 31045b03d5eSJeff Mahoney "directory %k. Please report", 311bd4c625cSLinus Torvalds INODE_PKEY(inode)); 3121da177e4SLinus Torvalds retval = remove_save_link_only(s, &save_link_key, 0); 3131da177e4SLinus Torvalds truncate = 0; 3141da177e4SLinus Torvalds iput(inode); 3151da177e4SLinus Torvalds continue; 3161da177e4SLinus Torvalds } 3171da177e4SLinus Torvalds 3181da177e4SLinus Torvalds if (truncate) { 319bd4c625cSLinus Torvalds REISERFS_I(inode)->i_flags |= 320bd4c625cSLinus Torvalds i_link_saved_truncate_mask; 3211da177e4SLinus Torvalds /* not completed truncate found. New size was committed together 3221da177e4SLinus Torvalds with "save" link */ 3231da177e4SLinus Torvalds reiserfs_info(s, "Truncating %k to %Ld ..", 3241da177e4SLinus Torvalds INODE_PKEY(inode), inode->i_size); 325bd4c625cSLinus Torvalds reiserfs_truncate_file(inode, 326bd4c625cSLinus Torvalds 0 327bd4c625cSLinus Torvalds /*don't update modification time */ 328bd4c625cSLinus Torvalds ); 3291da177e4SLinus Torvalds retval = remove_save_link(inode, truncate); 3301da177e4SLinus Torvalds } else { 3311da177e4SLinus Torvalds REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask; 3321da177e4SLinus Torvalds /* not completed unlink (rmdir) found */ 3331da177e4SLinus Torvalds reiserfs_info(s, "Removing %k..", INODE_PKEY(inode)); 334fb46f341SLepton Wu if (memcmp(&last_inode_key, INODE_PKEY(inode), 335fb46f341SLepton Wu sizeof(last_inode_key))){ 336fb46f341SLepton Wu last_inode_key = *INODE_PKEY(inode); 3371da177e4SLinus Torvalds /* removal gets completed in iput */ 3381da177e4SLinus Torvalds retval = 0; 339fb46f341SLepton Wu } else { 34045b03d5eSJeff Mahoney reiserfs_warning(s, "super-2189", "Dead loop " 34145b03d5eSJeff Mahoney "in finish_unfinished " 34245b03d5eSJeff Mahoney "detected, just remove " 34345b03d5eSJeff Mahoney "save link\n"); 344fb46f341SLepton Wu retval = remove_save_link_only(s, 345fb46f341SLepton Wu &save_link_key, 0); 346fb46f341SLepton Wu } 3471da177e4SLinus Torvalds } 3481da177e4SLinus Torvalds 3491da177e4SLinus Torvalds iput(inode); 3501da177e4SLinus Torvalds printk("done\n"); 3511da177e4SLinus Torvalds done++; 3521da177e4SLinus Torvalds } 3531da177e4SLinus Torvalds REISERFS_SB(s)->s_is_unlinked_ok = 0; 3541da177e4SLinus Torvalds 3551da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 3561da177e4SLinus Torvalds /* Turn quotas off */ 3571da177e4SLinus Torvalds for (i = 0; i < MAXQUOTAS; i++) { 358f4b113aeSJan Kara if (sb_dqopt(s)->files[i] && quota_enabled[i]) 359287a8095SChristoph Hellwig dquot_quota_off(s, i); 3601da177e4SLinus Torvalds } 3611da177e4SLinus Torvalds if (ms_active_set) 3621da177e4SLinus Torvalds /* Restore the flag back */ 3631da177e4SLinus Torvalds s->s_flags &= ~MS_ACTIVE; 3641da177e4SLinus Torvalds #endif 3651da177e4SLinus Torvalds pathrelse(&path); 3661da177e4SLinus Torvalds if (done) 3671da177e4SLinus Torvalds reiserfs_info(s, "There were %d uncompleted unlinks/truncates. " 3681da177e4SLinus Torvalds "Completed\n", done); 3691da177e4SLinus Torvalds return retval; 3701da177e4SLinus Torvalds } 3711da177e4SLinus Torvalds 3721da177e4SLinus Torvalds /* to protect file being unlinked from getting lost we "safe" link files 3731da177e4SLinus Torvalds being unlinked. This link will be deleted in the same transaction with last 3743a4fa0a2SRobert P. J. Day item of file. mounting the filesystem we scan all these links and remove 3751da177e4SLinus Torvalds files which almost got lost */ 3761da177e4SLinus Torvalds void add_save_link(struct reiserfs_transaction_handle *th, 3771da177e4SLinus Torvalds struct inode *inode, int truncate) 3781da177e4SLinus Torvalds { 3791da177e4SLinus Torvalds INITIALIZE_PATH(path); 3801da177e4SLinus Torvalds int retval; 3811da177e4SLinus Torvalds struct cpu_key key; 3821da177e4SLinus Torvalds struct item_head ih; 3833e8962beSAl Viro __le32 link; 3841da177e4SLinus Torvalds 3851da177e4SLinus Torvalds BUG_ON(!th->t_trans_id); 3861da177e4SLinus Torvalds 3871da177e4SLinus Torvalds /* file can only get one "save link" of each kind */ 3881da177e4SLinus Torvalds RFALSE(truncate && 3891da177e4SLinus Torvalds (REISERFS_I(inode)->i_flags & i_link_saved_truncate_mask), 3901da177e4SLinus Torvalds "saved link already exists for truncated inode %lx", 3911da177e4SLinus Torvalds (long)inode->i_ino); 3921da177e4SLinus Torvalds RFALSE(!truncate && 3931da177e4SLinus Torvalds (REISERFS_I(inode)->i_flags & i_link_saved_unlink_mask), 3941da177e4SLinus Torvalds "saved link already exists for unlinked inode %lx", 3951da177e4SLinus Torvalds (long)inode->i_ino); 3961da177e4SLinus Torvalds 3971da177e4SLinus Torvalds /* setup key of "save" link */ 3981da177e4SLinus Torvalds key.version = KEY_FORMAT_3_5; 3991da177e4SLinus Torvalds key.on_disk_key.k_dir_id = MAX_KEY_OBJECTID; 4001da177e4SLinus Torvalds key.on_disk_key.k_objectid = inode->i_ino; 4011da177e4SLinus Torvalds if (!truncate) { 4021da177e4SLinus Torvalds /* unlink, rmdir, rename */ 4031da177e4SLinus Torvalds set_cpu_key_k_offset(&key, 1 + inode->i_sb->s_blocksize); 4041da177e4SLinus Torvalds set_cpu_key_k_type(&key, TYPE_DIRECT); 4051da177e4SLinus Torvalds 4061da177e4SLinus Torvalds /* item head of "safe" link */ 407bd4c625cSLinus Torvalds make_le_item_head(&ih, &key, key.version, 408bd4c625cSLinus Torvalds 1 + inode->i_sb->s_blocksize, TYPE_DIRECT, 4091da177e4SLinus Torvalds 4 /*length */ , 0xffff /*free space */ ); 4101da177e4SLinus Torvalds } else { 4111da177e4SLinus Torvalds /* truncate */ 4121da177e4SLinus Torvalds if (S_ISDIR(inode->i_mode)) 41345b03d5eSJeff Mahoney reiserfs_warning(inode->i_sb, "green-2102", 41445b03d5eSJeff Mahoney "Adding a truncate savelink for " 41545b03d5eSJeff Mahoney "a directory %k! Please report", 416bd4c625cSLinus Torvalds INODE_PKEY(inode)); 4171da177e4SLinus Torvalds set_cpu_key_k_offset(&key, 1); 4181da177e4SLinus Torvalds set_cpu_key_k_type(&key, TYPE_INDIRECT); 4191da177e4SLinus Torvalds 4201da177e4SLinus Torvalds /* item head of "safe" link */ 4211da177e4SLinus Torvalds make_le_item_head(&ih, &key, key.version, 1, TYPE_INDIRECT, 4221da177e4SLinus Torvalds 4 /*length */ , 0 /*free space */ ); 4231da177e4SLinus Torvalds } 4241da177e4SLinus Torvalds key.key_length = 3; 4251da177e4SLinus Torvalds 4261da177e4SLinus Torvalds /* look for its place in the tree */ 4271da177e4SLinus Torvalds retval = search_item(inode->i_sb, &key, &path); 4281da177e4SLinus Torvalds if (retval != ITEM_NOT_FOUND) { 4291da177e4SLinus Torvalds if (retval != -ENOSPC) 4300030b645SJeff Mahoney reiserfs_error(inode->i_sb, "vs-2100", 431bd4c625cSLinus Torvalds "search_by_key (%K) returned %d", &key, 432bd4c625cSLinus Torvalds retval); 4331da177e4SLinus Torvalds pathrelse(&path); 4341da177e4SLinus Torvalds return; 4351da177e4SLinus Torvalds } 4361da177e4SLinus Torvalds 4371da177e4SLinus Torvalds /* body of "save" link */ 4381da177e4SLinus Torvalds link = INODE_PKEY(inode)->k_dir_id; 4391da177e4SLinus Torvalds 44025985edcSLucas De Marchi /* put "save" link into tree, don't charge quota to anyone */ 441bd4c625cSLinus Torvalds retval = 442bd4c625cSLinus Torvalds reiserfs_insert_item(th, &path, &key, &ih, NULL, (char *)&link); 4431da177e4SLinus Torvalds if (retval) { 4441da177e4SLinus Torvalds if (retval != -ENOSPC) 4450030b645SJeff Mahoney reiserfs_error(inode->i_sb, "vs-2120", 44645b03d5eSJeff Mahoney "insert_item returned %d", retval); 4471da177e4SLinus Torvalds } else { 4481da177e4SLinus Torvalds if (truncate) 449bd4c625cSLinus Torvalds REISERFS_I(inode)->i_flags |= 450bd4c625cSLinus Torvalds i_link_saved_truncate_mask; 4511da177e4SLinus Torvalds else 4521da177e4SLinus Torvalds REISERFS_I(inode)->i_flags |= i_link_saved_unlink_mask; 4531da177e4SLinus Torvalds } 4541da177e4SLinus Torvalds } 4551da177e4SLinus Torvalds 4561da177e4SLinus Torvalds /* this opens transaction unlike add_save_link */ 4571da177e4SLinus Torvalds int remove_save_link(struct inode *inode, int truncate) 4581da177e4SLinus Torvalds { 4591da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 4601da177e4SLinus Torvalds struct reiserfs_key key; 4611da177e4SLinus Torvalds int err; 4621da177e4SLinus Torvalds 4631da177e4SLinus Torvalds /* we are going to do one balancing only */ 4641da177e4SLinus Torvalds err = journal_begin(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT); 4651da177e4SLinus Torvalds if (err) 4661da177e4SLinus Torvalds return err; 4671da177e4SLinus Torvalds 4681da177e4SLinus Torvalds /* setup key of "save" link */ 4691da177e4SLinus Torvalds key.k_dir_id = cpu_to_le32(MAX_KEY_OBJECTID); 4701da177e4SLinus Torvalds key.k_objectid = INODE_PKEY(inode)->k_objectid; 4711da177e4SLinus Torvalds if (!truncate) { 4721da177e4SLinus Torvalds /* unlink, rmdir, rename */ 4731da177e4SLinus Torvalds set_le_key_k_offset(KEY_FORMAT_3_5, &key, 4741da177e4SLinus Torvalds 1 + inode->i_sb->s_blocksize); 4751da177e4SLinus Torvalds set_le_key_k_type(KEY_FORMAT_3_5, &key, TYPE_DIRECT); 4761da177e4SLinus Torvalds } else { 4771da177e4SLinus Torvalds /* truncate */ 4781da177e4SLinus Torvalds set_le_key_k_offset(KEY_FORMAT_3_5, &key, 1); 4791da177e4SLinus Torvalds set_le_key_k_type(KEY_FORMAT_3_5, &key, TYPE_INDIRECT); 4801da177e4SLinus Torvalds } 4811da177e4SLinus Torvalds 4821da177e4SLinus Torvalds if ((truncate && 4831da177e4SLinus Torvalds (REISERFS_I(inode)->i_flags & i_link_saved_truncate_mask)) || 4841da177e4SLinus Torvalds (!truncate && 4851da177e4SLinus Torvalds (REISERFS_I(inode)->i_flags & i_link_saved_unlink_mask))) 4861da177e4SLinus Torvalds /* don't take quota bytes from anywhere */ 4871da177e4SLinus Torvalds reiserfs_delete_solid_item(&th, NULL, &key); 4881da177e4SLinus Torvalds if (!truncate) { 4891da177e4SLinus Torvalds reiserfs_release_objectid(&th, inode->i_ino); 4901da177e4SLinus Torvalds REISERFS_I(inode)->i_flags &= ~i_link_saved_unlink_mask; 4911da177e4SLinus Torvalds } else 4921da177e4SLinus Torvalds REISERFS_I(inode)->i_flags &= ~i_link_saved_truncate_mask; 4931da177e4SLinus Torvalds 4941da177e4SLinus Torvalds return journal_end(&th, inode->i_sb, JOURNAL_PER_BALANCE_CNT); 4951da177e4SLinus Torvalds } 4961da177e4SLinus Torvalds 497edc666e2SDavid Howells static void reiserfs_kill_sb(struct super_block *s) 4981da177e4SLinus Torvalds { 499edc666e2SDavid Howells if (REISERFS_SB(s)) { 500a9e36da6SJeff Mahoney /* 501a9e36da6SJeff Mahoney * Force any pending inode evictions to occur now. Any 502a9e36da6SJeff Mahoney * inodes to be removed that have extended attributes 503a9e36da6SJeff Mahoney * associated with them need to clean them up before 504a9e36da6SJeff Mahoney * we can release the extended attribute root dentries. 505a9e36da6SJeff Mahoney * shrink_dcache_for_umount will BUG if we don't release 506a9e36da6SJeff Mahoney * those before it's called so ->put_super is too late. 507a9e36da6SJeff Mahoney */ 508a9e36da6SJeff Mahoney shrink_dcache_sb(s); 509a9e36da6SJeff Mahoney 5101da177e4SLinus Torvalds dput(REISERFS_SB(s)->xattr_root); 511edc666e2SDavid Howells REISERFS_SB(s)->xattr_root = NULL; 5121da177e4SLinus Torvalds dput(REISERFS_SB(s)->priv_root); 513edc666e2SDavid Howells REISERFS_SB(s)->priv_root = NULL; 5141da177e4SLinus Torvalds } 515edc666e2SDavid Howells 516edc666e2SDavid Howells kill_block_super(s); 517edc666e2SDavid Howells } 518edc666e2SDavid Howells 519edc666e2SDavid Howells static void reiserfs_put_super(struct super_block *s) 520edc666e2SDavid Howells { 521edc666e2SDavid Howells struct reiserfs_transaction_handle th; 522edc666e2SDavid Howells th.t_trans_id = 0; 5231da177e4SLinus Torvalds 524e0ccfd95SChristoph Hellwig dquot_disable(s, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); 525e0ccfd95SChristoph Hellwig 5268ebc4232SFrederic Weisbecker reiserfs_write_lock(s); 5276cfd0148SChristoph Hellwig 5281da177e4SLinus Torvalds /* change file system state to current state if it was mounted with read-write permissions */ 5291da177e4SLinus Torvalds if (!(s->s_flags & MS_RDONLY)) { 5301da177e4SLinus Torvalds if (!journal_begin(&th, s, 10)) { 531bd4c625cSLinus Torvalds reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 532bd4c625cSLinus Torvalds 1); 533bd4c625cSLinus Torvalds set_sb_umount_state(SB_DISK_SUPER_BLOCK(s), 534bd4c625cSLinus Torvalds REISERFS_SB(s)->s_mount_state); 5351da177e4SLinus Torvalds journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); 5361da177e4SLinus Torvalds } 5371da177e4SLinus Torvalds } 5381da177e4SLinus Torvalds 5391da177e4SLinus Torvalds /* note, journal_release checks for readonly mount, and can decide not 5401da177e4SLinus Torvalds ** to do a journal_end 5411da177e4SLinus Torvalds */ 5421da177e4SLinus Torvalds journal_release(&th, s); 5431da177e4SLinus Torvalds 5445065227bSJeff Mahoney reiserfs_free_bitmap_cache(s); 5451da177e4SLinus Torvalds 5461da177e4SLinus Torvalds brelse(SB_BUFFER_WITH_SB(s)); 5471da177e4SLinus Torvalds 5481da177e4SLinus Torvalds print_statistics(s); 5491da177e4SLinus Torvalds 5501da177e4SLinus Torvalds if (REISERFS_SB(s)->reserved_blocks != 0) { 55145b03d5eSJeff Mahoney reiserfs_warning(s, "green-2005", "reserved blocks left %d", 5521da177e4SLinus Torvalds REISERFS_SB(s)->reserved_blocks); 5531da177e4SLinus Torvalds } 5541da177e4SLinus Torvalds 5551da177e4SLinus Torvalds reiserfs_proc_info_done(s); 5561da177e4SLinus Torvalds 5578ebc4232SFrederic Weisbecker reiserfs_write_unlock(s); 5588ebc4232SFrederic Weisbecker mutex_destroy(&REISERFS_SB(s)->lock); 5591da177e4SLinus Torvalds kfree(s->s_fs_info); 5601da177e4SLinus Torvalds s->s_fs_info = NULL; 5611da177e4SLinus Torvalds } 5621da177e4SLinus Torvalds 563e18b890bSChristoph Lameter static struct kmem_cache *reiserfs_inode_cachep; 5641da177e4SLinus Torvalds 5651da177e4SLinus Torvalds static struct inode *reiserfs_alloc_inode(struct super_block *sb) 5661da177e4SLinus Torvalds { 5671da177e4SLinus Torvalds struct reiserfs_inode_info *ei; 568bd4c625cSLinus Torvalds ei = (struct reiserfs_inode_info *) 569e94b1766SChristoph Lameter kmem_cache_alloc(reiserfs_inode_cachep, GFP_KERNEL); 5701da177e4SLinus Torvalds if (!ei) 5711da177e4SLinus Torvalds return NULL; 5720e4f6a79SAl Viro atomic_set(&ei->openers, 0); 5730e4f6a79SAl Viro mutex_init(&ei->tailpack); 5741da177e4SLinus Torvalds return &ei->vfs_inode; 5751da177e4SLinus Torvalds } 5761da177e4SLinus Torvalds 577fa0d7e3dSNick Piggin static void reiserfs_i_callback(struct rcu_head *head) 578fa0d7e3dSNick Piggin { 579fa0d7e3dSNick Piggin struct inode *inode = container_of(head, struct inode, i_rcu); 580fa0d7e3dSNick Piggin kmem_cache_free(reiserfs_inode_cachep, REISERFS_I(inode)); 581fa0d7e3dSNick Piggin } 582fa0d7e3dSNick Piggin 5831da177e4SLinus Torvalds static void reiserfs_destroy_inode(struct inode *inode) 5841da177e4SLinus Torvalds { 585fa0d7e3dSNick Piggin call_rcu(&inode->i_rcu, reiserfs_i_callback); 5861da177e4SLinus Torvalds } 5871da177e4SLinus Torvalds 58851cc5068SAlexey Dobriyan static void init_once(void *foo) 5891da177e4SLinus Torvalds { 5901da177e4SLinus Torvalds struct reiserfs_inode_info *ei = (struct reiserfs_inode_info *)foo; 5911da177e4SLinus Torvalds 5921da177e4SLinus Torvalds INIT_LIST_HEAD(&ei->i_prealloc_list); 5931da177e4SLinus Torvalds inode_init_once(&ei->vfs_inode); 5941da177e4SLinus Torvalds } 5951da177e4SLinus Torvalds 5961da177e4SLinus Torvalds static int init_inodecache(void) 5971da177e4SLinus Torvalds { 5981da177e4SLinus Torvalds reiserfs_inode_cachep = kmem_cache_create("reiser_inode_cache", 599bd4c625cSLinus Torvalds sizeof(struct 600bd4c625cSLinus Torvalds reiserfs_inode_info), 601fffb60f9SPaul Jackson 0, (SLAB_RECLAIM_ACCOUNT| 602fffb60f9SPaul Jackson SLAB_MEM_SPREAD), 60320c2df83SPaul Mundt init_once); 6041da177e4SLinus Torvalds if (reiserfs_inode_cachep == NULL) 6051da177e4SLinus Torvalds return -ENOMEM; 6061da177e4SLinus Torvalds return 0; 6071da177e4SLinus Torvalds } 6081da177e4SLinus Torvalds 6091da177e4SLinus Torvalds static void destroy_inodecache(void) 6101da177e4SLinus Torvalds { 6118c0a8537SKirill A. Shutemov /* 6128c0a8537SKirill A. Shutemov * Make sure all delayed rcu free inodes are flushed before we 6138c0a8537SKirill A. Shutemov * destroy cache. 6148c0a8537SKirill A. Shutemov */ 6158c0a8537SKirill A. Shutemov rcu_barrier(); 6161a1d92c1SAlexey Dobriyan kmem_cache_destroy(reiserfs_inode_cachep); 6171da177e4SLinus Torvalds } 6181da177e4SLinus Torvalds 6191da177e4SLinus Torvalds /* we don't mark inodes dirty, we just log them */ 620aa385729SChristoph Hellwig static void reiserfs_dirty_inode(struct inode *inode, int flags) 621bd4c625cSLinus Torvalds { 6221da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 6231da177e4SLinus Torvalds 6241da177e4SLinus Torvalds int err = 0; 625dc8f6d89SFrederic Weisbecker int lock_depth; 626dc8f6d89SFrederic Weisbecker 6271da177e4SLinus Torvalds if (inode->i_sb->s_flags & MS_RDONLY) { 62845b03d5eSJeff Mahoney reiserfs_warning(inode->i_sb, "clm-6006", 62945b03d5eSJeff Mahoney "writing inode %lu on readonly FS", 6301da177e4SLinus Torvalds inode->i_ino); 6311da177e4SLinus Torvalds return; 6321da177e4SLinus Torvalds } 633dc8f6d89SFrederic Weisbecker lock_depth = reiserfs_write_lock_once(inode->i_sb); 6341da177e4SLinus Torvalds 6351da177e4SLinus Torvalds /* this is really only used for atime updates, so they don't have 6361da177e4SLinus Torvalds ** to be included in O_SYNC or fsync 6371da177e4SLinus Torvalds */ 6381da177e4SLinus Torvalds err = journal_begin(&th, inode->i_sb, 1); 639dc8f6d89SFrederic Weisbecker if (err) 640dc8f6d89SFrederic Weisbecker goto out; 641dc8f6d89SFrederic Weisbecker 6421da177e4SLinus Torvalds reiserfs_update_sd(&th, inode); 6431da177e4SLinus Torvalds journal_end(&th, inode->i_sb, 1); 644dc8f6d89SFrederic Weisbecker 645dc8f6d89SFrederic Weisbecker out: 646dc8f6d89SFrederic Weisbecker reiserfs_write_unlock_once(inode->i_sb, lock_depth); 6471da177e4SLinus Torvalds } 6481da177e4SLinus Torvalds 649c3aa0776SJan Kara static int reiserfs_show_options(struct seq_file *seq, struct dentry *root) 650c3aa0776SJan Kara { 651c3aa0776SJan Kara struct super_block *s = root->d_sb; 652c3aa0776SJan Kara struct reiserfs_journal *journal = SB_JOURNAL(s); 653c3aa0776SJan Kara long opts = REISERFS_SB(s)->s_mount_opt; 654c3aa0776SJan Kara 655c3aa0776SJan Kara if (opts & (1 << REISERFS_LARGETAIL)) 656c3aa0776SJan Kara seq_puts(seq, ",tails=on"); 657c3aa0776SJan Kara else if (!(opts & (1 << REISERFS_SMALLTAIL))) 658c3aa0776SJan Kara seq_puts(seq, ",notail"); 659c3aa0776SJan Kara /* tails=small is default so we don't show it */ 660c3aa0776SJan Kara 661c3aa0776SJan Kara if (!(opts & (1 << REISERFS_BARRIER_FLUSH))) 662c3aa0776SJan Kara seq_puts(seq, ",barrier=none"); 663c3aa0776SJan Kara /* barrier=flush is default so we don't show it */ 664c3aa0776SJan Kara 665c3aa0776SJan Kara if (opts & (1 << REISERFS_ERROR_CONTINUE)) 666c3aa0776SJan Kara seq_puts(seq, ",errors=continue"); 667c3aa0776SJan Kara else if (opts & (1 << REISERFS_ERROR_PANIC)) 668c3aa0776SJan Kara seq_puts(seq, ",errors=panic"); 669c3aa0776SJan Kara /* errors=ro is default so we don't show it */ 670c3aa0776SJan Kara 671c3aa0776SJan Kara if (opts & (1 << REISERFS_DATA_LOG)) 672c3aa0776SJan Kara seq_puts(seq, ",data=journal"); 673c3aa0776SJan Kara else if (opts & (1 << REISERFS_DATA_WRITEBACK)) 674c3aa0776SJan Kara seq_puts(seq, ",data=writeback"); 675c3aa0776SJan Kara /* data=ordered is default so we don't show it */ 676c3aa0776SJan Kara 677c3aa0776SJan Kara if (opts & (1 << REISERFS_ATTRS)) 678c3aa0776SJan Kara seq_puts(seq, ",attrs"); 679c3aa0776SJan Kara 680c3aa0776SJan Kara if (opts & (1 << REISERFS_XATTRS_USER)) 681c3aa0776SJan Kara seq_puts(seq, ",user_xattr"); 682c3aa0776SJan Kara 683c3aa0776SJan Kara if (opts & (1 << REISERFS_EXPOSE_PRIVROOT)) 684c3aa0776SJan Kara seq_puts(seq, ",expose_privroot"); 685c3aa0776SJan Kara 686c3aa0776SJan Kara if (opts & (1 << REISERFS_POSIXACL)) 687c3aa0776SJan Kara seq_puts(seq, ",acl"); 688c3aa0776SJan Kara 689c3aa0776SJan Kara if (REISERFS_SB(s)->s_jdev) 690c3aa0776SJan Kara seq_printf(seq, ",jdev=%s", REISERFS_SB(s)->s_jdev); 691c3aa0776SJan Kara 692c3aa0776SJan Kara if (journal->j_max_commit_age != journal->j_default_max_commit_age) 693c3aa0776SJan Kara seq_printf(seq, ",commit=%d", journal->j_max_commit_age); 694c3aa0776SJan Kara 695c3aa0776SJan Kara #ifdef CONFIG_QUOTA 696c3aa0776SJan Kara if (REISERFS_SB(s)->s_qf_names[USRQUOTA]) 697c3aa0776SJan Kara seq_printf(seq, ",usrjquota=%s", REISERFS_SB(s)->s_qf_names[USRQUOTA]); 698c3aa0776SJan Kara else if (opts & (1 << REISERFS_USRQUOTA)) 699c3aa0776SJan Kara seq_puts(seq, ",usrquota"); 700c3aa0776SJan Kara if (REISERFS_SB(s)->s_qf_names[GRPQUOTA]) 701c3aa0776SJan Kara seq_printf(seq, ",grpjquota=%s", REISERFS_SB(s)->s_qf_names[GRPQUOTA]); 702c3aa0776SJan Kara else if (opts & (1 << REISERFS_GRPQUOTA)) 703c3aa0776SJan Kara seq_puts(seq, ",grpquota"); 704c3aa0776SJan Kara if (REISERFS_SB(s)->s_jquota_fmt) { 705c3aa0776SJan Kara if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_OLD) 706c3aa0776SJan Kara seq_puts(seq, ",jqfmt=vfsold"); 707c3aa0776SJan Kara else if (REISERFS_SB(s)->s_jquota_fmt == QFMT_VFS_V0) 708c3aa0776SJan Kara seq_puts(seq, ",jqfmt=vfsv0"); 709c3aa0776SJan Kara } 710c3aa0776SJan Kara #endif 711c3aa0776SJan Kara 712c3aa0776SJan Kara /* Block allocator options */ 713c3aa0776SJan Kara if (opts & (1 << REISERFS_NO_BORDER)) 714c3aa0776SJan Kara seq_puts(seq, ",block-allocator=noborder"); 715c3aa0776SJan Kara if (opts & (1 << REISERFS_NO_UNHASHED_RELOCATION)) 716c3aa0776SJan Kara seq_puts(seq, ",block-allocator=no_unhashed_relocation"); 717c3aa0776SJan Kara if (opts & (1 << REISERFS_HASHED_RELOCATION)) 718c3aa0776SJan Kara seq_puts(seq, ",block-allocator=hashed_relocation"); 719c3aa0776SJan Kara if (opts & (1 << REISERFS_TEST4)) 720c3aa0776SJan Kara seq_puts(seq, ",block-allocator=test4"); 721c3aa0776SJan Kara show_alloc_options(seq, s); 722c3aa0776SJan Kara return 0; 723c3aa0776SJan Kara } 724c3aa0776SJan Kara 7251da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 726bd4c625cSLinus Torvalds static ssize_t reiserfs_quota_write(struct super_block *, int, const char *, 727bd4c625cSLinus Torvalds size_t, loff_t); 728bd4c625cSLinus Torvalds static ssize_t reiserfs_quota_read(struct super_block *, int, char *, size_t, 729bd4c625cSLinus Torvalds loff_t); 7301da177e4SLinus Torvalds #endif 7311da177e4SLinus Torvalds 732ee9b6d61SJosef 'Jeff' Sipek static const struct super_operations reiserfs_sops = { 7331da177e4SLinus Torvalds .alloc_inode = reiserfs_alloc_inode, 7341da177e4SLinus Torvalds .destroy_inode = reiserfs_destroy_inode, 7351da177e4SLinus Torvalds .write_inode = reiserfs_write_inode, 7361da177e4SLinus Torvalds .dirty_inode = reiserfs_dirty_inode, 737845a2cc0SAl Viro .evict_inode = reiserfs_evict_inode, 7381da177e4SLinus Torvalds .put_super = reiserfs_put_super, 7391da177e4SLinus Torvalds .sync_fs = reiserfs_sync_fs, 740c4be0c1dSTakashi Sato .freeze_fs = reiserfs_freeze, 741c4be0c1dSTakashi Sato .unfreeze_fs = reiserfs_unfreeze, 7421da177e4SLinus Torvalds .statfs = reiserfs_statfs, 7431da177e4SLinus Torvalds .remount_fs = reiserfs_remount, 744c3aa0776SJan Kara .show_options = reiserfs_show_options, 7451da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 7461da177e4SLinus Torvalds .quota_read = reiserfs_quota_read, 7471da177e4SLinus Torvalds .quota_write = reiserfs_quota_write, 7481da177e4SLinus Torvalds #endif 7491da177e4SLinus Torvalds }; 7501da177e4SLinus Torvalds 7511da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 7521da177e4SLinus Torvalds #define QTYPE2NAME(t) ((t)==USRQUOTA?"user":"group") 7531da177e4SLinus Torvalds 7541da177e4SLinus Torvalds static int reiserfs_write_dquot(struct dquot *); 7551da177e4SLinus Torvalds static int reiserfs_acquire_dquot(struct dquot *); 7561da177e4SLinus Torvalds static int reiserfs_release_dquot(struct dquot *); 7571da177e4SLinus Torvalds static int reiserfs_mark_dquot_dirty(struct dquot *); 7581da177e4SLinus Torvalds static int reiserfs_write_info(struct super_block *, int); 759f00c9e44SJan Kara static int reiserfs_quota_on(struct super_block *, int, int, struct path *); 7601da177e4SLinus Torvalds 76161e225dcSAlexey Dobriyan static const struct dquot_operations reiserfs_quota_operations = { 7621da177e4SLinus Torvalds .write_dquot = reiserfs_write_dquot, 7631da177e4SLinus Torvalds .acquire_dquot = reiserfs_acquire_dquot, 7641da177e4SLinus Torvalds .release_dquot = reiserfs_release_dquot, 7651da177e4SLinus Torvalds .mark_dirty = reiserfs_mark_dquot_dirty, 7661da177e4SLinus Torvalds .write_info = reiserfs_write_info, 7674103003bSJan Kara .alloc_dquot = dquot_alloc, 7684103003bSJan Kara .destroy_dquot = dquot_destroy, 7691da177e4SLinus Torvalds }; 7701da177e4SLinus Torvalds 7710d54b217SAlexey Dobriyan static const struct quotactl_ops reiserfs_qctl_operations = { 7721da177e4SLinus Torvalds .quota_on = reiserfs_quota_on, 773287a8095SChristoph Hellwig .quota_off = dquot_quota_off, 774287a8095SChristoph Hellwig .quota_sync = dquot_quota_sync, 775287a8095SChristoph Hellwig .get_info = dquot_get_dqinfo, 776287a8095SChristoph Hellwig .set_info = dquot_set_dqinfo, 777287a8095SChristoph Hellwig .get_dqblk = dquot_get_dqblk, 778287a8095SChristoph Hellwig .set_dqblk = dquot_set_dqblk, 7791da177e4SLinus Torvalds }; 7801da177e4SLinus Torvalds #endif 7811da177e4SLinus Torvalds 78239655164SChristoph Hellwig static const struct export_operations reiserfs_export_ops = { 7831da177e4SLinus Torvalds .encode_fh = reiserfs_encode_fh, 784be55caf1SChristoph Hellwig .fh_to_dentry = reiserfs_fh_to_dentry, 785be55caf1SChristoph Hellwig .fh_to_parent = reiserfs_fh_to_parent, 7861da177e4SLinus Torvalds .get_parent = reiserfs_get_parent, 7871da177e4SLinus Torvalds }; 7881da177e4SLinus Torvalds 7891da177e4SLinus Torvalds /* this struct is used in reiserfs_getopt () for containing the value for those 7901da177e4SLinus Torvalds mount options that have values rather than being toggles. */ 7911da177e4SLinus Torvalds typedef struct { 7921da177e4SLinus Torvalds char *value; 7931da177e4SLinus Torvalds int setmask; /* bitmask which is to set on mount_options bitmask when this 7941da177e4SLinus Torvalds value is found, 0 is no bits are to be changed. */ 7951da177e4SLinus Torvalds int clrmask; /* bitmask which is to clear on mount_options bitmask when this 7961da177e4SLinus Torvalds value is found, 0 is no bits are to be changed. This is 7971da177e4SLinus Torvalds applied BEFORE setmask */ 7981da177e4SLinus Torvalds } arg_desc_t; 7991da177e4SLinus Torvalds 8001da177e4SLinus Torvalds /* Set this bit in arg_required to allow empty arguments */ 8011da177e4SLinus Torvalds #define REISERFS_OPT_ALLOWEMPTY 31 8021da177e4SLinus Torvalds 8031da177e4SLinus Torvalds /* this struct is used in reiserfs_getopt() for describing the set of reiserfs 8041da177e4SLinus Torvalds mount options */ 8051da177e4SLinus Torvalds typedef struct { 8061da177e4SLinus Torvalds char *option_name; 8071da177e4SLinus Torvalds int arg_required; /* 0 if argument is not required, not 0 otherwise */ 8081da177e4SLinus Torvalds const arg_desc_t *values; /* list of values accepted by an option */ 8091da177e4SLinus Torvalds int setmask; /* bitmask which is to set on mount_options bitmask when this 8101da177e4SLinus Torvalds value is found, 0 is no bits are to be changed. */ 8111da177e4SLinus Torvalds int clrmask; /* bitmask which is to clear on mount_options bitmask when this 8121da177e4SLinus Torvalds value is found, 0 is no bits are to be changed. This is 8131da177e4SLinus Torvalds applied BEFORE setmask */ 8141da177e4SLinus Torvalds } opt_desc_t; 8151da177e4SLinus Torvalds 8161da177e4SLinus Torvalds /* possible values for -o data= */ 8171da177e4SLinus Torvalds static const arg_desc_t logging_mode[] = { 818bd4c625cSLinus Torvalds {"ordered", 1 << REISERFS_DATA_ORDERED, 819bd4c625cSLinus Torvalds (1 << REISERFS_DATA_LOG | 1 << REISERFS_DATA_WRITEBACK)}, 820bd4c625cSLinus Torvalds {"journal", 1 << REISERFS_DATA_LOG, 821bd4c625cSLinus Torvalds (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_WRITEBACK)}, 822bd4c625cSLinus Torvalds {"writeback", 1 << REISERFS_DATA_WRITEBACK, 823bd4c625cSLinus Torvalds (1 << REISERFS_DATA_ORDERED | 1 << REISERFS_DATA_LOG)}, 824cd02b966SVladimir V. Saveliev {.value = NULL} 8251da177e4SLinus Torvalds }; 8261da177e4SLinus Torvalds 8271da177e4SLinus Torvalds /* possible values for -o barrier= */ 8281da177e4SLinus Torvalds static const arg_desc_t barrier_mode[] = { 8291da177e4SLinus Torvalds {"none", 1 << REISERFS_BARRIER_NONE, 1 << REISERFS_BARRIER_FLUSH}, 8301da177e4SLinus Torvalds {"flush", 1 << REISERFS_BARRIER_FLUSH, 1 << REISERFS_BARRIER_NONE}, 831cd02b966SVladimir V. Saveliev {.value = NULL} 8321da177e4SLinus Torvalds }; 8331da177e4SLinus Torvalds 8341da177e4SLinus Torvalds /* possible values for "-o block-allocator=" and bits which are to be set in 8351da177e4SLinus Torvalds s_mount_opt of reiserfs specific part of in-core super block */ 8361da177e4SLinus Torvalds static const arg_desc_t balloc[] = { 8371da177e4SLinus Torvalds {"noborder", 1 << REISERFS_NO_BORDER, 0}, 8381da177e4SLinus Torvalds {"border", 0, 1 << REISERFS_NO_BORDER}, 8391da177e4SLinus Torvalds {"no_unhashed_relocation", 1 << REISERFS_NO_UNHASHED_RELOCATION, 0}, 8401da177e4SLinus Torvalds {"hashed_relocation", 1 << REISERFS_HASHED_RELOCATION, 0}, 8411da177e4SLinus Torvalds {"test4", 1 << REISERFS_TEST4, 0}, 8421da177e4SLinus Torvalds {"notest4", 0, 1 << REISERFS_TEST4}, 8431da177e4SLinus Torvalds {NULL, 0, 0} 8441da177e4SLinus Torvalds }; 8451da177e4SLinus Torvalds 8461da177e4SLinus Torvalds static const arg_desc_t tails[] = { 8471da177e4SLinus Torvalds {"on", 1 << REISERFS_LARGETAIL, 1 << REISERFS_SMALLTAIL}, 8481da177e4SLinus Torvalds {"off", 0, (1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)}, 8491da177e4SLinus Torvalds {"small", 1 << REISERFS_SMALLTAIL, 1 << REISERFS_LARGETAIL}, 8501da177e4SLinus Torvalds {NULL, 0, 0} 8511da177e4SLinus Torvalds }; 8521da177e4SLinus Torvalds 8531da177e4SLinus Torvalds static const arg_desc_t error_actions[] = { 8541da177e4SLinus Torvalds {"panic", 1 << REISERFS_ERROR_PANIC, 8551da177e4SLinus Torvalds (1 << REISERFS_ERROR_RO | 1 << REISERFS_ERROR_CONTINUE)}, 8561da177e4SLinus Torvalds {"ro-remount", 1 << REISERFS_ERROR_RO, 8571da177e4SLinus Torvalds (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_CONTINUE)}, 8581da177e4SLinus Torvalds #ifdef REISERFS_JOURNAL_ERROR_ALLOWS_NO_LOG 8591da177e4SLinus Torvalds {"continue", 1 << REISERFS_ERROR_CONTINUE, 8601da177e4SLinus Torvalds (1 << REISERFS_ERROR_PANIC | 1 << REISERFS_ERROR_RO)}, 8611da177e4SLinus Torvalds #endif 8621da177e4SLinus Torvalds {NULL, 0, 0}, 8631da177e4SLinus Torvalds }; 8641da177e4SLinus Torvalds 8651da177e4SLinus Torvalds /* proceed only one option from a list *cur - string containing of mount options 8661da177e4SLinus Torvalds opts - array of options which are accepted 8671da177e4SLinus Torvalds opt_arg - if option is found and requires an argument and if it is specifed 8681da177e4SLinus Torvalds in the input - pointer to the argument is stored here 8691da177e4SLinus Torvalds bit_flags - if option requires to set a certain bit - it is set here 8701da177e4SLinus Torvalds return -1 if unknown option is found, opt->arg_required otherwise */ 871bd4c625cSLinus Torvalds static int reiserfs_getopt(struct super_block *s, char **cur, opt_desc_t * opts, 872bd4c625cSLinus Torvalds char **opt_arg, unsigned long *bit_flags) 8731da177e4SLinus Torvalds { 8741da177e4SLinus Torvalds char *p; 8751da177e4SLinus Torvalds /* foo=bar, 8761da177e4SLinus Torvalds ^ ^ ^ 8771da177e4SLinus Torvalds | | +-- option_end 8781da177e4SLinus Torvalds | +-- arg_start 8791da177e4SLinus Torvalds +-- option_start 8801da177e4SLinus Torvalds */ 8811da177e4SLinus Torvalds const opt_desc_t *opt; 8821da177e4SLinus Torvalds const arg_desc_t *arg; 8831da177e4SLinus Torvalds 8841da177e4SLinus Torvalds p = *cur; 8851da177e4SLinus Torvalds 8861da177e4SLinus Torvalds /* assume argument cannot contain commas */ 8871da177e4SLinus Torvalds *cur = strchr(p, ','); 8881da177e4SLinus Torvalds if (*cur) { 8891da177e4SLinus Torvalds *(*cur) = '\0'; 8901da177e4SLinus Torvalds (*cur)++; 8911da177e4SLinus Torvalds } 8921da177e4SLinus Torvalds 8931da177e4SLinus Torvalds if (!strncmp(p, "alloc=", 6)) { 8941da177e4SLinus Torvalds /* Ugly special case, probably we should redo options parser so that 8951da177e4SLinus Torvalds it can understand several arguments for some options, also so that 8961da177e4SLinus Torvalds it can fill several bitfields with option values. */ 8971da177e4SLinus Torvalds if (reiserfs_parse_alloc_options(s, p + 6)) { 8981da177e4SLinus Torvalds return -1; 8991da177e4SLinus Torvalds } else { 9001da177e4SLinus Torvalds return 0; 9011da177e4SLinus Torvalds } 9021da177e4SLinus Torvalds } 9031da177e4SLinus Torvalds 9041da177e4SLinus Torvalds /* for every option in the list */ 9051da177e4SLinus Torvalds for (opt = opts; opt->option_name; opt++) { 9061da177e4SLinus Torvalds if (!strncmp(p, opt->option_name, strlen(opt->option_name))) { 9071da177e4SLinus Torvalds if (bit_flags) { 908bd4c625cSLinus Torvalds if (opt->clrmask == 909bd4c625cSLinus Torvalds (1 << REISERFS_UNSUPPORTED_OPT)) 91045b03d5eSJeff Mahoney reiserfs_warning(s, "super-6500", 91145b03d5eSJeff Mahoney "%s not supported.\n", 912bd4c625cSLinus Torvalds p); 9131da177e4SLinus Torvalds else 9141da177e4SLinus Torvalds *bit_flags &= ~opt->clrmask; 915bd4c625cSLinus Torvalds if (opt->setmask == 916bd4c625cSLinus Torvalds (1 << REISERFS_UNSUPPORTED_OPT)) 91745b03d5eSJeff Mahoney reiserfs_warning(s, "super-6501", 91845b03d5eSJeff Mahoney "%s not supported.\n", 919bd4c625cSLinus Torvalds p); 9201da177e4SLinus Torvalds else 9211da177e4SLinus Torvalds *bit_flags |= opt->setmask; 9221da177e4SLinus Torvalds } 9231da177e4SLinus Torvalds break; 9241da177e4SLinus Torvalds } 9251da177e4SLinus Torvalds } 9261da177e4SLinus Torvalds if (!opt->option_name) { 92745b03d5eSJeff Mahoney reiserfs_warning(s, "super-6502", 92845b03d5eSJeff Mahoney "unknown mount option \"%s\"", p); 9291da177e4SLinus Torvalds return -1; 9301da177e4SLinus Torvalds } 9311da177e4SLinus Torvalds 9321da177e4SLinus Torvalds p += strlen(opt->option_name); 9331da177e4SLinus Torvalds switch (*p) { 9341da177e4SLinus Torvalds case '=': 9351da177e4SLinus Torvalds if (!opt->arg_required) { 93645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6503", 93745b03d5eSJeff Mahoney "the option \"%s\" does not " 93845b03d5eSJeff Mahoney "require an argument\n", 9391da177e4SLinus Torvalds opt->option_name); 9401da177e4SLinus Torvalds return -1; 9411da177e4SLinus Torvalds } 9421da177e4SLinus Torvalds break; 9431da177e4SLinus Torvalds 9441da177e4SLinus Torvalds case 0: 9451da177e4SLinus Torvalds if (opt->arg_required) { 94645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6504", 94745b03d5eSJeff Mahoney "the option \"%s\" requires an " 94845b03d5eSJeff Mahoney "argument\n", opt->option_name); 9491da177e4SLinus Torvalds return -1; 9501da177e4SLinus Torvalds } 9511da177e4SLinus Torvalds break; 9521da177e4SLinus Torvalds default: 95345b03d5eSJeff Mahoney reiserfs_warning(s, "super-6505", 95445b03d5eSJeff Mahoney "head of option \"%s\" is only correct\n", 955bd4c625cSLinus Torvalds opt->option_name); 9561da177e4SLinus Torvalds return -1; 9571da177e4SLinus Torvalds } 9581da177e4SLinus Torvalds 9591da177e4SLinus Torvalds /* move to the argument, or to next option if argument is not required */ 9601da177e4SLinus Torvalds p++; 9611da177e4SLinus Torvalds 962bd4c625cSLinus Torvalds if (opt->arg_required 963bd4c625cSLinus Torvalds && !(opt->arg_required & (1 << REISERFS_OPT_ALLOWEMPTY)) 964bd4c625cSLinus Torvalds && !strlen(p)) { 9651da177e4SLinus Torvalds /* this catches "option=," if not allowed */ 96645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6506", 96745b03d5eSJeff Mahoney "empty argument for \"%s\"\n", 968bd4c625cSLinus Torvalds opt->option_name); 9691da177e4SLinus Torvalds return -1; 9701da177e4SLinus Torvalds } 9711da177e4SLinus Torvalds 9721da177e4SLinus Torvalds if (!opt->values) { 9731da177e4SLinus Torvalds /* *=NULLopt_arg contains pointer to argument */ 9741da177e4SLinus Torvalds *opt_arg = p; 9751da177e4SLinus Torvalds return opt->arg_required & ~(1 << REISERFS_OPT_ALLOWEMPTY); 9761da177e4SLinus Torvalds } 9771da177e4SLinus Torvalds 9781da177e4SLinus Torvalds /* values possible for this option are listed in opt->values */ 9791da177e4SLinus Torvalds for (arg = opt->values; arg->value; arg++) { 9801da177e4SLinus Torvalds if (!strcmp(p, arg->value)) { 9811da177e4SLinus Torvalds if (bit_flags) { 9821da177e4SLinus Torvalds *bit_flags &= ~arg->clrmask; 9831da177e4SLinus Torvalds *bit_flags |= arg->setmask; 9841da177e4SLinus Torvalds } 9851da177e4SLinus Torvalds return opt->arg_required; 9861da177e4SLinus Torvalds } 9871da177e4SLinus Torvalds } 9881da177e4SLinus Torvalds 98945b03d5eSJeff Mahoney reiserfs_warning(s, "super-6506", 99045b03d5eSJeff Mahoney "bad value \"%s\" for option \"%s\"\n", p, 991bd4c625cSLinus Torvalds opt->option_name); 9921da177e4SLinus Torvalds return -1; 9931da177e4SLinus Torvalds } 9941da177e4SLinus Torvalds 9951da177e4SLinus Torvalds /* returns 0 if something is wrong in option string, 1 - otherwise */ 9961da177e4SLinus Torvalds static int reiserfs_parse_options(struct super_block *s, char *options, /* string given via mount's -o */ 9971da177e4SLinus Torvalds unsigned long *mount_options, 9981da177e4SLinus Torvalds /* after the parsing phase, contains the 9991da177e4SLinus Torvalds collection of bitflags defining what 10001da177e4SLinus Torvalds mount options were selected. */ 10011da177e4SLinus Torvalds unsigned long *blocks, /* strtol-ed from NNN of resize=NNN */ 10021da177e4SLinus Torvalds char **jdev_name, 100300b44197SJan Kara unsigned int *commit_max_age, 100400b44197SJan Kara char **qf_names, 100500b44197SJan Kara unsigned int *qfmt) 10061da177e4SLinus Torvalds { 10071da177e4SLinus Torvalds int c; 10081da177e4SLinus Torvalds char *arg = NULL; 10091da177e4SLinus Torvalds char *pos; 10101da177e4SLinus Torvalds opt_desc_t opts[] = { 10111da177e4SLinus Torvalds /* Compatibility stuff, so that -o notail for old setups still work */ 10121da177e4SLinus Torvalds {"tails",.arg_required = 't',.values = tails}, 1013bd4c625cSLinus Torvalds {"notail",.clrmask = 1014bd4c625cSLinus Torvalds (1 << REISERFS_LARGETAIL) | (1 << REISERFS_SMALLTAIL)}, 10151da177e4SLinus Torvalds {"conv",.setmask = 1 << REISERFS_CONVERT}, 10161da177e4SLinus Torvalds {"attrs",.setmask = 1 << REISERFS_ATTRS}, 10171da177e4SLinus Torvalds {"noattrs",.clrmask = 1 << REISERFS_ATTRS}, 101873422811SJeff Mahoney {"expose_privroot", .setmask = 1 << REISERFS_EXPOSE_PRIVROOT}, 10191da177e4SLinus Torvalds #ifdef CONFIG_REISERFS_FS_XATTR 10201da177e4SLinus Torvalds {"user_xattr",.setmask = 1 << REISERFS_XATTRS_USER}, 10211da177e4SLinus Torvalds {"nouser_xattr",.clrmask = 1 << REISERFS_XATTRS_USER}, 10221da177e4SLinus Torvalds #else 10231da177e4SLinus Torvalds {"user_xattr",.setmask = 1 << REISERFS_UNSUPPORTED_OPT}, 10241da177e4SLinus Torvalds {"nouser_xattr",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT}, 10251da177e4SLinus Torvalds #endif 10261da177e4SLinus Torvalds #ifdef CONFIG_REISERFS_FS_POSIX_ACL 10271da177e4SLinus Torvalds {"acl",.setmask = 1 << REISERFS_POSIXACL}, 10281da177e4SLinus Torvalds {"noacl",.clrmask = 1 << REISERFS_POSIXACL}, 10291da177e4SLinus Torvalds #else 10301da177e4SLinus Torvalds {"acl",.setmask = 1 << REISERFS_UNSUPPORTED_OPT}, 10311da177e4SLinus Torvalds {"noacl",.clrmask = 1 << REISERFS_UNSUPPORTED_OPT}, 10321da177e4SLinus Torvalds #endif 1033cd02b966SVladimir V. Saveliev {.option_name = "nolog"}, 10341da177e4SLinus Torvalds {"replayonly",.setmask = 1 << REPLAYONLY}, 10351da177e4SLinus Torvalds {"block-allocator",.arg_required = 'a',.values = balloc}, 10361da177e4SLinus Torvalds {"data",.arg_required = 'd',.values = logging_mode}, 10371da177e4SLinus Torvalds {"barrier",.arg_required = 'b',.values = barrier_mode}, 10381da177e4SLinus Torvalds {"resize",.arg_required = 'r',.values = NULL}, 10391da177e4SLinus Torvalds {"jdev",.arg_required = 'j',.values = NULL}, 10401da177e4SLinus Torvalds {"nolargeio",.arg_required = 'w',.values = NULL}, 10411da177e4SLinus Torvalds {"commit",.arg_required = 'c',.values = NULL}, 1042c3aa0776SJan Kara {"usrquota",.setmask = 1 << REISERFS_USRQUOTA}, 1043c3aa0776SJan Kara {"grpquota",.setmask = 1 << REISERFS_GRPQUOTA}, 1044c3aa0776SJan Kara {"noquota",.clrmask = 1 << REISERFS_USRQUOTA | 1 << REISERFS_GRPQUOTA}, 10451da177e4SLinus Torvalds {"errors",.arg_required = 'e',.values = error_actions}, 1046bd4c625cSLinus Torvalds {"usrjquota",.arg_required = 1047bd4c625cSLinus Torvalds 'u' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL}, 1048bd4c625cSLinus Torvalds {"grpjquota",.arg_required = 1049bd4c625cSLinus Torvalds 'g' | (1 << REISERFS_OPT_ALLOWEMPTY),.values = NULL}, 10501da177e4SLinus Torvalds {"jqfmt",.arg_required = 'f',.values = NULL}, 1051cd02b966SVladimir V. Saveliev {.option_name = NULL} 10521da177e4SLinus Torvalds }; 10531da177e4SLinus Torvalds 10541da177e4SLinus Torvalds *blocks = 0; 10551da177e4SLinus Torvalds if (!options || !*options) 10561da177e4SLinus Torvalds /* use default configuration: create tails, journaling on, no 10571da177e4SLinus Torvalds conversion to newest format */ 10581da177e4SLinus Torvalds return 1; 10591da177e4SLinus Torvalds 10601da177e4SLinus Torvalds for (pos = options; pos;) { 10611da177e4SLinus Torvalds c = reiserfs_getopt(s, &pos, opts, &arg, mount_options); 10621da177e4SLinus Torvalds if (c == -1) 10631da177e4SLinus Torvalds /* wrong option is given */ 10641da177e4SLinus Torvalds return 0; 10651da177e4SLinus Torvalds 10661da177e4SLinus Torvalds if (c == 'r') { 10671da177e4SLinus Torvalds char *p; 10681da177e4SLinus Torvalds 10691da177e4SLinus Torvalds p = NULL; 10709a3bb301SPaolo 'Blaisorblade' Giarrusso /* "resize=NNN" or "resize=auto" */ 10719a3bb301SPaolo 'Blaisorblade' Giarrusso 10729a3bb301SPaolo 'Blaisorblade' Giarrusso if (!strcmp(arg, "auto")) { 10739a3bb301SPaolo 'Blaisorblade' Giarrusso /* From JFS code, to auto-get the size. */ 1074bd4c625cSLinus Torvalds *blocks = 1075bd4c625cSLinus Torvalds s->s_bdev->bd_inode->i_size >> s-> 1076bd4c625cSLinus Torvalds s_blocksize_bits; 10779a3bb301SPaolo 'Blaisorblade' Giarrusso } else { 10781da177e4SLinus Torvalds *blocks = simple_strtoul(arg, &p, 0); 10791da177e4SLinus Torvalds if (*p != '\0') { 10801da177e4SLinus Torvalds /* NNN does not look like a number */ 108145b03d5eSJeff Mahoney reiserfs_warning(s, "super-6507", 108245b03d5eSJeff Mahoney "bad value %s for " 108345b03d5eSJeff Mahoney "-oresize\n", arg); 10841da177e4SLinus Torvalds return 0; 10851da177e4SLinus Torvalds } 10861da177e4SLinus Torvalds } 10879a3bb301SPaolo 'Blaisorblade' Giarrusso } 10881da177e4SLinus Torvalds 10891da177e4SLinus Torvalds if (c == 'c') { 10901da177e4SLinus Torvalds char *p = NULL; 10911da177e4SLinus Torvalds unsigned long val = simple_strtoul(arg, &p, 0); 10921da177e4SLinus Torvalds /* commit=NNN (time in seconds) */ 10931da177e4SLinus Torvalds if (*p != '\0' || val >= (unsigned int)-1) { 109445b03d5eSJeff Mahoney reiserfs_warning(s, "super-6508", 109545b03d5eSJeff Mahoney "bad value %s for -ocommit\n", 1096bd4c625cSLinus Torvalds arg); 10979a3bb301SPaolo 'Blaisorblade' Giarrusso return 0; 10981da177e4SLinus Torvalds } 10991da177e4SLinus Torvalds *commit_max_age = (unsigned int)val; 11001da177e4SLinus Torvalds } 11011da177e4SLinus Torvalds 11021da177e4SLinus Torvalds if (c == 'w') { 110345b03d5eSJeff Mahoney reiserfs_warning(s, "super-6509", "nolargeio option " 110445b03d5eSJeff Mahoney "is no longer supported"); 11051da177e4SLinus Torvalds return 0; 11061da177e4SLinus Torvalds } 11071da177e4SLinus Torvalds 11081da177e4SLinus Torvalds if (c == 'j') { 11091da177e4SLinus Torvalds if (arg && *arg && jdev_name) { 11101da177e4SLinus Torvalds if (*jdev_name) { //Hm, already assigned? 111145b03d5eSJeff Mahoney reiserfs_warning(s, "super-6510", 111245b03d5eSJeff Mahoney "journal device was " 111345b03d5eSJeff Mahoney "already specified to " 111445b03d5eSJeff Mahoney "be %s", *jdev_name); 11151da177e4SLinus Torvalds return 0; 11161da177e4SLinus Torvalds } 11171da177e4SLinus Torvalds *jdev_name = arg; 11181da177e4SLinus Torvalds } 11191da177e4SLinus Torvalds } 11201da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 11211da177e4SLinus Torvalds if (c == 'u' || c == 'g') { 11221da177e4SLinus Torvalds int qtype = c == 'u' ? USRQUOTA : GRPQUOTA; 11231da177e4SLinus Torvalds 11246929f891SJan Kara if (sb_any_quota_loaded(s) && 112500b44197SJan Kara (!*arg != !REISERFS_SB(s)->s_qf_names[qtype])) { 112645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6511", 112745b03d5eSJeff Mahoney "cannot change journaled " 112845b03d5eSJeff Mahoney "quota options when quota " 112945b03d5eSJeff Mahoney "turned on."); 11301da177e4SLinus Torvalds return 0; 11311da177e4SLinus Torvalds } 11321da177e4SLinus Torvalds if (*arg) { /* Some filename specified? */ 1133bd4c625cSLinus Torvalds if (REISERFS_SB(s)->s_qf_names[qtype] 1134bd4c625cSLinus Torvalds && strcmp(REISERFS_SB(s)->s_qf_names[qtype], 1135bd4c625cSLinus Torvalds arg)) { 113645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6512", 113745b03d5eSJeff Mahoney "%s quota file " 113845b03d5eSJeff Mahoney "already specified.", 1139bd4c625cSLinus Torvalds QTYPE2NAME(qtype)); 11401da177e4SLinus Torvalds return 0; 11411da177e4SLinus Torvalds } 11421da177e4SLinus Torvalds if (strchr(arg, '/')) { 114345b03d5eSJeff Mahoney reiserfs_warning(s, "super-6513", 114445b03d5eSJeff Mahoney "quotafile must be " 114545b03d5eSJeff Mahoney "on filesystem root."); 11461da177e4SLinus Torvalds return 0; 11471da177e4SLinus Torvalds } 114800b44197SJan Kara qf_names[qtype] = 1149bd4c625cSLinus Torvalds kmalloc(strlen(arg) + 1, GFP_KERNEL); 115000b44197SJan Kara if (!qf_names[qtype]) { 115145b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2502", 115245b03d5eSJeff Mahoney "not enough memory " 115345b03d5eSJeff Mahoney "for storing " 115445b03d5eSJeff Mahoney "quotafile name."); 11551da177e4SLinus Torvalds return 0; 11561da177e4SLinus Torvalds } 115700b44197SJan Kara strcpy(qf_names[qtype], arg); 1158c3aa0776SJan Kara if (qtype == USRQUOTA) 1159c3aa0776SJan Kara *mount_options |= 1 << REISERFS_USRQUOTA; 1160c3aa0776SJan Kara else 1161c3aa0776SJan Kara *mount_options |= 1 << REISERFS_GRPQUOTA; 1162bd4c625cSLinus Torvalds } else { 116300b44197SJan Kara if (qf_names[qtype] != 116400b44197SJan Kara REISERFS_SB(s)->s_qf_names[qtype]) 116500b44197SJan Kara kfree(qf_names[qtype]); 116600b44197SJan Kara qf_names[qtype] = NULL; 1167c3aa0776SJan Kara if (qtype == USRQUOTA) 1168c3aa0776SJan Kara *mount_options &= ~(1 << REISERFS_USRQUOTA); 1169c3aa0776SJan Kara else 1170c3aa0776SJan Kara *mount_options &= ~(1 << REISERFS_GRPQUOTA); 11711da177e4SLinus Torvalds } 11721da177e4SLinus Torvalds } 11731da177e4SLinus Torvalds if (c == 'f') { 11741da177e4SLinus Torvalds if (!strcmp(arg, "vfsold")) 117500b44197SJan Kara *qfmt = QFMT_VFS_OLD; 11761da177e4SLinus Torvalds else if (!strcmp(arg, "vfsv0")) 117700b44197SJan Kara *qfmt = QFMT_VFS_V0; 11781da177e4SLinus Torvalds else { 117945b03d5eSJeff Mahoney reiserfs_warning(s, "super-6514", 118045b03d5eSJeff Mahoney "unknown quota format " 118145b03d5eSJeff Mahoney "specified."); 11821da177e4SLinus Torvalds return 0; 11831da177e4SLinus Torvalds } 11846929f891SJan Kara if (sb_any_quota_loaded(s) && 118500b44197SJan Kara *qfmt != REISERFS_SB(s)->s_jquota_fmt) { 118645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6515", 118745b03d5eSJeff Mahoney "cannot change journaled " 118845b03d5eSJeff Mahoney "quota options when quota " 118945b03d5eSJeff Mahoney "turned on."); 119000b44197SJan Kara return 0; 119100b44197SJan Kara } 11921da177e4SLinus Torvalds } 11931da177e4SLinus Torvalds #else 11941da177e4SLinus Torvalds if (c == 'u' || c == 'g' || c == 'f') { 119545b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2503", "journaled " 119645b03d5eSJeff Mahoney "quota options not supported."); 11971da177e4SLinus Torvalds return 0; 11981da177e4SLinus Torvalds } 11991da177e4SLinus Torvalds #endif 12001da177e4SLinus Torvalds } 12011da177e4SLinus Torvalds 12021da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 120300b44197SJan Kara if (!REISERFS_SB(s)->s_jquota_fmt && !*qfmt 120400b44197SJan Kara && (qf_names[USRQUOTA] || qf_names[GRPQUOTA])) { 120545b03d5eSJeff Mahoney reiserfs_warning(s, "super-6515", 120645b03d5eSJeff Mahoney "journaled quota format not specified."); 12071da177e4SLinus Torvalds return 0; 12081da177e4SLinus Torvalds } 1209c3aa0776SJan Kara if ((!(*mount_options & (1 << REISERFS_USRQUOTA)) && 1210c3aa0776SJan Kara sb_has_quota_loaded(s, USRQUOTA)) || 1211c3aa0776SJan Kara (!(*mount_options & (1 << REISERFS_GRPQUOTA)) && 1212c3aa0776SJan Kara sb_has_quota_loaded(s, GRPQUOTA))) { 121345b03d5eSJeff Mahoney reiserfs_warning(s, "super-6516", "quota options must " 121445b03d5eSJeff Mahoney "be present when quota is turned on."); 1215556a2a45SJan Kara return 0; 1216556a2a45SJan Kara } 12171da177e4SLinus Torvalds #endif 1218556a2a45SJan Kara 12191da177e4SLinus Torvalds return 1; 12201da177e4SLinus Torvalds } 12211da177e4SLinus Torvalds 1222bd4c625cSLinus Torvalds static void switch_data_mode(struct super_block *s, unsigned long mode) 1223bd4c625cSLinus Torvalds { 12241da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt &= ~((1 << REISERFS_DATA_LOG) | 12251da177e4SLinus Torvalds (1 << REISERFS_DATA_ORDERED) | 12261da177e4SLinus Torvalds (1 << REISERFS_DATA_WRITEBACK)); 12271da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt |= (1 << mode); 12281da177e4SLinus Torvalds } 12291da177e4SLinus Torvalds 12301da177e4SLinus Torvalds static void handle_data_mode(struct super_block *s, unsigned long mount_options) 12311da177e4SLinus Torvalds { 12321da177e4SLinus Torvalds if (mount_options & (1 << REISERFS_DATA_LOG)) { 12331da177e4SLinus Torvalds if (!reiserfs_data_log(s)) { 12341da177e4SLinus Torvalds switch_data_mode(s, REISERFS_DATA_LOG); 12351da177e4SLinus Torvalds reiserfs_info(s, "switching to journaled data mode\n"); 12361da177e4SLinus Torvalds } 12371da177e4SLinus Torvalds } else if (mount_options & (1 << REISERFS_DATA_ORDERED)) { 12381da177e4SLinus Torvalds if (!reiserfs_data_ordered(s)) { 12391da177e4SLinus Torvalds switch_data_mode(s, REISERFS_DATA_ORDERED); 12401da177e4SLinus Torvalds reiserfs_info(s, "switching to ordered data mode\n"); 12411da177e4SLinus Torvalds } 12421da177e4SLinus Torvalds } else if (mount_options & (1 << REISERFS_DATA_WRITEBACK)) { 12431da177e4SLinus Torvalds if (!reiserfs_data_writeback(s)) { 12441da177e4SLinus Torvalds switch_data_mode(s, REISERFS_DATA_WRITEBACK); 12451da177e4SLinus Torvalds reiserfs_info(s, "switching to writeback data mode\n"); 12461da177e4SLinus Torvalds } 12471da177e4SLinus Torvalds } 12481da177e4SLinus Torvalds } 12491da177e4SLinus Torvalds 1250bd4c625cSLinus Torvalds static void handle_barrier_mode(struct super_block *s, unsigned long bits) 1251bd4c625cSLinus Torvalds { 12521da177e4SLinus Torvalds int flush = (1 << REISERFS_BARRIER_FLUSH); 12531da177e4SLinus Torvalds int none = (1 << REISERFS_BARRIER_NONE); 12541da177e4SLinus Torvalds int all_barrier = flush | none; 12551da177e4SLinus Torvalds 12561da177e4SLinus Torvalds if (bits & all_barrier) { 12571da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt &= ~all_barrier; 12581da177e4SLinus Torvalds if (bits & flush) { 12591da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt |= flush; 12601da177e4SLinus Torvalds printk("reiserfs: enabling write barrier flush mode\n"); 12611da177e4SLinus Torvalds } else if (bits & none) { 12621da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt |= none; 12631da177e4SLinus Torvalds printk("reiserfs: write barriers turned off\n"); 12641da177e4SLinus Torvalds } 12651da177e4SLinus Torvalds } 12661da177e4SLinus Torvalds } 12671da177e4SLinus Torvalds 12681da177e4SLinus Torvalds static void handle_attrs(struct super_block *s) 12691da177e4SLinus Torvalds { 1270c60e81eeSAndrew Morton struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(s); 12711da177e4SLinus Torvalds 12721da177e4SLinus Torvalds if (reiserfs_attrs(s)) { 12731da177e4SLinus Torvalds if (old_format_only(s)) { 127445b03d5eSJeff Mahoney reiserfs_warning(s, "super-6517", "cannot support " 127545b03d5eSJeff Mahoney "attributes on 3.5.x disk format"); 12761da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS); 12771da177e4SLinus Torvalds return; 12781da177e4SLinus Torvalds } 12791da177e4SLinus Torvalds if (!(le32_to_cpu(rs->s_flags) & reiserfs_attrs_cleared)) { 128045b03d5eSJeff Mahoney reiserfs_warning(s, "super-6518", "cannot support " 128145b03d5eSJeff Mahoney "attributes until flag is set in " 128245b03d5eSJeff Mahoney "super-block"); 12831da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_opt &= ~(1 << REISERFS_ATTRS); 12841da177e4SLinus Torvalds } 12851da177e4SLinus Torvalds } 12861da177e4SLinus Torvalds } 12871da177e4SLinus Torvalds 128800b44197SJan Kara #ifdef CONFIG_QUOTA 128900b44197SJan Kara static void handle_quota_files(struct super_block *s, char **qf_names, 129000b44197SJan Kara unsigned int *qfmt) 129100b44197SJan Kara { 129200b44197SJan Kara int i; 129300b44197SJan Kara 129400b44197SJan Kara for (i = 0; i < MAXQUOTAS; i++) { 129500b44197SJan Kara if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) 129600b44197SJan Kara kfree(REISERFS_SB(s)->s_qf_names[i]); 129700b44197SJan Kara REISERFS_SB(s)->s_qf_names[i] = qf_names[i]; 129800b44197SJan Kara } 1299a06d789bSJan Kara if (*qfmt) 130000b44197SJan Kara REISERFS_SB(s)->s_jquota_fmt = *qfmt; 130100b44197SJan Kara } 130200b44197SJan Kara #endif 130300b44197SJan Kara 13041da177e4SLinus Torvalds static int reiserfs_remount(struct super_block *s, int *mount_flags, char *arg) 13051da177e4SLinus Torvalds { 13061da177e4SLinus Torvalds struct reiserfs_super_block *rs; 13071da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 13081da177e4SLinus Torvalds unsigned long blocks; 13091da177e4SLinus Torvalds unsigned long mount_options = REISERFS_SB(s)->s_mount_opt; 13101da177e4SLinus Torvalds unsigned long safe_mask = 0; 13111da177e4SLinus Torvalds unsigned int commit_max_age = (unsigned int)-1; 13121da177e4SLinus Torvalds struct reiserfs_journal *journal = SB_JOURNAL(s); 1313cdf6ccc8SMiklos Szeredi char *new_opts = kstrdup(arg, GFP_KERNEL); 13141da177e4SLinus Torvalds int err; 131500b44197SJan Kara char *qf_names[MAXQUOTAS]; 131600b44197SJan Kara unsigned int qfmt = 0; 13171da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 13181da177e4SLinus Torvalds int i; 13198ebc4232SFrederic Weisbecker #endif 132000b44197SJan Kara 13218ebc4232SFrederic Weisbecker reiserfs_write_lock(s); 13228ebc4232SFrederic Weisbecker 13238ebc4232SFrederic Weisbecker #ifdef CONFIG_QUOTA 132400b44197SJan Kara memcpy(qf_names, REISERFS_SB(s)->s_qf_names, sizeof(qf_names)); 13251da177e4SLinus Torvalds #endif 13261da177e4SLinus Torvalds 13271da177e4SLinus Torvalds rs = SB_DISK_SUPER_BLOCK(s); 13281da177e4SLinus Torvalds 1329bd4c625cSLinus Torvalds if (!reiserfs_parse_options 133000b44197SJan Kara (s, arg, &mount_options, &blocks, NULL, &commit_max_age, 133100b44197SJan Kara qf_names, &qfmt)) { 13321da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 133300b44197SJan Kara for (i = 0; i < MAXQUOTAS; i++) 133400b44197SJan Kara if (qf_names[i] != REISERFS_SB(s)->s_qf_names[i]) 133500b44197SJan Kara kfree(qf_names[i]); 13361da177e4SLinus Torvalds #endif 1337cdf6ccc8SMiklos Szeredi err = -EINVAL; 13383bb3e1fcSJan Kara goto out_unlock; 13391da177e4SLinus Torvalds } 134000b44197SJan Kara #ifdef CONFIG_QUOTA 134100b44197SJan Kara handle_quota_files(s, qf_names, &qfmt); 134200b44197SJan Kara #endif 13431da177e4SLinus Torvalds 13441da177e4SLinus Torvalds handle_attrs(s); 13451da177e4SLinus Torvalds 13461da177e4SLinus Torvalds /* Add options that are safe here */ 13471da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_SMALLTAIL; 13481da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_LARGETAIL; 13491da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_NO_BORDER; 13501da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_NO_UNHASHED_RELOCATION; 13511da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_HASHED_RELOCATION; 13521da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_TEST4; 13531da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_ATTRS; 13541da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_XATTRS_USER; 13551da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_POSIXACL; 13561da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_BARRIER_FLUSH; 13571da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_BARRIER_NONE; 13581da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_ERROR_RO; 13591da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_ERROR_CONTINUE; 13601da177e4SLinus Torvalds safe_mask |= 1 << REISERFS_ERROR_PANIC; 1361c3aa0776SJan Kara safe_mask |= 1 << REISERFS_USRQUOTA; 1362c3aa0776SJan Kara safe_mask |= 1 << REISERFS_GRPQUOTA; 13631da177e4SLinus Torvalds 13641da177e4SLinus Torvalds /* Update the bitmask, taking care to keep 13651da177e4SLinus Torvalds * the bits we're not allowed to change here */ 1366bd4c625cSLinus Torvalds REISERFS_SB(s)->s_mount_opt = 1367bd4c625cSLinus Torvalds (REISERFS_SB(s)-> 1368bd4c625cSLinus Torvalds s_mount_opt & ~safe_mask) | (mount_options & safe_mask); 13691da177e4SLinus Torvalds 13701da177e4SLinus Torvalds if (commit_max_age != 0 && commit_max_age != (unsigned int)-1) { 13711da177e4SLinus Torvalds journal->j_max_commit_age = commit_max_age; 13721da177e4SLinus Torvalds journal->j_max_trans_age = commit_max_age; 1373bd4c625cSLinus Torvalds } else if (commit_max_age == 0) { 13741da177e4SLinus Torvalds /* 0 means restore defaults. */ 13751da177e4SLinus Torvalds journal->j_max_commit_age = journal->j_default_max_commit_age; 13761da177e4SLinus Torvalds journal->j_max_trans_age = JOURNAL_MAX_TRANS_AGE; 13771da177e4SLinus Torvalds } 13781da177e4SLinus Torvalds 13791da177e4SLinus Torvalds if (blocks) { 1380cdf6ccc8SMiklos Szeredi err = reiserfs_resize(s, blocks); 1381cdf6ccc8SMiklos Szeredi if (err != 0) 13823bb3e1fcSJan Kara goto out_unlock; 13831da177e4SLinus Torvalds } 13841da177e4SLinus Torvalds 13851da177e4SLinus Torvalds if (*mount_flags & MS_RDONLY) { 13861da177e4SLinus Torvalds reiserfs_xattr_init(s, *mount_flags); 13871da177e4SLinus Torvalds /* remount read-only */ 13881da177e4SLinus Torvalds if (s->s_flags & MS_RDONLY) 13891da177e4SLinus Torvalds /* it is read-only already */ 1390cdf6ccc8SMiklos Szeredi goto out_ok; 1391c79d967dSChristoph Hellwig 13923bb3e1fcSJan Kara /* 13933bb3e1fcSJan Kara * Drop write lock. Quota will retake it when needed and lock 13943bb3e1fcSJan Kara * ordering requires calling dquot_suspend() without it. 13953bb3e1fcSJan Kara */ 13963bb3e1fcSJan Kara reiserfs_write_unlock(s); 13970f0dd62fSChristoph Hellwig err = dquot_suspend(s, -1); 13980f0dd62fSChristoph Hellwig if (err < 0) 1399c79d967dSChristoph Hellwig goto out_err; 14003bb3e1fcSJan Kara reiserfs_write_lock(s); 1401c79d967dSChristoph Hellwig 14021da177e4SLinus Torvalds /* try to remount file system with read-only permissions */ 1403bd4c625cSLinus Torvalds if (sb_umount_state(rs) == REISERFS_VALID_FS 1404bd4c625cSLinus Torvalds || REISERFS_SB(s)->s_mount_state != REISERFS_VALID_FS) { 1405cdf6ccc8SMiklos Szeredi goto out_ok; 14061da177e4SLinus Torvalds } 14071da177e4SLinus Torvalds 14081da177e4SLinus Torvalds err = journal_begin(&th, s, 10); 14091da177e4SLinus Torvalds if (err) 14103bb3e1fcSJan Kara goto out_unlock; 14111da177e4SLinus Torvalds 14121da177e4SLinus Torvalds /* Mounting a rw partition read-only. */ 14131da177e4SLinus Torvalds reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 14141da177e4SLinus Torvalds set_sb_umount_state(rs, REISERFS_SB(s)->s_mount_state); 14151da177e4SLinus Torvalds journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); 14161da177e4SLinus Torvalds } else { 14171da177e4SLinus Torvalds /* remount read-write */ 14181da177e4SLinus Torvalds if (!(s->s_flags & MS_RDONLY)) { 14191da177e4SLinus Torvalds reiserfs_xattr_init(s, *mount_flags); 1420cdf6ccc8SMiklos Szeredi goto out_ok; /* We are read-write already */ 14211da177e4SLinus Torvalds } 14221da177e4SLinus Torvalds 1423cdf6ccc8SMiklos Szeredi if (reiserfs_is_journal_aborted(journal)) { 1424cdf6ccc8SMiklos Szeredi err = journal->j_errno; 14253bb3e1fcSJan Kara goto out_unlock; 1426cdf6ccc8SMiklos Szeredi } 14271da177e4SLinus Torvalds 14281da177e4SLinus Torvalds handle_data_mode(s, mount_options); 14291da177e4SLinus Torvalds handle_barrier_mode(s, mount_options); 14301da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_state = sb_umount_state(rs); 14311da177e4SLinus Torvalds s->s_flags &= ~MS_RDONLY; /* now it is safe to call journal_begin */ 14321da177e4SLinus Torvalds err = journal_begin(&th, s, 10); 14331da177e4SLinus Torvalds if (err) 14343bb3e1fcSJan Kara goto out_unlock; 14351da177e4SLinus Torvalds 14361da177e4SLinus Torvalds /* Mount a partition which is read-only, read-write */ 14371da177e4SLinus Torvalds reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 14381da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_state = sb_umount_state(rs); 14391da177e4SLinus Torvalds s->s_flags &= ~MS_RDONLY; 14401da177e4SLinus Torvalds set_sb_umount_state(rs, REISERFS_ERROR_FS); 1441702d21c6SJeff Mahoney if (!old_format_only(s)) 1442702d21c6SJeff Mahoney set_sb_mnt_count(rs, sb_mnt_count(rs) + 1); 14431da177e4SLinus Torvalds /* mark_buffer_dirty (SB_BUFFER_WITH_SB (s), 1); */ 14441da177e4SLinus Torvalds journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); 14451da177e4SLinus Torvalds REISERFS_SB(s)->s_mount_state = REISERFS_VALID_FS; 14461da177e4SLinus Torvalds } 14471da177e4SLinus Torvalds /* this will force a full flush of all journal lists */ 14481da177e4SLinus Torvalds SB_JOURNAL(s)->j_must_wait = 1; 14491da177e4SLinus Torvalds err = journal_end(&th, s, 10); 14501da177e4SLinus Torvalds if (err) 14513bb3e1fcSJan Kara goto out_unlock; 14521da177e4SLinus Torvalds 14531da177e4SLinus Torvalds if (!(*mount_flags & MS_RDONLY)) { 14543bb3e1fcSJan Kara /* 14553bb3e1fcSJan Kara * Drop write lock. Quota will retake it when needed and lock 14563bb3e1fcSJan Kara * ordering requires calling dquot_resume() without it. 14573bb3e1fcSJan Kara */ 14583bb3e1fcSJan Kara reiserfs_write_unlock(s); 14590f0dd62fSChristoph Hellwig dquot_resume(s, -1); 14603bb3e1fcSJan Kara reiserfs_write_lock(s); 14611da177e4SLinus Torvalds finish_unfinished(s); 14621da177e4SLinus Torvalds reiserfs_xattr_init(s, *mount_flags); 14631da177e4SLinus Torvalds } 14641da177e4SLinus Torvalds 1465cdf6ccc8SMiklos Szeredi out_ok: 14662a32cebdSAl Viro replace_mount_options(s, new_opts); 14678ebc4232SFrederic Weisbecker reiserfs_write_unlock(s); 14681da177e4SLinus Torvalds return 0; 1469cdf6ccc8SMiklos Szeredi 14703bb3e1fcSJan Kara out_unlock: 14713bb3e1fcSJan Kara reiserfs_write_unlock(s); 1472cdf6ccc8SMiklos Szeredi out_err: 1473cdf6ccc8SMiklos Szeredi kfree(new_opts); 1474cdf6ccc8SMiklos Szeredi return err; 14751da177e4SLinus Torvalds } 14761da177e4SLinus Torvalds 14771da177e4SLinus Torvalds static int read_super_block(struct super_block *s, int offset) 14781da177e4SLinus Torvalds { 14791da177e4SLinus Torvalds struct buffer_head *bh; 14801da177e4SLinus Torvalds struct reiserfs_super_block *rs; 14811da177e4SLinus Torvalds int fs_blocksize; 14821da177e4SLinus Torvalds 14831da177e4SLinus Torvalds bh = sb_bread(s, offset / s->s_blocksize); 14841da177e4SLinus Torvalds if (!bh) { 148545b03d5eSJeff Mahoney reiserfs_warning(s, "sh-2006", 14861da177e4SLinus Torvalds "bread failed (dev %s, block %lu, size %lu)", 1487bd4c625cSLinus Torvalds reiserfs_bdevname(s), offset / s->s_blocksize, 1488bd4c625cSLinus Torvalds s->s_blocksize); 14891da177e4SLinus Torvalds return 1; 14901da177e4SLinus Torvalds } 14911da177e4SLinus Torvalds 14921da177e4SLinus Torvalds rs = (struct reiserfs_super_block *)bh->b_data; 14931da177e4SLinus Torvalds if (!is_any_reiserfs_magic_string(rs)) { 14941da177e4SLinus Torvalds brelse(bh); 14951da177e4SLinus Torvalds return 1; 14961da177e4SLinus Torvalds } 14971da177e4SLinus Torvalds // 14981da177e4SLinus Torvalds // ok, reiserfs signature (old or new) found in at the given offset 14991da177e4SLinus Torvalds // 15001da177e4SLinus Torvalds fs_blocksize = sb_blocksize(rs); 15011da177e4SLinus Torvalds brelse(bh); 15021da177e4SLinus Torvalds sb_set_blocksize(s, fs_blocksize); 15031da177e4SLinus Torvalds 15041da177e4SLinus Torvalds bh = sb_bread(s, offset / s->s_blocksize); 15051da177e4SLinus Torvalds if (!bh) { 150645b03d5eSJeff Mahoney reiserfs_warning(s, "sh-2007", 150745b03d5eSJeff Mahoney "bread failed (dev %s, block %lu, size %lu)", 1508bd4c625cSLinus Torvalds reiserfs_bdevname(s), offset / s->s_blocksize, 1509bd4c625cSLinus Torvalds s->s_blocksize); 15101da177e4SLinus Torvalds return 1; 15111da177e4SLinus Torvalds } 15121da177e4SLinus Torvalds 15131da177e4SLinus Torvalds rs = (struct reiserfs_super_block *)bh->b_data; 15141da177e4SLinus Torvalds if (sb_blocksize(rs) != s->s_blocksize) { 151545b03d5eSJeff Mahoney reiserfs_warning(s, "sh-2011", "can't find a reiserfs " 151645b03d5eSJeff Mahoney "filesystem on (dev %s, block %Lu, size %lu)", 1517bd4c625cSLinus Torvalds reiserfs_bdevname(s), 1518bd4c625cSLinus Torvalds (unsigned long long)bh->b_blocknr, 1519bd4c625cSLinus Torvalds s->s_blocksize); 15201da177e4SLinus Torvalds brelse(bh); 15211da177e4SLinus Torvalds return 1; 15221da177e4SLinus Torvalds } 15231da177e4SLinus Torvalds 15243e8962beSAl Viro if (rs->s_v1.s_root_block == cpu_to_le32(-1)) { 15251da177e4SLinus Torvalds brelse(bh); 152645b03d5eSJeff Mahoney reiserfs_warning(s, "super-6519", "Unfinished reiserfsck " 152745b03d5eSJeff Mahoney "--rebuild-tree run detected. Please run\n" 152845b03d5eSJeff Mahoney "reiserfsck --rebuild-tree and wait for a " 152945b03d5eSJeff Mahoney "completion. If that fails\n" 15301da177e4SLinus Torvalds "get newer reiserfsprogs package"); 15311da177e4SLinus Torvalds return 1; 15321da177e4SLinus Torvalds } 15331da177e4SLinus Torvalds 15341da177e4SLinus Torvalds SB_BUFFER_WITH_SB(s) = bh; 15351da177e4SLinus Torvalds SB_DISK_SUPER_BLOCK(s) = rs; 15361da177e4SLinus Torvalds 15371da177e4SLinus Torvalds if (is_reiserfs_jr(rs)) { 15381da177e4SLinus Torvalds /* magic is of non-standard journal filesystem, look at s_version to 15391da177e4SLinus Torvalds find which format is in use */ 15401da177e4SLinus Torvalds if (sb_version(rs) == REISERFS_VERSION_2) 15411d889d99SJeff Mahoney reiserfs_info(s, "found reiserfs format \"3.6\"" 15421d889d99SJeff Mahoney " with non-standard journal\n"); 15431da177e4SLinus Torvalds else if (sb_version(rs) == REISERFS_VERSION_1) 15441d889d99SJeff Mahoney reiserfs_info(s, "found reiserfs format \"3.5\"" 15451d889d99SJeff Mahoney " with non-standard journal\n"); 15461da177e4SLinus Torvalds else { 154745b03d5eSJeff Mahoney reiserfs_warning(s, "sh-2012", "found unknown " 154845b03d5eSJeff Mahoney "format \"%u\" of reiserfs with " 154945b03d5eSJeff Mahoney "non-standard magic", sb_version(rs)); 15501da177e4SLinus Torvalds return 1; 15511da177e4SLinus Torvalds } 1552bd4c625cSLinus Torvalds } else 15531da177e4SLinus Torvalds /* s_version of standard format may contain incorrect information, 15541da177e4SLinus Torvalds so we just look at the magic string */ 1555bd4c625cSLinus Torvalds reiserfs_info(s, 1556bd4c625cSLinus Torvalds "found reiserfs format \"%s\" with standard journal\n", 15571da177e4SLinus Torvalds is_reiserfs_3_5(rs) ? "3.5" : "3.6"); 15581da177e4SLinus Torvalds 15591da177e4SLinus Torvalds s->s_op = &reiserfs_sops; 15601da177e4SLinus Torvalds s->s_export_op = &reiserfs_export_ops; 15611da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 15621da177e4SLinus Torvalds s->s_qcop = &reiserfs_qctl_operations; 15631da177e4SLinus Torvalds s->dq_op = &reiserfs_quota_operations; 15641da177e4SLinus Torvalds #endif 15651da177e4SLinus Torvalds 15661da177e4SLinus Torvalds /* new format is limited by the 32 bit wide i_blocks field, want to 15671da177e4SLinus Torvalds ** be one full block below that. 15681da177e4SLinus Torvalds */ 15691da177e4SLinus Torvalds s->s_maxbytes = (512LL << 32) - s->s_blocksize; 15701da177e4SLinus Torvalds return 0; 15711da177e4SLinus Torvalds } 15721da177e4SLinus Torvalds 15731da177e4SLinus Torvalds /* after journal replay, reread all bitmap and super blocks */ 1574bd4c625cSLinus Torvalds static int reread_meta_blocks(struct super_block *s) 1575bd4c625cSLinus Torvalds { 15761da177e4SLinus Torvalds ll_rw_block(READ, 1, &(SB_BUFFER_WITH_SB(s))); 15771da177e4SLinus Torvalds wait_on_buffer(SB_BUFFER_WITH_SB(s)); 15781da177e4SLinus Torvalds if (!buffer_uptodate(SB_BUFFER_WITH_SB(s))) { 157945b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2504", "error reading the super"); 15801da177e4SLinus Torvalds return 1; 15811da177e4SLinus Torvalds } 15821da177e4SLinus Torvalds 15831da177e4SLinus Torvalds return 0; 15841da177e4SLinus Torvalds } 15851da177e4SLinus Torvalds 15861da177e4SLinus Torvalds ///////////////////////////////////////////////////// 15871da177e4SLinus Torvalds // hash detection stuff 15881da177e4SLinus Torvalds 15891da177e4SLinus Torvalds // if root directory is empty - we set default - Yura's - hash and 15901da177e4SLinus Torvalds // warn about it 15911da177e4SLinus Torvalds // FIXME: we look for only one name in a directory. If tea and yura 15921da177e4SLinus Torvalds // bith have the same value - we ask user to send report to the 15931da177e4SLinus Torvalds // mailing list 15941da177e4SLinus Torvalds static __u32 find_hash_out(struct super_block *s) 15951da177e4SLinus Torvalds { 15961da177e4SLinus Torvalds int retval; 15971da177e4SLinus Torvalds struct inode *inode; 15981da177e4SLinus Torvalds struct cpu_key key; 15991da177e4SLinus Torvalds INITIALIZE_PATH(path); 16001da177e4SLinus Torvalds struct reiserfs_dir_entry de; 16011da177e4SLinus Torvalds __u32 hash = DEFAULT_HASH; 16021da177e4SLinus Torvalds 16031da177e4SLinus Torvalds inode = s->s_root->d_inode; 16041da177e4SLinus Torvalds 16051da177e4SLinus Torvalds do { // Some serious "goto"-hater was there ;) 16061da177e4SLinus Torvalds u32 teahash, r5hash, yurahash; 16071da177e4SLinus Torvalds 16081da177e4SLinus Torvalds make_cpu_key(&key, inode, ~0, TYPE_DIRENTRY, 3); 16091da177e4SLinus Torvalds retval = search_by_entry_key(s, &key, &path, &de); 16101da177e4SLinus Torvalds if (retval == IO_ERROR) { 16111da177e4SLinus Torvalds pathrelse(&path); 16121da177e4SLinus Torvalds return UNSET_HASH; 16131da177e4SLinus Torvalds } 16141da177e4SLinus Torvalds if (retval == NAME_NOT_FOUND) 16151da177e4SLinus Torvalds de.de_entry_num--; 16161da177e4SLinus Torvalds set_de_name_and_namelen(&de); 16171da177e4SLinus Torvalds if (deh_offset(&(de.de_deh[de.de_entry_num])) == DOT_DOT_OFFSET) { 16181da177e4SLinus Torvalds /* allow override in this case */ 16191da177e4SLinus Torvalds if (reiserfs_rupasov_hash(s)) { 16201da177e4SLinus Torvalds hash = YURA_HASH; 16211da177e4SLinus Torvalds } 16221d889d99SJeff Mahoney reiserfs_info(s, "FS seems to be empty, autodetect " 16231d889d99SJeff Mahoney "is using the default hash\n"); 16241da177e4SLinus Torvalds break; 16251da177e4SLinus Torvalds } 16261da177e4SLinus Torvalds r5hash = GET_HASH_VALUE(r5_hash(de.de_name, de.de_namelen)); 16271da177e4SLinus Torvalds teahash = GET_HASH_VALUE(keyed_hash(de.de_name, de.de_namelen)); 16281da177e4SLinus Torvalds yurahash = GET_HASH_VALUE(yura_hash(de.de_name, de.de_namelen)); 1629bd4c625cSLinus Torvalds if (((teahash == r5hash) 1630bd4c625cSLinus Torvalds && 1631bd4c625cSLinus Torvalds (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) 1632bd4c625cSLinus Torvalds == r5hash)) || ((teahash == yurahash) 1633bd4c625cSLinus Torvalds && (yurahash == 1634bd4c625cSLinus Torvalds GET_HASH_VALUE(deh_offset 1635bd4c625cSLinus Torvalds (& 1636bd4c625cSLinus Torvalds (de. 1637bd4c625cSLinus Torvalds de_deh[de. 1638bd4c625cSLinus Torvalds de_entry_num]))))) 1639bd4c625cSLinus Torvalds || ((r5hash == yurahash) 1640bd4c625cSLinus Torvalds && (yurahash == 1641bd4c625cSLinus Torvalds GET_HASH_VALUE(deh_offset 1642bd4c625cSLinus Torvalds (&(de.de_deh[de.de_entry_num])))))) { 164345b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2506", "Unable to " 164445b03d5eSJeff Mahoney "automatically detect hash function. " 164545b03d5eSJeff Mahoney "Please mount with -o " 164645b03d5eSJeff Mahoney "hash={tea,rupasov,r5}"); 16471da177e4SLinus Torvalds hash = UNSET_HASH; 16481da177e4SLinus Torvalds break; 16491da177e4SLinus Torvalds } 1650bd4c625cSLinus Torvalds if (GET_HASH_VALUE(deh_offset(&(de.de_deh[de.de_entry_num]))) == 1651bd4c625cSLinus Torvalds yurahash) 16521da177e4SLinus Torvalds hash = YURA_HASH; 1653bd4c625cSLinus Torvalds else if (GET_HASH_VALUE 1654bd4c625cSLinus Torvalds (deh_offset(&(de.de_deh[de.de_entry_num]))) == teahash) 16551da177e4SLinus Torvalds hash = TEA_HASH; 1656bd4c625cSLinus Torvalds else if (GET_HASH_VALUE 1657bd4c625cSLinus Torvalds (deh_offset(&(de.de_deh[de.de_entry_num]))) == r5hash) 16581da177e4SLinus Torvalds hash = R5_HASH; 16591da177e4SLinus Torvalds else { 166045b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2506", 166145b03d5eSJeff Mahoney "Unrecognised hash function"); 16621da177e4SLinus Torvalds hash = UNSET_HASH; 16631da177e4SLinus Torvalds } 16641da177e4SLinus Torvalds } while (0); 16651da177e4SLinus Torvalds 16661da177e4SLinus Torvalds pathrelse(&path); 16671da177e4SLinus Torvalds return hash; 16681da177e4SLinus Torvalds } 16691da177e4SLinus Torvalds 16701da177e4SLinus Torvalds // finds out which hash names are sorted with 16711da177e4SLinus Torvalds static int what_hash(struct super_block *s) 16721da177e4SLinus Torvalds { 16731da177e4SLinus Torvalds __u32 code; 16741da177e4SLinus Torvalds 16751da177e4SLinus Torvalds code = sb_hash_function_code(SB_DISK_SUPER_BLOCK(s)); 16761da177e4SLinus Torvalds 16771da177e4SLinus Torvalds /* reiserfs_hash_detect() == true if any of the hash mount options 16781da177e4SLinus Torvalds ** were used. We must check them to make sure the user isn't 16791da177e4SLinus Torvalds ** using a bad hash value 16801da177e4SLinus Torvalds */ 16811da177e4SLinus Torvalds if (code == UNSET_HASH || reiserfs_hash_detect(s)) 16821da177e4SLinus Torvalds code = find_hash_out(s); 16831da177e4SLinus Torvalds 16841da177e4SLinus Torvalds if (code != UNSET_HASH && reiserfs_hash_detect(s)) { 16851da177e4SLinus Torvalds /* detection has found the hash, and we must check against the 16861da177e4SLinus Torvalds ** mount options 16871da177e4SLinus Torvalds */ 16881da177e4SLinus Torvalds if (reiserfs_rupasov_hash(s) && code != YURA_HASH) { 168945b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2507", 169045b03d5eSJeff Mahoney "Error, %s hash detected, " 1691bd4c625cSLinus Torvalds "unable to force rupasov hash", 1692bd4c625cSLinus Torvalds reiserfs_hashname(code)); 16931da177e4SLinus Torvalds code = UNSET_HASH; 16941da177e4SLinus Torvalds } else if (reiserfs_tea_hash(s) && code != TEA_HASH) { 169545b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2508", 169645b03d5eSJeff Mahoney "Error, %s hash detected, " 1697bd4c625cSLinus Torvalds "unable to force tea hash", 1698bd4c625cSLinus Torvalds reiserfs_hashname(code)); 16991da177e4SLinus Torvalds code = UNSET_HASH; 17001da177e4SLinus Torvalds } else if (reiserfs_r5_hash(s) && code != R5_HASH) { 170145b03d5eSJeff Mahoney reiserfs_warning(s, "reiserfs-2509", 170245b03d5eSJeff Mahoney "Error, %s hash detected, " 1703bd4c625cSLinus Torvalds "unable to force r5 hash", 1704bd4c625cSLinus Torvalds reiserfs_hashname(code)); 17051da177e4SLinus Torvalds code = UNSET_HASH; 17061da177e4SLinus Torvalds } 17071da177e4SLinus Torvalds } else { 17081da177e4SLinus Torvalds /* find_hash_out was not called or could not determine the hash */ 17091da177e4SLinus Torvalds if (reiserfs_rupasov_hash(s)) { 17101da177e4SLinus Torvalds code = YURA_HASH; 17111da177e4SLinus Torvalds } else if (reiserfs_tea_hash(s)) { 17121da177e4SLinus Torvalds code = TEA_HASH; 17131da177e4SLinus Torvalds } else if (reiserfs_r5_hash(s)) { 17141da177e4SLinus Torvalds code = R5_HASH; 17151da177e4SLinus Torvalds } 17161da177e4SLinus Torvalds } 17171da177e4SLinus Torvalds 17181da177e4SLinus Torvalds /* if we are mounted RW, and we have a new valid hash code, update 17191da177e4SLinus Torvalds ** the super 17201da177e4SLinus Torvalds */ 17211da177e4SLinus Torvalds if (code != UNSET_HASH && 17221da177e4SLinus Torvalds !(s->s_flags & MS_RDONLY) && 17231da177e4SLinus Torvalds code != sb_hash_function_code(SB_DISK_SUPER_BLOCK(s))) { 17241da177e4SLinus Torvalds set_sb_hash_function_code(SB_DISK_SUPER_BLOCK(s), code); 17251da177e4SLinus Torvalds } 17261da177e4SLinus Torvalds return code; 17271da177e4SLinus Torvalds } 17281da177e4SLinus Torvalds 17291da177e4SLinus Torvalds // return pointer to appropriate function 17301da177e4SLinus Torvalds static hashf_t hash_function(struct super_block *s) 17311da177e4SLinus Torvalds { 17321da177e4SLinus Torvalds switch (what_hash(s)) { 17331da177e4SLinus Torvalds case TEA_HASH: 17341da177e4SLinus Torvalds reiserfs_info(s, "Using tea hash to sort names\n"); 17351da177e4SLinus Torvalds return keyed_hash; 17361da177e4SLinus Torvalds case YURA_HASH: 17371da177e4SLinus Torvalds reiserfs_info(s, "Using rupasov hash to sort names\n"); 17381da177e4SLinus Torvalds return yura_hash; 17391da177e4SLinus Torvalds case R5_HASH: 17401da177e4SLinus Torvalds reiserfs_info(s, "Using r5 hash to sort names\n"); 17411da177e4SLinus Torvalds return r5_hash; 17421da177e4SLinus Torvalds } 17431da177e4SLinus Torvalds return NULL; 17441da177e4SLinus Torvalds } 17451da177e4SLinus Torvalds 17461da177e4SLinus Torvalds // this is used to set up correct value for old partitions 17471da177e4SLinus Torvalds static int function2code(hashf_t func) 17481da177e4SLinus Torvalds { 17491da177e4SLinus Torvalds if (func == keyed_hash) 17501da177e4SLinus Torvalds return TEA_HASH; 17511da177e4SLinus Torvalds if (func == yura_hash) 17521da177e4SLinus Torvalds return YURA_HASH; 17531da177e4SLinus Torvalds if (func == r5_hash) 17541da177e4SLinus Torvalds return R5_HASH; 17551da177e4SLinus Torvalds 17561da177e4SLinus Torvalds BUG(); // should never happen 17571da177e4SLinus Torvalds 17581da177e4SLinus Torvalds return 0; 17591da177e4SLinus Torvalds } 17601da177e4SLinus Torvalds 176145b03d5eSJeff Mahoney #define SWARN(silent, s, id, ...) \ 17621da177e4SLinus Torvalds if (!(silent)) \ 176345b03d5eSJeff Mahoney reiserfs_warning(s, id, __VA_ARGS__) 17641da177e4SLinus Torvalds 17651da177e4SLinus Torvalds static int reiserfs_fill_super(struct super_block *s, void *data, int silent) 17661da177e4SLinus Torvalds { 17671da177e4SLinus Torvalds struct inode *root_inode; 17681da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 17691da177e4SLinus Torvalds int old_format = 0; 17701da177e4SLinus Torvalds unsigned long blocks; 17711da177e4SLinus Torvalds unsigned int commit_max_age = 0; 17721da177e4SLinus Torvalds int jinit_done = 0; 17731da177e4SLinus Torvalds struct reiserfs_iget_args args; 17741da177e4SLinus Torvalds struct reiserfs_super_block *rs; 17751da177e4SLinus Torvalds char *jdev_name; 17761da177e4SLinus Torvalds struct reiserfs_sb_info *sbi; 17771da177e4SLinus Torvalds int errval = -EINVAL; 177800b44197SJan Kara char *qf_names[MAXQUOTAS] = {}; 177900b44197SJan Kara unsigned int qfmt = 0; 17801da177e4SLinus Torvalds 1781cdf6ccc8SMiklos Szeredi save_mount_options(s, data); 1782cdf6ccc8SMiklos Szeredi 178301afb213SYan Burman sbi = kzalloc(sizeof(struct reiserfs_sb_info), GFP_KERNEL); 1784b7b7fa43SJeff Mahoney if (!sbi) 1785b7b7fa43SJeff Mahoney return -ENOMEM; 17861da177e4SLinus Torvalds s->s_fs_info = sbi; 17871da177e4SLinus Torvalds /* Set default values for options: non-aggressive tails, RO on errors */ 1788efaa33ebSArtem Bityutskiy sbi->s_mount_opt |= (1 << REISERFS_SMALLTAIL); 1789efaa33ebSArtem Bityutskiy sbi->s_mount_opt |= (1 << REISERFS_ERROR_RO); 1790efaa33ebSArtem Bityutskiy sbi->s_mount_opt |= (1 << REISERFS_BARRIER_FLUSH); 17911da177e4SLinus Torvalds /* no preallocation minimum, be smart in 17921da177e4SLinus Torvalds reiserfs_file_write instead */ 1793efaa33ebSArtem Bityutskiy sbi->s_alloc_options.preallocmin = 0; 17941da177e4SLinus Torvalds /* Preallocate by 16 blocks (17-1) at once */ 1795efaa33ebSArtem Bityutskiy sbi->s_alloc_options.preallocsize = 17; 17961da177e4SLinus Torvalds /* setup default block allocator options */ 17971da177e4SLinus Torvalds reiserfs_init_alloc_options(s); 17981da177e4SLinus Torvalds 1799033369d1SArtem Bityutskiy spin_lock_init(&sbi->old_work_lock); 1800033369d1SArtem Bityutskiy INIT_DELAYED_WORK(&sbi->old_work, flush_old_commits); 1801efaa33ebSArtem Bityutskiy mutex_init(&sbi->lock); 1802efaa33ebSArtem Bityutskiy sbi->lock_depth = -1; 18038ebc4232SFrederic Weisbecker 18041da177e4SLinus Torvalds jdev_name = NULL; 1805bd4c625cSLinus Torvalds if (reiserfs_parse_options 1806bd4c625cSLinus Torvalds (s, (char *)data, &(sbi->s_mount_opt), &blocks, &jdev_name, 180700b44197SJan Kara &commit_max_age, qf_names, &qfmt) == 0) { 1808f32485beSFrederic Weisbecker goto error_unlocked; 18091da177e4SLinus Torvalds } 1810c3aa0776SJan Kara if (jdev_name && jdev_name[0]) { 1811efaa33ebSArtem Bityutskiy sbi->s_jdev = kstrdup(jdev_name, GFP_KERNEL); 1812efaa33ebSArtem Bityutskiy if (!sbi->s_jdev) { 1813c3aa0776SJan Kara SWARN(silent, s, "", "Cannot allocate memory for " 1814c3aa0776SJan Kara "journal device name"); 1815c3aa0776SJan Kara goto error; 1816c3aa0776SJan Kara } 1817c3aa0776SJan Kara } 181800b44197SJan Kara #ifdef CONFIG_QUOTA 181900b44197SJan Kara handle_quota_files(s, qf_names, &qfmt); 182000b44197SJan Kara #endif 18211da177e4SLinus Torvalds 18221da177e4SLinus Torvalds if (blocks) { 182345b03d5eSJeff Mahoney SWARN(silent, s, "jmacd-7", "resize option for remount only"); 1824f32485beSFrederic Weisbecker goto error_unlocked; 18251da177e4SLinus Torvalds } 18261da177e4SLinus Torvalds 18271da177e4SLinus Torvalds /* try old format (undistributed bitmap, super block in 8-th 1k block of a device) */ 18281da177e4SLinus Torvalds if (!read_super_block(s, REISERFS_OLD_DISK_OFFSET_IN_BYTES)) 18291da177e4SLinus Torvalds old_format = 1; 18301da177e4SLinus Torvalds /* try new format (64-th 1k block), which can contain reiserfs super block */ 18311da177e4SLinus Torvalds else if (read_super_block(s, REISERFS_DISK_OFFSET_IN_BYTES)) { 183245b03d5eSJeff Mahoney SWARN(silent, s, "sh-2021", "can not find reiserfs on %s", 1833bd4c625cSLinus Torvalds reiserfs_bdevname(s)); 1834f32485beSFrederic Weisbecker goto error_unlocked; 18351da177e4SLinus Torvalds } 18361da177e4SLinus Torvalds 18371da177e4SLinus Torvalds rs = SB_DISK_SUPER_BLOCK(s); 18381da177e4SLinus Torvalds /* Let's do basic sanity check to verify that underlying device is not 18391da177e4SLinus Torvalds smaller than the filesystem. If the check fails then abort and scream, 18401da177e4SLinus Torvalds because bad stuff will happen otherwise. */ 1841bd4c625cSLinus Torvalds if (s->s_bdev && s->s_bdev->bd_inode 1842bd4c625cSLinus Torvalds && i_size_read(s->s_bdev->bd_inode) < 1843bd4c625cSLinus Torvalds sb_block_count(rs) * sb_blocksize(rs)) { 184445b03d5eSJeff Mahoney SWARN(silent, s, "", "Filesystem cannot be " 184545b03d5eSJeff Mahoney "mounted because it is bigger than the device"); 184645b03d5eSJeff Mahoney SWARN(silent, s, "", "You may need to run fsck " 184745b03d5eSJeff Mahoney "or increase size of your LVM partition"); 184845b03d5eSJeff Mahoney SWARN(silent, s, "", "Or may be you forgot to " 184945b03d5eSJeff Mahoney "reboot after fdisk when it told you to"); 1850f32485beSFrederic Weisbecker goto error_unlocked; 18511da177e4SLinus Torvalds } 18521da177e4SLinus Torvalds 18531da177e4SLinus Torvalds sbi->s_mount_state = SB_REISERFS_STATE(s); 18541da177e4SLinus Torvalds sbi->s_mount_state = REISERFS_VALID_FS; 18551da177e4SLinus Torvalds 18566f01046bSJeff Mahoney if ((errval = reiserfs_init_bitmap_cache(s))) { 185745b03d5eSJeff Mahoney SWARN(silent, s, "jmacd-8", "unable to read bitmap"); 1858f32485beSFrederic Weisbecker goto error_unlocked; 18591da177e4SLinus Torvalds } 1860f32485beSFrederic Weisbecker 1861d2c89a42SJeff Mahoney errval = -EINVAL; 18621da177e4SLinus Torvalds #ifdef CONFIG_REISERFS_CHECK 186345b03d5eSJeff Mahoney SWARN(silent, s, "", "CONFIG_REISERFS_CHECK is set ON"); 186445b03d5eSJeff Mahoney SWARN(silent, s, "", "- it is slow mode for debugging."); 18651da177e4SLinus Torvalds #endif 18661da177e4SLinus Torvalds 18671da177e4SLinus Torvalds /* make data=ordered the default */ 18681da177e4SLinus Torvalds if (!reiserfs_data_log(s) && !reiserfs_data_ordered(s) && 1869bd4c625cSLinus Torvalds !reiserfs_data_writeback(s)) { 1870efaa33ebSArtem Bityutskiy sbi->s_mount_opt |= (1 << REISERFS_DATA_ORDERED); 18711da177e4SLinus Torvalds } 18721da177e4SLinus Torvalds 18731da177e4SLinus Torvalds if (reiserfs_data_log(s)) { 18741da177e4SLinus Torvalds reiserfs_info(s, "using journaled data mode\n"); 18751da177e4SLinus Torvalds } else if (reiserfs_data_ordered(s)) { 18761da177e4SLinus Torvalds reiserfs_info(s, "using ordered data mode\n"); 18771da177e4SLinus Torvalds } else { 18781da177e4SLinus Torvalds reiserfs_info(s, "using writeback data mode\n"); 18791da177e4SLinus Torvalds } 18801da177e4SLinus Torvalds if (reiserfs_barrier_flush(s)) { 18811da177e4SLinus Torvalds printk("reiserfs: using flush barriers\n"); 18821da177e4SLinus Torvalds } 1883f32485beSFrederic Weisbecker 188437c69b98SFrederic Weisbecker // set_device_ro(s->s_dev, 1) ; 188537c69b98SFrederic Weisbecker if (journal_init(s, jdev_name, old_format, commit_max_age)) { 188637c69b98SFrederic Weisbecker SWARN(silent, s, "sh-2022", 188737c69b98SFrederic Weisbecker "unable to initialize journal space"); 188837c69b98SFrederic Weisbecker goto error_unlocked; 188937c69b98SFrederic Weisbecker } else { 189037c69b98SFrederic Weisbecker jinit_done = 1; /* once this is set, journal_release must be called 189137c69b98SFrederic Weisbecker ** if we error out of the mount 189237c69b98SFrederic Weisbecker */ 189337c69b98SFrederic Weisbecker } 189437c69b98SFrederic Weisbecker 18951da177e4SLinus Torvalds if (reread_meta_blocks(s)) { 189645b03d5eSJeff Mahoney SWARN(silent, s, "jmacd-9", 189745b03d5eSJeff Mahoney "unable to reread meta blocks after journal init"); 18989b467e6eSFrederic Weisbecker goto error_unlocked; 18991da177e4SLinus Torvalds } 19001da177e4SLinus Torvalds 19011da177e4SLinus Torvalds if (replay_only(s)) 19029b467e6eSFrederic Weisbecker goto error_unlocked; 19031da177e4SLinus Torvalds 19041da177e4SLinus Torvalds if (bdev_read_only(s->s_bdev) && !(s->s_flags & MS_RDONLY)) { 190545b03d5eSJeff Mahoney SWARN(silent, s, "clm-7000", 190645b03d5eSJeff Mahoney "Detected readonly device, marking FS readonly"); 19071da177e4SLinus Torvalds s->s_flags |= MS_RDONLY; 19081da177e4SLinus Torvalds } 19091da177e4SLinus Torvalds args.objectid = REISERFS_ROOT_OBJECTID; 19101da177e4SLinus Torvalds args.dirid = REISERFS_ROOT_PARENT_OBJECTID; 1911bd4c625cSLinus Torvalds root_inode = 1912bd4c625cSLinus Torvalds iget5_locked(s, REISERFS_ROOT_OBJECTID, reiserfs_find_actor, 1913bd4c625cSLinus Torvalds reiserfs_init_locked_inode, (void *)(&args)); 19141da177e4SLinus Torvalds if (!root_inode) { 191545b03d5eSJeff Mahoney SWARN(silent, s, "jmacd-10", "get root inode failed"); 19169b467e6eSFrederic Weisbecker goto error_unlocked; 19171da177e4SLinus Torvalds } 19181da177e4SLinus Torvalds 19199b467e6eSFrederic Weisbecker /* 19209b467e6eSFrederic Weisbecker * This path assumed to be called with the BKL in the old times. 19219b467e6eSFrederic Weisbecker * Now we have inherited the big reiserfs lock from it and many 19229b467e6eSFrederic Weisbecker * reiserfs helpers called in the mount path and elsewhere require 19239b467e6eSFrederic Weisbecker * this lock to be held even if it's not always necessary. Let's be 19249b467e6eSFrederic Weisbecker * conservative and hold it early. The window can be reduced after 19259b467e6eSFrederic Weisbecker * careful review of the code. 19269b467e6eSFrederic Weisbecker */ 19279b467e6eSFrederic Weisbecker reiserfs_write_lock(s); 19289b467e6eSFrederic Weisbecker 19291da177e4SLinus Torvalds if (root_inode->i_state & I_NEW) { 19301da177e4SLinus Torvalds reiserfs_read_locked_inode(root_inode, &args); 19311da177e4SLinus Torvalds unlock_new_inode(root_inode); 19321da177e4SLinus Torvalds } 19331da177e4SLinus Torvalds 193448fde701SAl Viro s->s_root = d_make_root(root_inode); 193548fde701SAl Viro if (!s->s_root) 19361da177e4SLinus Torvalds goto error; 19371da177e4SLinus Torvalds // define and initialize hash function 19381da177e4SLinus Torvalds sbi->s_hash_function = hash_function(s); 19391da177e4SLinus Torvalds if (sbi->s_hash_function == NULL) { 19401da177e4SLinus Torvalds dput(s->s_root); 19411da177e4SLinus Torvalds s->s_root = NULL; 19421da177e4SLinus Torvalds goto error; 19431da177e4SLinus Torvalds } 19441da177e4SLinus Torvalds 1945bd4c625cSLinus Torvalds if (is_reiserfs_3_5(rs) 1946bd4c625cSLinus Torvalds || (is_reiserfs_jr(rs) && SB_VERSION(s) == REISERFS_VERSION_1)) 19471da177e4SLinus Torvalds set_bit(REISERFS_3_5, &(sbi->s_properties)); 1948e1fabd3cSJeff Mahoney else if (old_format) 1949e1fabd3cSJeff Mahoney set_bit(REISERFS_OLD_FORMAT, &(sbi->s_properties)); 19501da177e4SLinus Torvalds else 19511da177e4SLinus Torvalds set_bit(REISERFS_3_6, &(sbi->s_properties)); 19521da177e4SLinus Torvalds 19531da177e4SLinus Torvalds if (!(s->s_flags & MS_RDONLY)) { 19541da177e4SLinus Torvalds 19551da177e4SLinus Torvalds errval = journal_begin(&th, s, 1); 19561da177e4SLinus Torvalds if (errval) { 19571da177e4SLinus Torvalds dput(s->s_root); 19581da177e4SLinus Torvalds s->s_root = NULL; 19591da177e4SLinus Torvalds goto error; 19601da177e4SLinus Torvalds } 19611da177e4SLinus Torvalds reiserfs_prepare_for_journal(s, SB_BUFFER_WITH_SB(s), 1); 19621da177e4SLinus Torvalds 19631da177e4SLinus Torvalds set_sb_umount_state(rs, REISERFS_ERROR_FS); 19641da177e4SLinus Torvalds set_sb_fs_state(rs, 0); 19651da177e4SLinus Torvalds 1966cb680c1bSJeff Mahoney /* Clear out s_bmap_nr if it would wrap. We can handle this 1967cb680c1bSJeff Mahoney * case, but older revisions can't. This will cause the 1968cb680c1bSJeff Mahoney * file system to fail mount on those older implementations, 1969cb680c1bSJeff Mahoney * avoiding corruption. -jeffm */ 1970cb680c1bSJeff Mahoney if (bmap_would_wrap(reiserfs_bmap_count(s)) && 1971cb680c1bSJeff Mahoney sb_bmap_nr(rs) != 0) { 197245b03d5eSJeff Mahoney reiserfs_warning(s, "super-2030", "This file system " 1973cb680c1bSJeff Mahoney "claims to use %u bitmap blocks in " 1974cb680c1bSJeff Mahoney "its super block, but requires %u. " 1975cb680c1bSJeff Mahoney "Clearing to zero.", sb_bmap_nr(rs), 1976cb680c1bSJeff Mahoney reiserfs_bmap_count(s)); 1977cb680c1bSJeff Mahoney 1978cb680c1bSJeff Mahoney set_sb_bmap_nr(rs, 0); 1979cb680c1bSJeff Mahoney } 1980cb680c1bSJeff Mahoney 19811da177e4SLinus Torvalds if (old_format_only(s)) { 19821da177e4SLinus Torvalds /* filesystem of format 3.5 either with standard or non-standard 19831da177e4SLinus Torvalds journal */ 19841da177e4SLinus Torvalds if (convert_reiserfs(s)) { 19851da177e4SLinus Torvalds /* and -o conv is given */ 19861da177e4SLinus Torvalds if (!silent) 1987bd4c625cSLinus Torvalds reiserfs_info(s, 1988bd4c625cSLinus Torvalds "converting 3.5 filesystem to the 3.6 format"); 19891da177e4SLinus Torvalds 19901da177e4SLinus Torvalds if (is_reiserfs_3_5(rs)) 19911da177e4SLinus Torvalds /* put magic string of 3.6 format. 2.2 will not be able to 19921da177e4SLinus Torvalds mount this filesystem anymore */ 1993bd4c625cSLinus Torvalds memcpy(rs->s_v1.s_magic, 1994bd4c625cSLinus Torvalds reiserfs_3_6_magic_string, 1995bd4c625cSLinus Torvalds sizeof 1996bd4c625cSLinus Torvalds (reiserfs_3_6_magic_string)); 19971da177e4SLinus Torvalds 19981da177e4SLinus Torvalds set_sb_version(rs, REISERFS_VERSION_2); 19991da177e4SLinus Torvalds reiserfs_convert_objectid_map_v1(s); 20001da177e4SLinus Torvalds set_bit(REISERFS_3_6, &(sbi->s_properties)); 20011da177e4SLinus Torvalds clear_bit(REISERFS_3_5, &(sbi->s_properties)); 20021da177e4SLinus Torvalds } else if (!silent) { 20031da177e4SLinus Torvalds reiserfs_info(s, "using 3.5.x disk format\n"); 20041da177e4SLinus Torvalds } 2005702d21c6SJeff Mahoney } else 2006702d21c6SJeff Mahoney set_sb_mnt_count(rs, sb_mnt_count(rs) + 1); 2007702d21c6SJeff Mahoney 20081da177e4SLinus Torvalds 20091da177e4SLinus Torvalds journal_mark_dirty(&th, s, SB_BUFFER_WITH_SB(s)); 20101da177e4SLinus Torvalds errval = journal_end(&th, s, 1); 20111da177e4SLinus Torvalds if (errval) { 20121da177e4SLinus Torvalds dput(s->s_root); 20131da177e4SLinus Torvalds s->s_root = NULL; 20141da177e4SLinus Torvalds goto error; 20151da177e4SLinus Torvalds } 20161da177e4SLinus Torvalds 2017edcc37a0SAl Viro if ((errval = reiserfs_lookup_privroot(s)) || 2018edcc37a0SAl Viro (errval = reiserfs_xattr_init(s, s->s_flags))) { 20191da177e4SLinus Torvalds dput(s->s_root); 20201da177e4SLinus Torvalds s->s_root = NULL; 20211da177e4SLinus Torvalds goto error; 20221da177e4SLinus Torvalds } 20231da177e4SLinus Torvalds 20241da177e4SLinus Torvalds /* look for files which were to be removed in previous session */ 20251da177e4SLinus Torvalds finish_unfinished(s); 20261da177e4SLinus Torvalds } else { 20271da177e4SLinus Torvalds if (old_format_only(s) && !silent) { 20281da177e4SLinus Torvalds reiserfs_info(s, "using 3.5.x disk format\n"); 20291da177e4SLinus Torvalds } 20301da177e4SLinus Torvalds 2031edcc37a0SAl Viro if ((errval = reiserfs_lookup_privroot(s)) || 2032edcc37a0SAl Viro (errval = reiserfs_xattr_init(s, s->s_flags))) { 20331da177e4SLinus Torvalds dput(s->s_root); 20341da177e4SLinus Torvalds s->s_root = NULL; 20351da177e4SLinus Torvalds goto error; 20361da177e4SLinus Torvalds } 20371da177e4SLinus Torvalds } 20381da177e4SLinus Torvalds // mark hash in super block: it could be unset. overwrite should be ok 20391da177e4SLinus Torvalds set_sb_hash_function_code(rs, function2code(sbi->s_hash_function)); 20401da177e4SLinus Torvalds 20411da177e4SLinus Torvalds handle_attrs(s); 20421da177e4SLinus Torvalds 20431da177e4SLinus Torvalds reiserfs_proc_info_init(s); 20441da177e4SLinus Torvalds 20451da177e4SLinus Torvalds init_waitqueue_head(&(sbi->s_wait)); 20461da177e4SLinus Torvalds spin_lock_init(&sbi->bitmap_lock); 20471da177e4SLinus Torvalds 20488ebc4232SFrederic Weisbecker reiserfs_write_unlock(s); 20498ebc4232SFrederic Weisbecker 20501da177e4SLinus Torvalds return (0); 20511da177e4SLinus Torvalds 20521da177e4SLinus Torvalds error: 2053b7b7fa43SJeff Mahoney reiserfs_write_unlock(s); 2054b7b7fa43SJeff Mahoney 2055f32485beSFrederic Weisbecker error_unlocked: 2056f32485beSFrederic Weisbecker /* kill the commit thread, free journal ram */ 2057f32485beSFrederic Weisbecker if (jinit_done) { 2058f32485beSFrederic Weisbecker reiserfs_write_lock(s); 2059f32485beSFrederic Weisbecker journal_release_error(NULL, s); 2060f32485beSFrederic Weisbecker reiserfs_write_unlock(s); 2061f32485beSFrederic Weisbecker } 2062f32485beSFrederic Weisbecker 2063033369d1SArtem Bityutskiy cancel_delayed_work_sync(&REISERFS_SB(s)->old_work); 2064033369d1SArtem Bityutskiy 20655065227bSJeff Mahoney reiserfs_free_bitmap_cache(s); 20661da177e4SLinus Torvalds if (SB_BUFFER_WITH_SB(s)) 20671da177e4SLinus Torvalds brelse(SB_BUFFER_WITH_SB(s)); 20681da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 20695065227bSJeff Mahoney { 20705065227bSJeff Mahoney int j; 207100b44197SJan Kara for (j = 0; j < MAXQUOTAS; j++) 207200b44197SJan Kara kfree(qf_names[j]); 20735065227bSJeff Mahoney } 20741da177e4SLinus Torvalds #endif 20751da177e4SLinus Torvalds kfree(sbi); 20761da177e4SLinus Torvalds 20771da177e4SLinus Torvalds s->s_fs_info = NULL; 20781da177e4SLinus Torvalds return errval; 20791da177e4SLinus Torvalds } 20801da177e4SLinus Torvalds 2081726c3342SDavid Howells static int reiserfs_statfs(struct dentry *dentry, struct kstatfs *buf) 20821da177e4SLinus Torvalds { 2083726c3342SDavid Howells struct reiserfs_super_block *rs = SB_DISK_SUPER_BLOCK(dentry->d_sb); 20841da177e4SLinus Torvalds 20851da177e4SLinus Torvalds buf->f_namelen = (REISERFS_MAX_NAME(s->s_blocksize)); 20861da177e4SLinus Torvalds buf->f_bfree = sb_free_blocks(rs); 20871da177e4SLinus Torvalds buf->f_bavail = buf->f_bfree; 20881da177e4SLinus Torvalds buf->f_blocks = sb_block_count(rs) - sb_bmap_nr(rs) - 1; 2089726c3342SDavid Howells buf->f_bsize = dentry->d_sb->s_blocksize; 20901da177e4SLinus Torvalds /* changed to accommodate gcc folks. */ 20911da177e4SLinus Torvalds buf->f_type = REISERFS_SUPER_MAGIC; 2092651d0623SColy Li buf->f_fsid.val[0] = (u32)crc32_le(0, rs->s_uuid, sizeof(rs->s_uuid)/2); 2093651d0623SColy Li buf->f_fsid.val[1] = (u32)crc32_le(0, rs->s_uuid + sizeof(rs->s_uuid)/2, 2094651d0623SColy Li sizeof(rs->s_uuid)/2); 2095651d0623SColy Li 20961da177e4SLinus Torvalds return 0; 20971da177e4SLinus Torvalds } 20981da177e4SLinus Torvalds 20991da177e4SLinus Torvalds #ifdef CONFIG_QUOTA 21001da177e4SLinus Torvalds static int reiserfs_write_dquot(struct dquot *dquot) 21011da177e4SLinus Torvalds { 21021da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 2103bd6a1f16SJan Kara int ret, err; 21041da177e4SLinus Torvalds 21051da177e4SLinus Torvalds reiserfs_write_lock(dquot->dq_sb); 2106bd4c625cSLinus Torvalds ret = 2107bd4c625cSLinus Torvalds journal_begin(&th, dquot->dq_sb, 2108bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); 2109bd6a1f16SJan Kara if (ret) 2110bd6a1f16SJan Kara goto out; 21111da177e4SLinus Torvalds ret = dquot_commit(dquot); 2112bd4c625cSLinus Torvalds err = 2113bd4c625cSLinus Torvalds journal_end(&th, dquot->dq_sb, 2114bd4c625cSLinus Torvalds REISERFS_QUOTA_TRANS_BLOCKS(dquot->dq_sb)); 2115bd6a1f16SJan Kara if (!ret && err) 2116bd6a1f16SJan Kara ret = err; 2117bd6a1f16SJan Kara out: 21181da177e4SLinus Torvalds reiserfs_write_unlock(dquot->dq_sb); 21191da177e4SLinus Torvalds return ret; 21201da177e4SLinus Torvalds } 21211da177e4SLinus Torvalds 21221da177e4SLinus Torvalds static int reiserfs_acquire_dquot(struct dquot *dquot) 21231da177e4SLinus Torvalds { 21241da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 2125bd6a1f16SJan Kara int ret, err; 21261da177e4SLinus Torvalds 21271da177e4SLinus Torvalds reiserfs_write_lock(dquot->dq_sb); 2128bd4c625cSLinus Torvalds ret = 2129bd4c625cSLinus Torvalds journal_begin(&th, dquot->dq_sb, 2130bd4c625cSLinus Torvalds REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); 2131bd6a1f16SJan Kara if (ret) 2132bd6a1f16SJan Kara goto out; 21331da177e4SLinus Torvalds ret = dquot_acquire(dquot); 2134bd4c625cSLinus Torvalds err = 2135bd4c625cSLinus Torvalds journal_end(&th, dquot->dq_sb, 2136bd4c625cSLinus Torvalds REISERFS_QUOTA_INIT_BLOCKS(dquot->dq_sb)); 2137bd6a1f16SJan Kara if (!ret && err) 2138bd6a1f16SJan Kara ret = err; 2139bd6a1f16SJan Kara out: 21401da177e4SLinus Torvalds reiserfs_write_unlock(dquot->dq_sb); 21411da177e4SLinus Torvalds return ret; 21421da177e4SLinus Torvalds } 21431da177e4SLinus Torvalds 21441da177e4SLinus Torvalds static int reiserfs_release_dquot(struct dquot *dquot) 21451da177e4SLinus Torvalds { 21461da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 2147bd6a1f16SJan Kara int ret, err; 21481da177e4SLinus Torvalds 21491da177e4SLinus Torvalds reiserfs_write_lock(dquot->dq_sb); 2150bd4c625cSLinus Torvalds ret = 2151bd4c625cSLinus Torvalds journal_begin(&th, dquot->dq_sb, 2152bd4c625cSLinus Torvalds REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 21539c3013e9SJan Kara if (ret) { 21549c3013e9SJan Kara /* Release dquot anyway to avoid endless cycle in dqput() */ 21559c3013e9SJan Kara dquot_release(dquot); 2156bd6a1f16SJan Kara goto out; 21579c3013e9SJan Kara } 21581da177e4SLinus Torvalds ret = dquot_release(dquot); 2159bd4c625cSLinus Torvalds err = 2160bd4c625cSLinus Torvalds journal_end(&th, dquot->dq_sb, 2161bd4c625cSLinus Torvalds REISERFS_QUOTA_DEL_BLOCKS(dquot->dq_sb)); 2162bd6a1f16SJan Kara if (!ret && err) 2163bd6a1f16SJan Kara ret = err; 2164bd6a1f16SJan Kara out: 21651da177e4SLinus Torvalds reiserfs_write_unlock(dquot->dq_sb); 21661da177e4SLinus Torvalds return ret; 21671da177e4SLinus Torvalds } 21681da177e4SLinus Torvalds 21691da177e4SLinus Torvalds static int reiserfs_mark_dquot_dirty(struct dquot *dquot) 21701da177e4SLinus Torvalds { 21714506567bSJan Kara /* Are we journaling quotas? */ 21721da177e4SLinus Torvalds if (REISERFS_SB(dquot->dq_sb)->s_qf_names[USRQUOTA] || 21731da177e4SLinus Torvalds REISERFS_SB(dquot->dq_sb)->s_qf_names[GRPQUOTA]) { 21741da177e4SLinus Torvalds dquot_mark_dquot_dirty(dquot); 21751da177e4SLinus Torvalds return reiserfs_write_dquot(dquot); 2176bd4c625cSLinus Torvalds } else 21771da177e4SLinus Torvalds return dquot_mark_dquot_dirty(dquot); 21781da177e4SLinus Torvalds } 21791da177e4SLinus Torvalds 21801da177e4SLinus Torvalds static int reiserfs_write_info(struct super_block *sb, int type) 21811da177e4SLinus Torvalds { 21821da177e4SLinus Torvalds struct reiserfs_transaction_handle th; 2183bd6a1f16SJan Kara int ret, err; 21841da177e4SLinus Torvalds 21851da177e4SLinus Torvalds /* Data block + inode block */ 21861da177e4SLinus Torvalds reiserfs_write_lock(sb); 2187bd6a1f16SJan Kara ret = journal_begin(&th, sb, 2); 2188bd6a1f16SJan Kara if (ret) 2189bd6a1f16SJan Kara goto out; 21901da177e4SLinus Torvalds ret = dquot_commit_info(sb, type); 2191bd6a1f16SJan Kara err = journal_end(&th, sb, 2); 2192bd6a1f16SJan Kara if (!ret && err) 2193bd6a1f16SJan Kara ret = err; 2194bd6a1f16SJan Kara out: 21951da177e4SLinus Torvalds reiserfs_write_unlock(sb); 21961da177e4SLinus Torvalds return ret; 21971da177e4SLinus Torvalds } 21981da177e4SLinus Torvalds 21991da177e4SLinus Torvalds /* 220084de856eSChristoph Hellwig * Turn on quotas during mount time - we need to find the quota file and such... 22011da177e4SLinus Torvalds */ 22021da177e4SLinus Torvalds static int reiserfs_quota_on_mount(struct super_block *sb, int type) 22031da177e4SLinus Torvalds { 2204287a8095SChristoph Hellwig return dquot_quota_on_mount(sb, REISERFS_SB(sb)->s_qf_names[type], 220584de856eSChristoph Hellwig REISERFS_SB(sb)->s_jquota_fmt, type); 22061da177e4SLinus Torvalds } 22071da177e4SLinus Torvalds 22081da177e4SLinus Torvalds /* 22091da177e4SLinus Torvalds * Standard function to be called on quota_on 22101da177e4SLinus Torvalds */ 2211bd4c625cSLinus Torvalds static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, 2212f00c9e44SJan Kara struct path *path) 22131da177e4SLinus Torvalds { 22141da177e4SLinus Torvalds int err; 2215d5dee5c3SJan Kara struct inode *inode; 22165d4f7fddSJan Kara struct reiserfs_transaction_handle th; 2217c3aa0776SJan Kara int opt = type == USRQUOTA ? REISERFS_USRQUOTA : REISERFS_GRPQUOTA; 22181da177e4SLinus Torvalds 2219c3aa0776SJan Kara if (!(REISERFS_SB(sb)->s_mount_opt & (1 << opt))) 2220556a2a45SJan Kara return -EINVAL; 2221307ae18aSChristoph Hellwig 22221da177e4SLinus Torvalds /* Quotafile not on the same filesystem? */ 2223d8c9584eSAl Viro if (path->dentry->d_sb != sb) { 222477e69dacSAl Viro err = -EXDEV; 222577e69dacSAl Viro goto out; 22261da177e4SLinus Torvalds } 2227f00c9e44SJan Kara inode = path->dentry->d_inode; 22281da177e4SLinus Torvalds /* We must not pack tails for quota files on reiserfs for quota IO to work */ 2229d5dee5c3SJan Kara if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) { 2230d5dee5c3SJan Kara err = reiserfs_unpack(inode, NULL); 2231d5dee5c3SJan Kara if (err) { 223245b03d5eSJeff Mahoney reiserfs_warning(sb, "super-6520", 223345b03d5eSJeff Mahoney "Unpacking tail of quota file failed" 2234d5dee5c3SJan Kara " (%d). Cannot turn on quotas.", err); 223577e69dacSAl Viro err = -EINVAL; 223677e69dacSAl Viro goto out; 22371da177e4SLinus Torvalds } 2238d5dee5c3SJan Kara mark_inode_dirty(inode); 2239d5dee5c3SJan Kara } 22405d4f7fddSJan Kara /* Journaling quota? */ 22415d4f7fddSJan Kara if (REISERFS_SB(sb)->s_qf_names[type]) { 22421da177e4SLinus Torvalds /* Quotafile not of fs root? */ 2243f00c9e44SJan Kara if (path->dentry->d_parent != sb->s_root) 224445b03d5eSJeff Mahoney reiserfs_warning(sb, "super-6521", 224545b03d5eSJeff Mahoney "Quota file not on filesystem root. " 22461da177e4SLinus Torvalds "Journalled quota will not work."); 22475d4f7fddSJan Kara } 22485d4f7fddSJan Kara 22495d4f7fddSJan Kara /* 22505d4f7fddSJan Kara * When we journal data on quota file, we have to flush journal to see 22515d4f7fddSJan Kara * all updates to the file when we bypass pagecache... 22525d4f7fddSJan Kara */ 22535d4f7fddSJan Kara if (reiserfs_file_data_log(inode)) { 22545d4f7fddSJan Kara /* Just start temporary transaction and finish it */ 22555d4f7fddSJan Kara err = journal_begin(&th, sb, 1); 22565d4f7fddSJan Kara if (err) 225777e69dacSAl Viro goto out; 22585d4f7fddSJan Kara err = journal_end_sync(&th, sb, 1); 22595d4f7fddSJan Kara if (err) 226077e69dacSAl Viro goto out; 22615d4f7fddSJan Kara } 2262f00c9e44SJan Kara err = dquot_quota_on(sb, type, format_id, path); 226377e69dacSAl Viro out: 226477e69dacSAl Viro return err; 22651da177e4SLinus Torvalds } 22661da177e4SLinus Torvalds 22671da177e4SLinus Torvalds /* Read data from quotafile - avoid pagecache and such because we cannot afford 22681da177e4SLinus Torvalds * acquiring the locks... As quota files are never truncated and quota code 22691da177e4SLinus Torvalds * itself serializes the operations (and no one else should touch the files) 22701da177e4SLinus Torvalds * we don't have to be afraid of races */ 22711da177e4SLinus Torvalds static ssize_t reiserfs_quota_read(struct super_block *sb, int type, char *data, 22721da177e4SLinus Torvalds size_t len, loff_t off) 22731da177e4SLinus Torvalds { 22741da177e4SLinus Torvalds struct inode *inode = sb_dqopt(sb)->files[type]; 22751da177e4SLinus Torvalds unsigned long blk = off >> sb->s_blocksize_bits; 22761da177e4SLinus Torvalds int err = 0, offset = off & (sb->s_blocksize - 1), tocopy; 22771da177e4SLinus Torvalds size_t toread; 22781da177e4SLinus Torvalds struct buffer_head tmp_bh, *bh; 22791da177e4SLinus Torvalds loff_t i_size = i_size_read(inode); 22801da177e4SLinus Torvalds 22811da177e4SLinus Torvalds if (off > i_size) 22821da177e4SLinus Torvalds return 0; 22831da177e4SLinus Torvalds if (off + len > i_size) 22841da177e4SLinus Torvalds len = i_size - off; 22851da177e4SLinus Torvalds toread = len; 22861da177e4SLinus Torvalds while (toread > 0) { 2287bd4c625cSLinus Torvalds tocopy = 2288bd4c625cSLinus Torvalds sb->s_blocksize - offset < 2289bd4c625cSLinus Torvalds toread ? sb->s_blocksize - offset : toread; 22901da177e4SLinus Torvalds tmp_bh.b_state = 0; 22911da177e4SLinus Torvalds /* Quota files are without tails so we can safely use this function */ 22921da177e4SLinus Torvalds reiserfs_write_lock(sb); 22931da177e4SLinus Torvalds err = reiserfs_get_block(inode, blk, &tmp_bh, 0); 22941da177e4SLinus Torvalds reiserfs_write_unlock(sb); 22951da177e4SLinus Torvalds if (err) 22961da177e4SLinus Torvalds return err; 22971da177e4SLinus Torvalds if (!buffer_mapped(&tmp_bh)) /* A hole? */ 22981da177e4SLinus Torvalds memset(data, 0, tocopy); 22991da177e4SLinus Torvalds else { 23001da177e4SLinus Torvalds bh = sb_bread(sb, tmp_bh.b_blocknr); 23011da177e4SLinus Torvalds if (!bh) 23021da177e4SLinus Torvalds return -EIO; 23031da177e4SLinus Torvalds memcpy(data, bh->b_data + offset, tocopy); 23041da177e4SLinus Torvalds brelse(bh); 23051da177e4SLinus Torvalds } 23061da177e4SLinus Torvalds offset = 0; 23071da177e4SLinus Torvalds toread -= tocopy; 23081da177e4SLinus Torvalds data += tocopy; 23091da177e4SLinus Torvalds blk++; 23101da177e4SLinus Torvalds } 23111da177e4SLinus Torvalds return len; 23121da177e4SLinus Torvalds } 23131da177e4SLinus Torvalds 23141da177e4SLinus Torvalds /* Write to quotafile (we know the transaction is already started and has 23151da177e4SLinus Torvalds * enough credits) */ 23161da177e4SLinus Torvalds static ssize_t reiserfs_quota_write(struct super_block *sb, int type, 23171da177e4SLinus Torvalds const char *data, size_t len, loff_t off) 23181da177e4SLinus Torvalds { 23191da177e4SLinus Torvalds struct inode *inode = sb_dqopt(sb)->files[type]; 23201da177e4SLinus Torvalds unsigned long blk = off >> sb->s_blocksize_bits; 23211da177e4SLinus Torvalds int err = 0, offset = off & (sb->s_blocksize - 1), tocopy; 23221da177e4SLinus Torvalds int journal_quota = REISERFS_SB(sb)->s_qf_names[type] != NULL; 23231da177e4SLinus Torvalds size_t towrite = len; 23241da177e4SLinus Torvalds struct buffer_head tmp_bh, *bh; 23251da177e4SLinus Torvalds 23269c3013e9SJan Kara if (!current->journal_info) { 23279c3013e9SJan Kara printk(KERN_WARNING "reiserfs: Quota write (off=%Lu, len=%Lu)" 23289c3013e9SJan Kara " cancelled because transaction is not started.\n", 23299c3013e9SJan Kara (unsigned long long)off, (unsigned long long)len); 23309c3013e9SJan Kara return -EIO; 23319c3013e9SJan Kara } 23321da177e4SLinus Torvalds while (towrite > 0) { 23331da177e4SLinus Torvalds tocopy = sb->s_blocksize - offset < towrite ? 23341da177e4SLinus Torvalds sb->s_blocksize - offset : towrite; 23351da177e4SLinus Torvalds tmp_bh.b_state = 0; 23361da177e4SLinus Torvalds err = reiserfs_get_block(inode, blk, &tmp_bh, GET_BLOCK_CREATE); 23371da177e4SLinus Torvalds if (err) 23381da177e4SLinus Torvalds goto out; 23391da177e4SLinus Torvalds if (offset || tocopy != sb->s_blocksize) 23401da177e4SLinus Torvalds bh = sb_bread(sb, tmp_bh.b_blocknr); 23411da177e4SLinus Torvalds else 23421da177e4SLinus Torvalds bh = sb_getblk(sb, tmp_bh.b_blocknr); 23431da177e4SLinus Torvalds if (!bh) { 23441da177e4SLinus Torvalds err = -EIO; 23451da177e4SLinus Torvalds goto out; 23461da177e4SLinus Torvalds } 23471da177e4SLinus Torvalds lock_buffer(bh); 23481da177e4SLinus Torvalds memcpy(bh->b_data + offset, data, tocopy); 23491da177e4SLinus Torvalds flush_dcache_page(bh->b_page); 23501da177e4SLinus Torvalds set_buffer_uptodate(bh); 23511da177e4SLinus Torvalds unlock_buffer(bh); 23521da177e4SLinus Torvalds reiserfs_prepare_for_journal(sb, bh, 1); 23531da177e4SLinus Torvalds journal_mark_dirty(current->journal_info, sb, bh); 23541da177e4SLinus Torvalds if (!journal_quota) 23551da177e4SLinus Torvalds reiserfs_add_ordered_list(inode, bh); 23561da177e4SLinus Torvalds brelse(bh); 23571da177e4SLinus Torvalds offset = 0; 23581da177e4SLinus Torvalds towrite -= tocopy; 23591da177e4SLinus Torvalds data += tocopy; 23601da177e4SLinus Torvalds blk++; 23611da177e4SLinus Torvalds } 23621da177e4SLinus Torvalds out: 236367f1648dSJan Kara if (len == towrite) 23641da177e4SLinus Torvalds return err; 23651da177e4SLinus Torvalds if (inode->i_size < off + len - towrite) 23661da177e4SLinus Torvalds i_size_write(inode, off + len - towrite); 23671da177e4SLinus Torvalds inode->i_version++; 23681da177e4SLinus Torvalds inode->i_mtime = inode->i_ctime = CURRENT_TIME; 23691da177e4SLinus Torvalds mark_inode_dirty(inode); 23701da177e4SLinus Torvalds return len - towrite; 23711da177e4SLinus Torvalds } 23721da177e4SLinus Torvalds 23731da177e4SLinus Torvalds #endif 23741da177e4SLinus Torvalds 2375152a0836SAl Viro static struct dentry *get_super_block(struct file_system_type *fs_type, 2376bd4c625cSLinus Torvalds int flags, const char *dev_name, 2377152a0836SAl Viro void *data) 23781da177e4SLinus Torvalds { 2379152a0836SAl Viro return mount_bdev(fs_type, flags, dev_name, data, reiserfs_fill_super); 23801da177e4SLinus Torvalds } 23811da177e4SLinus Torvalds 2382bd4c625cSLinus Torvalds static int __init init_reiserfs_fs(void) 23831da177e4SLinus Torvalds { 23841da177e4SLinus Torvalds int ret; 23851da177e4SLinus Torvalds 23861da177e4SLinus Torvalds if ((ret = init_inodecache())) { 23871da177e4SLinus Torvalds return ret; 23881da177e4SLinus Torvalds } 23891da177e4SLinus Torvalds 23901da177e4SLinus Torvalds reiserfs_proc_info_global_init(); 23911da177e4SLinus Torvalds 23921da177e4SLinus Torvalds ret = register_filesystem(&reiserfs_fs_type); 23931da177e4SLinus Torvalds 23941da177e4SLinus Torvalds if (ret == 0) { 23951da177e4SLinus Torvalds return 0; 23961da177e4SLinus Torvalds } 23971da177e4SLinus Torvalds 23981da177e4SLinus Torvalds reiserfs_proc_info_global_done(); 23991da177e4SLinus Torvalds destroy_inodecache(); 24001da177e4SLinus Torvalds 24011da177e4SLinus Torvalds return ret; 24021da177e4SLinus Torvalds } 24031da177e4SLinus Torvalds 2404bd4c625cSLinus Torvalds static void __exit exit_reiserfs_fs(void) 24051da177e4SLinus Torvalds { 24061da177e4SLinus Torvalds reiserfs_proc_info_global_done(); 24071da177e4SLinus Torvalds unregister_filesystem(&reiserfs_fs_type); 24081da177e4SLinus Torvalds destroy_inodecache(); 24091da177e4SLinus Torvalds } 24101da177e4SLinus Torvalds 24111da177e4SLinus Torvalds struct file_system_type reiserfs_fs_type = { 24121da177e4SLinus Torvalds .owner = THIS_MODULE, 24131da177e4SLinus Torvalds .name = "reiserfs", 2414152a0836SAl Viro .mount = get_super_block, 2415edc666e2SDavid Howells .kill_sb = reiserfs_kill_sb, 24161da177e4SLinus Torvalds .fs_flags = FS_REQUIRES_DEV, 24171da177e4SLinus Torvalds }; 24181da177e4SLinus Torvalds 24191da177e4SLinus Torvalds MODULE_DESCRIPTION("ReiserFS journaled filesystem"); 24201da177e4SLinus Torvalds MODULE_AUTHOR("Hans Reiser <reiser@namesys.com>"); 24211da177e4SLinus Torvalds MODULE_LICENSE("GPL"); 24221da177e4SLinus Torvalds 24231da177e4SLinus Torvalds module_init(init_reiserfs_fs); 24241da177e4SLinus Torvalds module_exit(exit_reiserfs_fs); 2425