diff options
author | Igor Mammedov <niallain@gmail.com> | 2008-04-28 23:08:21 +0000 |
---|---|---|
committer | Steve French <sfrench@us.ibm.com> | 2008-04-28 23:08:21 +0000 |
commit | e9f20d6f03e8df393b001dab6dc5226c2a5daf57 (patch) | |
tree | 73e94fa5e4f83576c97e36187b809c5aad2ade30 /fs | |
parent | bf62fd887cab230f5952b611bde25e8e15acb454 (diff) | |
parent | e31a94ed371c70855eb30b77c490d6d85dd4da26 (diff) | |
download | kernel_samsung_crespo-e9f20d6f03e8df393b001dab6dc5226c2a5daf57.zip kernel_samsung_crespo-e9f20d6f03e8df393b001dab6dc5226c2a5daf57.tar.gz kernel_samsung_crespo-e9f20d6f03e8df393b001dab6dc5226c2a5daf57.tar.bz2 |
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
Diffstat (limited to 'fs')
60 files changed, 727 insertions, 567 deletions
@@ -1166,7 +1166,10 @@ retry: break; if (min_nr <= i) break; - ret = 0; + if (unlikely(ctx->dead)) { + ret = -EINVAL; + break; + } if (to.timed_out) /* Only check after read evt */ break; /* Try to only show up in io wait if there are ops @@ -1231,6 +1234,13 @@ static void io_destroy(struct kioctx *ioctx) aio_cancel_all(ioctx); wait_for_all_aios(ioctx); + + /* + * Wake up any waiters. The setting of ctx->dead must be seen + * by other CPUs at this point. Right now, we rely on the + * locking done by the above calls to ensure this consistency. + */ + wake_up(&ioctx->wait); put_ioctx(ioctx); /* once for the lookup */ } diff --git a/fs/buffer.c b/fs/buffer.c index 39ff144..3db4a26 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -360,16 +360,19 @@ void invalidate_bdev(struct block_device *bdev) */ static void free_more_memory(void) { - struct zone **zones; - pg_data_t *pgdat; + struct zone *zone; + int nid; wakeup_pdflush(1024); yield(); - for_each_online_pgdat(pgdat) { - zones = pgdat->node_zonelists[gfp_zone(GFP_NOFS)].zones; - if (*zones) - try_to_free_pages(zones, 0, GFP_NOFS); + for_each_online_node(nid) { + (void)first_zones_zonelist(node_zonelist(nid, GFP_NOFS), + gfp_zone(GFP_NOFS), NULL, + &zone); + if (zone) + try_to_free_pages(node_zonelist(nid, GFP_NOFS), 0, + GFP_NOFS); } } @@ -2243,6 +2246,8 @@ int cont_expand_zero(struct file *file, struct address_space *mapping, goto out; BUG_ON(err != len); err = 0; + + balance_dirty_pages_ratelimited(mapping); } /* page covers the boundary, find the boundary offset */ @@ -3180,8 +3185,7 @@ static void recalc_bh_state(void) struct buffer_head *alloc_buffer_head(gfp_t gfp_flags) { - struct buffer_head *ret = kmem_cache_alloc(bh_cachep, - set_migrateflags(gfp_flags, __GFP_RECLAIMABLE)); + struct buffer_head *ret = kmem_cache_alloc(bh_cachep, gfp_flags); if (ret) { INIT_LIST_HEAD(&ret->b_assoc_buffers); get_cpu_var(bh_accounting).nr++; @@ -289,7 +289,15 @@ static void wait_on_dquot(struct dquot *dquot) mutex_unlock(&dquot->dq_lock); } -#define mark_dquot_dirty(dquot) ((dquot)->dq_sb->dq_op->mark_dirty(dquot)) +static inline int dquot_dirty(struct dquot *dquot) +{ + return test_bit(DQ_MOD_B, &dquot->dq_flags); +} + +static inline int mark_dquot_dirty(struct dquot *dquot) +{ + return dquot->dq_sb->dq_op->mark_dirty(dquot); +} int dquot_mark_dquot_dirty(struct dquot *dquot) { @@ -1441,31 +1449,43 @@ static inline void set_enable_flags(struct quota_info *dqopt, int type) switch (type) { case USRQUOTA: dqopt->flags |= DQUOT_USR_ENABLED; + dqopt->flags &= ~DQUOT_USR_SUSPENDED; break; case GRPQUOTA: dqopt->flags |= DQUOT_GRP_ENABLED; + dqopt->flags &= ~DQUOT_GRP_SUSPENDED; break; } } -static inline void reset_enable_flags(struct quota_info *dqopt, int type) +static inline void reset_enable_flags(struct quota_info *dqopt, int type, + int remount) { switch (type) { case USRQUOTA: dqopt->flags &= ~DQUOT_USR_ENABLED; + if (remount) + dqopt->flags |= DQUOT_USR_SUSPENDED; + else + dqopt->flags &= ~DQUOT_USR_SUSPENDED; break; case GRPQUOTA: dqopt->flags &= ~DQUOT_GRP_ENABLED; + if (remount) + dqopt->flags |= DQUOT_GRP_SUSPENDED; + else + dqopt->flags &= ~DQUOT_GRP_SUSPENDED; break; } } + /* * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount) */ -int vfs_quota_off(struct super_block *sb, int type) +int vfs_quota_off(struct super_block *sb, int type, int remount) { - int cnt; + int cnt, ret = 0; struct quota_info *dqopt = sb_dqopt(sb); struct inode *toputinode[MAXQUOTAS]; @@ -1475,9 +1495,17 @@ int vfs_quota_off(struct super_block *sb, int type) toputinode[cnt] = NULL; if (type != -1 && cnt != type) continue; + /* If we keep inodes of quota files after remount and quotaoff + * is called, drop kept inodes. */ + if (!remount && sb_has_quota_suspended(sb, cnt)) { + iput(dqopt->files[cnt]); + dqopt->files[cnt] = NULL; + reset_enable_flags(dqopt, cnt, 0); + continue; + } if (!sb_has_quota_enabled(sb, cnt)) continue; - reset_enable_flags(dqopt, cnt); + reset_enable_flags(dqopt, cnt, remount); /* Note: these are blocking operations */ drop_dquot_ref(sb, cnt); @@ -1493,7 +1521,8 @@ int vfs_quota_off(struct super_block *sb, int type) put_quota_format(dqopt->info[cnt].dqi_format); toputinode[cnt] = dqopt->files[cnt]; - dqopt->files[cnt] = NULL; + if (!remount) + dqopt->files[cnt] = NULL; dqopt->info[cnt].dqi_flags = 0; dqopt->info[cnt].dqi_igrace = 0; dqopt->info[cnt].dqi_bgrace = 0; @@ -1523,12 +1552,19 @@ int vfs_quota_off(struct super_block *sb, int type) mutex_unlock(&toputinode[cnt]->i_mutex); mark_inode_dirty(toputinode[cnt]); } - iput(toputinode[cnt]); mutex_unlock(&dqopt->dqonoff_mutex); + /* On remount RO, we keep the inode pointer so that we + * can reenable quota on the subsequent remount RW. + * But we have better not keep inode pointer when there + * is pending delete on the quota file... */ + if (!remount) + iput(toputinode[cnt]); + else if (!toputinode[cnt]->i_nlink) + ret = -EBUSY; } if (sb->s_bdev) invalidate_bdev(sb->s_bdev); - return 0; + return ret; } /* @@ -1566,7 +1602,8 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) invalidate_bdev(sb->s_bdev); mutex_lock(&inode->i_mutex); mutex_lock(&dqopt->dqonoff_mutex); - if (sb_has_quota_enabled(sb, type)) { + if (sb_has_quota_enabled(sb, type) || + sb_has_quota_suspended(sb, type)) { error = -EBUSY; goto out_lock; } @@ -1589,6 +1626,7 @@ static int vfs_quota_on_inode(struct inode *inode, int type, int format_id) dqopt->ops[type] = fmt->qf_ops; dqopt->info[type].dqi_format = fmt; + dqopt->info[type].dqi_fmt_id = format_id; INIT_LIST_HEAD(&dqopt->info[type].dqi_dirty_list); mutex_lock(&dqopt->dqio_mutex); if ((error = dqopt->ops[type]->read_file_info(sb, type)) < 0) { @@ -1624,12 +1662,41 @@ out_fmt: return error; } +/* Reenable quotas on remount RW */ +static int vfs_quota_on_remount(struct super_block *sb, int type) +{ + struct quota_info *dqopt = sb_dqopt(sb); + struct inode *inode; + int ret; + + mutex_lock(&dqopt->dqonoff_mutex); + if (!sb_has_quota_suspended(sb, type)) { + mutex_unlock(&dqopt->dqonoff_mutex); + return 0; + } + BUG_ON(sb_has_quota_enabled(sb, type)); + + inode = dqopt->files[type]; + dqopt->files[type] = NULL; + reset_enable_flags(dqopt, type, 0); + mutex_unlock(&dqopt->dqonoff_mutex); + + ret = vfs_quota_on_inode(inode, type, dqopt->info[type].dqi_fmt_id); + iput(inode); + + return ret; +} + /* Actual function called from quotactl() */ -int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path) +int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path, + int remount) { struct nameidata nd; int error; + if (remount) + return vfs_quota_on_remount(sb, type); + error = path_lookup(path, LOOKUP_FOLLOW, &nd); if (error < 0) return error; @@ -1709,10 +1776,19 @@ int vfs_get_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *d } /* Generic routine for setting common part of quota structure */ -static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) +static int do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) { struct mem_dqblk *dm = &dquot->dq_dqb; int check_blim = 0, check_ilim = 0; + struct mem_dqinfo *dqi = &sb_dqopt(dquot->dq_sb)->info[dquot->dq_type]; + + if ((di->dqb_valid & QIF_BLIMITS && + (di->dqb_bhardlimit > dqi->dqi_maxblimit || + di->dqb_bsoftlimit > dqi->dqi_maxblimit)) || + (di->dqb_valid & QIF_ILIMITS && + (di->dqb_ihardlimit > dqi->dqi_maxilimit || + di->dqb_isoftlimit > dqi->dqi_maxilimit))) + return -ERANGE; spin_lock(&dq_data_lock); if (di->dqb_valid & QIF_SPACE) { @@ -1744,7 +1820,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) clear_bit(DQ_BLKS_B, &dquot->dq_flags); } else if (!(di->dqb_valid & QIF_BTIME)) /* Set grace only if user hasn't provided his own... */ - dm->dqb_btime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_bgrace; + dm->dqb_btime = get_seconds() + dqi->dqi_bgrace; } if (check_ilim) { if (!dm->dqb_isoftlimit || dm->dqb_curinodes < dm->dqb_isoftlimit) { @@ -1752,7 +1828,7 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) clear_bit(DQ_INODES_B, &dquot->dq_flags); } else if (!(di->dqb_valid & QIF_ITIME)) /* Set grace only if user hasn't provided his own... */ - dm->dqb_itime = get_seconds() + sb_dqopt(dquot->dq_sb)->info[dquot->dq_type].dqi_igrace; + dm->dqb_itime = get_seconds() + dqi->dqi_igrace; } if (dm->dqb_bhardlimit || dm->dqb_bsoftlimit || dm->dqb_ihardlimit || dm->dqb_isoftlimit) clear_bit(DQ_FAKE_B, &dquot->dq_flags); @@ -1760,21 +1836,24 @@ static void do_set_dqblk(struct dquot *dquot, struct if_dqblk *di) set_bit(DQ_FAKE_B, &dquot->dq_flags); spin_unlock(&dq_data_lock); mark_dquot_dirty(dquot); + + return 0; } int vfs_set_dqblk(struct super_block *sb, int type, qid_t id, struct if_dqblk *di) { struct dquot *dquot; + int rc; mutex_lock(&sb_dqopt(sb)->dqonoff_mutex); if (!(dquot = dqget(sb, id, type))) { mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); return -ESRCH; } - do_set_dqblk(dquot, di); + rc = do_set_dqblk(dquot, di); dqput(dquot); mutex_unlock(&sb_dqopt(sb)->dqonoff_mutex); - return 0; + return rc; } /* Generic routine for getting common part of quota file information */ diff --git a/fs/ext2/balloc.c b/fs/ext2/balloc.c index e7b2baf..10bb02c 100644 --- a/fs/ext2/balloc.c +++ b/fs/ext2/balloc.c @@ -106,7 +106,7 @@ static int ext2_valid_block_bitmap(struct super_block *sb, return 1; err_out: - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "Invalid block bitmap - " "block_group = %d, block = %lu", block_group, bitmap_blk); @@ -132,7 +132,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); bh = sb_getblk(sb, bitmap_blk); if (unlikely(!bh)) { - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); @@ -143,17 +143,18 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) if (bh_submit_read(bh) < 0) { brelse(bh); - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); return NULL; } - if (!ext2_valid_block_bitmap(sb, desc, block_group, bh)) { - brelse(bh); - return NULL; - } + ext2_valid_block_bitmap(sb, desc, block_group, bh); + /* + * file system mounted not to panic on error, continue with corrupt + * bitmap + */ return bh; } @@ -245,11 +246,10 @@ restart: prev = rsv; } printk("Window map complete.\n"); - if (bad) - BUG(); + BUG_ON(bad); } #define rsv_window_dump(root, verbose) \ - __rsv_window_dump((root), (verbose), __FUNCTION__) + __rsv_window_dump((root), (verbose), __func__) #else #define rsv_window_dump(root, verbose) do {} while (0) #endif @@ -548,7 +548,7 @@ do_more: for (i = 0, group_freed = 0; i < count; i++) { if (!ext2_clear_bit_atomic(sb_bgl_lock(sbi, block_group), bit + i, bitmap_bh->b_data)) { - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "bit already cleared for block %lu", block + i); } else { group_freed++; @@ -1381,7 +1381,12 @@ allocated: "Allocating block in system zone - " "blocks from "E2FSBLK", length %lu", ret_block, num); - goto out; + /* + * ext2_try_to_allocate marked the blocks we allocated as in + * use. So we may want to selectively mark some of the blocks + * as free + */ + goto retry_alloc; } performed_allocation = 1; diff --git a/fs/ext2/dir.c b/fs/ext2/dir.c index 8dededd..a78c6b4 100644 --- a/fs/ext2/dir.c +++ b/fs/ext2/dir.c @@ -41,8 +41,8 @@ static inline __le16 ext2_rec_len_to_disk(unsigned len) { if (len == (1 << 16)) return cpu_to_le16(EXT2_MAX_REC_LEN); - else if (len > (1 << 16)) - BUG(); + else + BUG_ON(len > (1 << 16)); return cpu_to_le16(len); } @@ -295,11 +295,11 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) struct page *page = ext2_get_page(inode, n); if (IS_ERR(page)) { - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "bad page in #%lu", inode->i_ino); filp->f_pos += PAGE_CACHE_SIZE - offset; - return -EIO; + return PTR_ERR(page); } kaddr = page_address(page); if (unlikely(need_revalidate)) { @@ -314,7 +314,7 @@ ext2_readdir (struct file * filp, void * dirent, filldir_t filldir) limit = kaddr + ext2_last_byte(inode, n) - EXT2_DIR_REC_LEN(1); for ( ;(char*)de <= limit; de = ext2_next_entry(de)) { if (de->rec_len == 0) { - ext2_error(sb, __FUNCTION__, + ext2_error(sb, __func__, "zero-length directory entry"); ext2_put_page(page); return -EIO; @@ -381,7 +381,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, kaddr += ext2_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) { if (de->rec_len == 0) { - ext2_error(dir->i_sb, __FUNCTION__, + ext2_error(dir->i_sb, __func__, "zero-length directory entry"); ext2_put_page(page); goto out; @@ -396,7 +396,7 @@ struct ext2_dir_entry_2 * ext2_find_entry (struct inode * dir, n = 0; /* next page is past the blocks we've got */ if (unlikely(n > (dir->i_blocks >> (PAGE_CACHE_SHIFT - 9)))) { - ext2_error(dir->i_sb, __FUNCTION__, + ext2_error(dir->i_sb, __func__, "dir %lu size %lld exceeds block count %llu", dir->i_ino, dir->i_size, (unsigned long long)dir->i_blocks); @@ -506,7 +506,7 @@ int ext2_add_link (struct dentry *dentry, struct inode *inode) goto got_it; } if (de->rec_len == 0) { - ext2_error(dir->i_sb, __FUNCTION__, + ext2_error(dir->i_sb, __func__, "zero-length directory entry"); err = -EIO; goto out_unlock; @@ -578,7 +578,7 @@ int ext2_delete_entry (struct ext2_dir_entry_2 * dir, struct page * page ) while ((char*)de < (char*)dir) { if (de->rec_len == 0) { - ext2_error(inode->i_sb, __FUNCTION__, + ext2_error(inode->i_sb, __func__, "zero-length directory entry"); err = -EIO; goto out; @@ -670,7 +670,7 @@ int ext2_empty_dir (struct inode * inode) while ((char *)de <= kaddr) { if (de->rec_len == 0) { - ext2_error(inode->i_sb, __FUNCTION__, + ext2_error(inode->i_sb, __func__, "zero-length directory entry"); printk("kaddr=%p, de=%p\n", kaddr, de); goto not_empty; diff --git a/fs/ext2/ialloc.c b/fs/ext2/ialloc.c index 08f647d..f597413 100644 --- a/fs/ext2/ialloc.c +++ b/fs/ext2/ialloc.c @@ -75,11 +75,9 @@ static void ext2_release_inode(struct super_block *sb, int group, int dir) } spin_lock(sb_bgl_lock(EXT2_SB(sb), group)); - desc->bg_free_inodes_count = - cpu_to_le16(le16_to_cpu(desc->bg_free_inodes_count) + 1); + le16_add_cpu(&desc->bg_free_inodes_count, 1); if (dir) - desc->bg_used_dirs_count = - cpu_to_le16(le16_to_cpu(desc->bg_used_dirs_count) - 1); + le16_add_cpu(&desc->bg_used_dirs_count, -1); spin_unlock(sb_bgl_lock(EXT2_SB(sb), group)); if (dir) percpu_counter_dec(&EXT2_SB(sb)->s_dirs_counter); @@ -539,13 +537,11 @@ got: percpu_counter_inc(&sbi->s_dirs_counter); spin_lock(sb_bgl_lock(sbi, group)); - gdp->bg_free_inodes_count = - cpu_to_le16(le16_to_cpu(gdp->bg_free_inodes_count) - 1); + le16_add_cpu(&gdp->bg_free_inodes_count, -1); if (S_ISDIR(mode)) { if (sbi->s_debts[group] < 255) sbi->s_debts[group]++; - gdp->bg_used_dirs_count = - cpu_to_le16(le16_to_cpu(gdp->bg_used_dirs_count) + 1); + le16_add_cpu(&gdp->bg_used_dirs_count, 1); } else { if (sbi->s_debts[group]) sbi->s_debts[group]--; diff --git a/fs/ext2/inode.c b/fs/ext2/inode.c index b8a2990..384fc0d 100644 --- a/fs/ext2/inode.c +++ b/fs/ext2/inode.c @@ -254,13 +254,13 @@ no_block: * Caller must make sure that @ind is valid and will stay that way. */ -static unsigned long ext2_find_near(struct inode *inode, Indirect *ind) +static ext2_fsblk_t ext2_find_near(struct inode *inode, Indirect *ind) { struct ext2_inode_info *ei = EXT2_I(inode); __le32 *start = ind->bh ? (__le32 *) ind->bh->b_data : ei->i_data; __le32 *p; - unsigned long bg_start; - unsigned long colour; + ext2_fsblk_t bg_start; + ext2_fsblk_t colour; /* Try to find previous block */ for (p = ind->p - 1; p >= start; p--) @@ -275,8 +275,7 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind) * It is going to be refered from inode itself? OK, just put it into * the same cylinder group then. */ - bg_start = (ei->i_block_group * EXT2_BLOCKS_PER_GROUP(inode->i_sb)) + - le32_to_cpu(EXT2_SB(inode->i_sb)->s_es->s_first_data_block); + bg_start = ext2_group_first_block_no(inode->i_sb, ei->i_block_group); colour = (current->pid % 16) * (EXT2_BLOCKS_PER_GROUP(inode->i_sb) / 16); return bg_start + colour; @@ -291,8 +290,8 @@ static unsigned long ext2_find_near(struct inode *inode, Indirect *ind) * Returns preferred place for a block (the goal). */ -static inline int ext2_find_goal(struct inode *inode, long block, - Indirect *partial) +static inline ext2_fsblk_t ext2_find_goal(struct inode *inode, long block, + Indirect *partial) { struct ext2_block_alloc_info *block_i; @@ -796,7 +795,7 @@ const struct address_space_operations ext2_aops = { const struct address_space_operations ext2_aops_xip = { .bmap = ext2_bmap, - .get_xip_page = ext2_get_xip_page, + .get_xip_mem = ext2_get_xip_mem, }; const struct address_space_operations ext2_nobh_aops = { diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 088b011..ef50cbc 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -51,8 +51,7 @@ void ext2_error (struct super_block * sb, const char * function, if (!(sb->s_flags & MS_RDONLY)) { sbi->s_mount_state |= EXT2_ERROR_FS; - es->s_state = - cpu_to_le16(le16_to_cpu(es->s_state) | EXT2_ERROR_FS); + es->s_state |= cpu_to_le16(EXT2_ERROR_FS); ext2_sync_super(sb, es); } @@ -90,7 +89,7 @@ void ext2_update_dynamic_rev(struct super_block *sb) if (le32_to_cpu(es->s_rev_level) > EXT2_GOOD_OLD_REV) return; - ext2_warning(sb, __FUNCTION__, + ext2_warning(sb, __func__, "updating to rev %d because of new feature flag, " "running e2fsck is recommended", EXT2_DYNAMIC_REV); @@ -604,7 +603,7 @@ static int ext2_setup_super (struct super_block * sb, "running e2fsck is recommended\n"); if (!le16_to_cpu(es->s_max_mnt_count)) es->s_max_mnt_count = cpu_to_le16(EXT2_DFL_MAX_MNT_COUNT); - es->s_mnt_count=cpu_to_le16(le16_to_cpu(es->s_mnt_count) + 1); + le16_add_cpu(&es->s_mnt_count, 1); ext2_write_super(sb); if (test_opt (sb, DEBUG)) printk ("[EXT II FS %s, %s, bs=%lu, fs=%lu, gc=%lu, " @@ -622,13 +621,13 @@ static int ext2_check_descriptors(struct super_block *sb) { int i; struct ext2_sb_info *sbi = EXT2_SB(sb); - unsigned long first_block = le32_to_cpu(sbi->s_es->s_first_data_block); - unsigned long last_block; ext2_debug ("Checking group descriptors"); for (i = 0; i < sbi->s_groups_count; i++) { struct ext2_group_desc *gdp = ext2_get_group_desc(sb, i, NULL); + ext2_fsblk_t first_block = ext2_group_first_block_no(sb, i); + ext2_fsblk_t last_block; if (i == sbi->s_groups_count - 1) last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1; @@ -664,7 +663,6 @@ static int ext2_check_descriptors(struct super_block *sb) i, (unsigned long) le32_to_cpu(gdp->bg_inode_table)); return 0; } - first_block += EXT2_BLOCKS_PER_GROUP(sb); } return 1; } @@ -721,10 +719,9 @@ static unsigned long descriptor_loc(struct super_block *sb, int nr) { struct ext2_sb_info *sbi = EXT2_SB(sb); - unsigned long bg, first_data_block, first_meta_bg; + unsigned long bg, first_meta_bg; int has_super = 0; - first_data_block = le32_to_cpu(sbi->s_es->s_first_data_block); first_meta_bg = le32_to_cpu(sbi->s_es->s_first_meta_bg); if (!EXT2_HAS_INCOMPAT_FEATURE(sb, EXT2_FEATURE_INCOMPAT_META_BG) || @@ -733,7 +730,8 @@ static unsigned long descriptor_loc(struct super_block *sb, bg = sbi->s_desc_per_block * nr; if (ext2_bg_has_super(sb, bg)) has_super = 1; - return (first_data_block + has_super + (bg * sbi->s_blocks_per_group)); + + return ext2_group_first_block_no(sb, bg) + has_super; } static int ext2_fill_super(struct super_block *sb, void *data, int silent) @@ -1062,7 +1060,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) goto failed_mount3; } if (EXT2_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_HAS_JOURNAL)) - ext2_warning(sb, __FUNCTION__, + ext2_warning(sb, __func__, "mounting ext3 filesystem as ext2"); ext2_setup_super (sb, es, sb->s_flags & MS_RDONLY); return 0; @@ -1126,10 +1124,9 @@ void ext2_write_super (struct super_block * sb) if (!(sb->s_flags & MS_RDONLY)) { es = EXT2_SB(sb)->s_es; - if (le16_to_cpu(es->s_state) & EXT2_VALID_FS) { + if (es->s_state & cpu_to_le16(EXT2_VALID_FS)) { ext2_debug ("setting valid to 0\n"); - es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & - ~EXT2_VALID_FS); + es->s_state &= cpu_to_le16(~EXT2_VALID_FS); es->s_free_blocks_count = cpu_to_le32(ext2_count_free_blocks(sb)); es->s_free_inodes_count = cpu_to_le32(ext2_count_free_inodes(sb)); es->s_mtime = cpu_to_le32(get_seconds()); @@ -1180,7 +1177,7 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) if (((sbi->s_mount_opt & EXT2_MOUNT_XIP) != (old_mount_opt & EXT2_MOUNT_XIP)) && invalidate_inodes(sb)) - ext2_warning(sb, __FUNCTION__, "busy inodes while remounting "\ + ext2_warning(sb, __func__, "busy inodes while remounting "\ "xip remain in cache (no functional problem)"); if ((*flags & MS_RDONLY) == (sb->s_flags & MS_RDONLY)) return 0; diff --git a/fs/ext2/xattr.c b/fs/ext2/xattr.c index a99d46f..987a526 100644 --- a/fs/ext2/xattr.c +++ b/fs/ext2/xattr.c @@ -646,8 +646,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, unlock_buffer(new_bh); goto cleanup; } - HDR(new_bh)->h_refcount = cpu_to_le32(1 + - le32_to_cpu(HDR(new_bh)->h_refcount)); + le32_add_cpu(&HDR(new_bh)->h_refcount, 1); ea_bdebug(new_bh, "refcount now=%d", le32_to_cpu(HDR(new_bh)->h_refcount)); } @@ -660,10 +659,8 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, ext2_xattr_cache_insert(new_bh); } else { /* We need to allocate a new block */ - int goal = le32_to_cpu(EXT2_SB(sb)->s_es-> - s_first_data_block) + - EXT2_I(inode)->i_block_group * - EXT2_BLOCKS_PER_GROUP(sb); + ext2_fsblk_t goal = ext2_group_first_block_no(sb, + EXT2_I(inode)->i_block_group); int block = ext2_new_block(inode, goal, &error); if (error) goto cleanup; @@ -731,8 +728,7 @@ ext2_xattr_set2(struct inode *inode, struct buffer_head *old_bh, bforget(old_bh); } else { /* Decrement the refcount only. */ - HDR(old_bh)->h_refcount = cpu_to_le32( - le32_to_cpu(HDR(old_bh)->h_refcount) - 1); + le32_add_cpu(&HDR(old_bh)->h_refcount, -1); if (ce) mb_cache_entry_release(ce); DQUOT_FREE_BLOCK(inode, 1); @@ -789,8 +785,7 @@ ext2_xattr_delete_inode(struct inode *inode) bforget(bh); unlock_buffer(bh); } else { - HDR(bh)->h_refcount = cpu_to_le32( - le32_to_cpu(HDR(bh)->h_refcount) - 1); + le32_add_cpu(&HDR(bh)->h_refcount, -1); if (ce) mb_cache_entry_release(ce); ea_bdebug(bh, "refcount now=%d", diff --git a/fs/ext2/xip.c b/fs/ext2/xip.c index ca7f003..4fb94c2 100644 --- a/fs/ext2/xip.c +++ b/fs/ext2/xip.c @@ -15,24 +15,28 @@ #include "xip.h" static inline int -__inode_direct_access(struct inode *inode, sector_t sector, - unsigned long *data) +__inode_direct_access(struct inode *inode, sector_t block, + void **kaddr, unsigned long *pfn) { - BUG_ON(!inode->i_sb->s_bdev->bd_disk->fops->direct_access); - return inode->i_sb->s_bdev->bd_disk->fops - ->direct_access(inode->i_sb->s_bdev,sector,data); + struct block_device *bdev = inode->i_sb->s_bdev; + struct block_device_operations *ops = bdev->bd_disk->fops; + sector_t sector; + + sector = block * (PAGE_SIZE / 512); /* ext2 block to bdev sector */ + + BUG_ON(!ops->direct_access); + return ops->direct_access(bdev, sector, kaddr, pfn); } static inline int -__ext2_get_sector(struct inode *inode, sector_t offset, int create, +__ext2_get_block(struct inode *inode, pgoff_t pgoff, int create, sector_t *result) { struct buffer_head tmp; int rc; memset(&tmp, 0, sizeof(struct buffer_head)); - rc = ext2_get_block(inode, offset/ (PAGE_SIZE/512), &tmp, - create); + rc = ext2_get_block(inode, pgoff, &tmp, create); *result = tmp.b_blocknr; /* did we get a sparse block (hole in the file)? */ @@ -45,15 +49,15 @@ __ext2_get_sector(struct inode *inode, sector_t offset, int create, } int -ext2_clear_xip_target(struct inode *inode, int block) +ext2_clear_xip_target(struct inode *inode, sector_t block) { - sector_t sector = block * (PAGE_SIZE/512); - unsigned long data; + void *kaddr; + unsigned long pfn; int rc; - rc = __inode_direct_access(inode, sector, &data); + rc = __inode_direct_access(inode, block, &kaddr, &pfn); if (!rc) - clear_page((void*)data); + clear_page(kaddr); return rc; } @@ -64,30 +68,23 @@ void ext2_xip_verify_sb(struct super_block *sb) if ((sbi->s_mount_opt & EXT2_MOUNT_XIP) && !sb->s_bdev->bd_disk->fops->direct_access) { sbi->s_mount_opt &= (~EXT2_MOUNT_XIP); - ext2_warning(sb, __FUNCTION__, + ext2_warning(sb, __func__, "ignoring xip option - not supported by bdev"); } } -struct page * -ext2_get_xip_page(struct address_space *mapping, sector_t offset, - int create) +int ext2_get_xip_mem(struct address_space *mapping, pgoff_t pgoff, int create, + void **kmem, unsigned long *pfn) { int rc; - unsigned long data; - sector_t sector; + sector_t block; /* first, retrieve the sector number */ - rc = __ext2_get_sector(mapping->host, offset, create, §or); + rc = __ext2_get_block(mapping->host, pgoff, create, &block); if (rc) - goto error; + return rc; /* retrieve address of the target data */ - rc = __inode_direct_access - (mapping->host, sector * (PAGE_SIZE/512), &data); - if (!rc) - return virt_to_page(data); - - error: - return ERR_PTR(rc); + rc = __inode_direct_access(mapping->host, block, kmem, pfn); + return rc; } diff --git a/fs/ext2/xip.h b/fs/ext2/xip.h index aa85331..18b34d2 100644 --- a/fs/ext2/xip.h +++ b/fs/ext2/xip.h @@ -7,19 +7,20 @@ #ifdef CONFIG_EXT2_FS_XIP extern void ext2_xip_verify_sb (struct super_block *); -extern int ext2_clear_xip_target (struct inode *, int); +extern int ext2_clear_xip_target (struct inode *, sector_t); static inline int ext2_use_xip (struct super_block *sb) { struct ext2_sb_info *sbi = EXT2_SB(sb); return (sbi->s_mount_opt & EXT2_MOUNT_XIP); } -struct page* ext2_get_xip_page (struct address_space *, sector_t, int); -#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_page) +int ext2_get_xip_mem(struct address_space *, pgoff_t, int, + void **, unsigned long *); +#define mapping_is_xip(map) unlikely(map->a_ops->get_xip_mem) #else #define mapping_is_xip(map) 0 #define ext2_xip_verify_sb(sb) do { } while (0) #define ext2_use_xip(sb) 0 #define ext2_clear_xip_target(inode, chain) 0 -#define ext2_get_xip_page NULL +#define ext2_get_xip_mem NULL #endif diff --git a/fs/ext3/balloc.c b/fs/ext3/balloc.c index da0cb2c..92fd033 100644 --- a/fs/ext3/balloc.c +++ b/fs/ext3/balloc.c @@ -117,7 +117,7 @@ static int ext3_valid_block_bitmap(struct super_block *sb, return 1; err_out: - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "Invalid block bitmap - " "block_group = %d, block = %lu", block_group, bitmap_blk); @@ -147,7 +147,7 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) bitmap_blk = le32_to_cpu(desc->bg_block_bitmap); bh = sb_getblk(sb, bitmap_blk); if (unlikely(!bh)) { - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); @@ -158,16 +158,17 @@ read_block_bitmap(struct super_block *sb, unsigned int block_group) if (bh_submit_read(bh) < 0) { brelse(bh); - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "Cannot read block bitmap - " "block_group = %d, block_bitmap = %u", block_group, le32_to_cpu(desc->bg_block_bitmap)); return NULL; } - if (!ext3_valid_block_bitmap(sb, desc, block_group, bh)) { - brelse(bh); - return NULL; - } + ext3_valid_block_bitmap(sb, desc, block_group, bh); + /* + * file system mounted not to panic on error, continue with corrupt + * bitmap + */ return bh; } /* @@ -232,11 +233,10 @@ restart: prev = rsv; } printk("Window map complete.\n"); - if (bad) - BUG(); + BUG_ON(bad); } #define rsv_window_dump(root, verbose) \ - __rsv_window_dump((root), (verbose), __FUNCTION__) + __rsv_window_dump((root), (verbose), __func__) #else #define rsv_window_dump(root, verbose) do {} while (0) #endif @@ -618,7 +618,7 @@ do_more: if (!ext3_clear_bit_atomic(sb_bgl_lock(sbi, block_group), bit + i, bitmap_bh->b_data)) { jbd_unlock_bh_state(bitmap_bh); - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "bit already cleared for block "E3FSBLK, block + i); jbd_lock_bh_state(bitmap_bh); @@ -1642,7 +1642,11 @@ allocated: "Allocating block in system zone - " "blocks from "E3FSBLK", length %lu", ret_block, num); - goto out; + /* + * claim_block() marked the blocks we allocated as in use. So we + * may want to selectively mark some of the blocks as free. + */ + goto retry_alloc; } performed_allocation = 1; @@ -1668,7 +1672,7 @@ allocated: if (ext3_test_bit(grp_alloc_blk+i, bh2jh(bitmap_bh)->b_committed_data)) { printk("%s: block was unexpectedly set in " - "b_committed_data\n", __FUNCTION__); + "b_committed_data\n", __func__); } } } diff --git a/fs/ext3/ext3_jbd.c b/fs/ext3/ext3_jbd.c index e1f91fd..d401f14 100644 --- a/fs/ext3/ext3_jbd.c +++ b/fs/ext3/ext3_jbd.c @@ -9,7 +9,7 @@ int __ext3_journal_get_undo_access(const char *where, handle_t *handle, { int err = journal_get_undo_access(handle, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } @@ -18,7 +18,7 @@ int __ext3_journal_get_write_access(const char *where, handle_t *handle, { int err = journal_get_write_access(handle, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } @@ -27,7 +27,7 @@ int __ext3_journal_forget(const char *where, handle_t *handle, { int err = journal_forget(handle, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } @@ -36,7 +36,7 @@ int __ext3_journal_revoke(const char *where, handle_t *handle, { int err = journal_revoke(handle, blocknr, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } @@ -45,7 +45,7 @@ int __ext3_journal_get_create_access(const char *where, { int err = journal_get_create_access(handle, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } @@ -54,6 +54,6 @@ int __ext3_journal_dirty_metadata(const char *where, { int err = journal_dirty_metadata(handle, bh); if (err) - ext3_journal_abort_handle(where, __FUNCTION__, bh, handle,err); + ext3_journal_abort_handle(where, __func__, bh, handle,err); return err; } diff --git a/fs/ext3/fsync.c b/fs/ext3/fsync.c index a588e23..d336341 100644 --- a/fs/ext3/fsync.c +++ b/fs/ext3/fsync.c @@ -72,6 +72,9 @@ int ext3_sync_file(struct file * file, struct dentry *dentry, int datasync) goto out; } + if (datasync && !(inode->i_state & I_DIRTY_DATASYNC)) + goto out; + /* * The VFS has written the file data. If the inode is unaltered * then we need not start a commit. diff --git a/fs/ext3/ialloc.c b/fs/ext3/ialloc.c index 96dd557..7712682 100644 --- a/fs/ext3/ialloc.c +++ b/fs/ext3/ialloc.c @@ -644,7 +644,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) /* Error cases - e2fsck has already cleaned up for us */ if (ino > max_ino) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "bad orphan ino %lu! e2fsck was run?", ino); goto error; } @@ -653,7 +653,7 @@ struct inode *ext3_orphan_get(struct super_block *sb, unsigned long ino) bit = (ino - 1) % EXT3_INODES_PER_GROUP(sb); bitmap_bh = read_inode_bitmap(sb, block_group); if (!bitmap_bh) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "inode bitmap error for orphan %lu", ino); goto error; } @@ -678,7 +678,7 @@ iget_failed: err = PTR_ERR(inode); inode = NULL; bad_orphan: - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "bad orphan inode %lu! e2fsck was run?", ino); printk(KERN_NOTICE "ext3_test_bit(bit=%d, block=%llu) = %d\n", bit, (unsigned long long)bitmap_bh->b_blocknr, diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index c683609..cc47b76 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -95,7 +95,7 @@ int ext3_forget(handle_t *handle, int is_metadata, struct inode *inode, BUFFER_TRACE(bh, "call ext3_journal_revoke"); err = ext3_journal_revoke(handle, blocknr, bh); if (err) - ext3_abort(inode->i_sb, __FUNCTION__, + ext3_abort(inode->i_sb, __func__, "error %d when attempting revoke", err); BUFFER_TRACE(bh, "exit"); return err; @@ -1190,7 +1190,7 @@ int ext3_journal_dirty_data(handle_t *handle, struct buffer_head *bh) { int err = journal_dirty_data(handle, bh); if (err) - ext3_journal_abort_handle(__FUNCTION__, __FUNCTION__, + ext3_journal_abort_handle(__func__, __func__, bh, handle, err); return err; } @@ -2454,11 +2454,10 @@ out_stop: static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb, unsigned long ino, struct ext3_iloc *iloc) { - unsigned long desc, group_desc, block_group; + unsigned long block_group; unsigned long offset; ext3_fsblk_t block; - struct buffer_head *bh; - struct ext3_group_desc * gdp; + struct ext3_group_desc *gdp; if (!ext3_valid_inum(sb, ino)) { /* @@ -2470,27 +2469,15 @@ static ext3_fsblk_t ext3_get_inode_block(struct super_block *sb, } block_group = (ino - 1) / EXT3_INODES_PER_GROUP(sb); - if (block_group >= EXT3_SB(sb)->s_groups_count) { - ext3_error(sb,"ext3_get_inode_block","group >= groups count"); - return 0; - } - smp_rmb(); - group_desc = block_group >> EXT3_DESC_PER_BLOCK_BITS(sb); - desc = block_group & (EXT3_DESC_PER_BLOCK(sb) - 1); - bh = EXT3_SB(sb)->s_group_desc[group_desc]; - if (!bh) { - ext3_error (sb, "ext3_get_inode_block", - "Descriptor not loaded"); + gdp = ext3_get_group_desc(sb, block_group, NULL); + if (!gdp) return 0; - } - - gdp = (struct ext3_group_desc *)bh->b_data; /* * Figure out the offset within the block group inode table */ offset = ((ino - 1) % EXT3_INODES_PER_GROUP(sb)) * EXT3_INODE_SIZE(sb); - block = le32_to_cpu(gdp[desc].bg_inode_table) + + block = le32_to_cpu(gdp->bg_inode_table) + (offset >> EXT3_BLOCK_SIZE_BITS(sb)); iloc->block_group = block_group; @@ -3214,7 +3201,7 @@ void ext3_dirty_inode(struct inode *inode) current_handle->h_transaction != handle->h_transaction) { /* This task has a transaction open against a different fs */ printk(KERN_EMERG "%s: transactions do not match!\n", - __FUNCTION__); + __func__); } else { jbd_debug(5, "marking dirty. outer handle=%p\n", current_handle); diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index dec3e0d..0b8cf80 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -57,10 +57,15 @@ static struct buffer_head *ext3_append(handle_t *handle, *block = inode->i_size >> inode->i_sb->s_blocksize_bits; - if ((bh = ext3_bread(handle, inode, *block, 1, err))) { + bh = ext3_bread(handle, inode, *block, 1, err); + if (bh) { inode->i_size += inode->i_sb->s_blocksize; EXT3_I(inode)->i_disksize = inode->i_size; - ext3_journal_get_write_access(handle,bh); + *err = ext3_journal_get_write_access(handle, bh); + if (*err) { + brelse(bh); + bh = NULL; + } } return bh; } @@ -356,7 +361,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (root->info.hash_version != DX_HASH_TEA && root->info.hash_version != DX_HASH_HALF_MD4 && root->info.hash_version != DX_HASH_LEGACY) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "Unrecognised inode hash code %d", root->info.hash_version); brelse(bh); @@ -370,7 +375,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, hash = hinfo->hash; if (root->info.unused_flags & 1) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "Unimplemented inode hash flags: %#06x", root->info.unused_flags); brelse(bh); @@ -379,7 +384,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, } if ((indirect = root->info.indirect_levels) > 1) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "Unimplemented inode hash depth: %#06x", root->info.indirect_levels); brelse(bh); @@ -392,7 +397,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, if (dx_get_limit(entries) != dx_root_limit(dir, root->info.info_length)) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "dx entry: limit != root limit"); brelse(bh); *err = ERR_BAD_DX_DIR; @@ -404,7 +409,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, { count = dx_get_count(entries); if (!count || count > dx_get_limit(entries)) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "dx entry: no count or count > limit"); brelse(bh); *err = ERR_BAD_DX_DIR; @@ -449,7 +454,7 @@ dx_probe(struct dentry *dentry, struct inode *dir, goto fail2; at = entries = ((struct dx_node *) bh->b_data)->entries; if (dx_get_limit(entries) != dx_node_limit (dir)) { - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "dx entry: limit != node limit"); brelse(bh); *err = ERR_BAD_DX_DIR; @@ -465,7 +470,7 @@ fail2: } fail: if (*err == ERR_BAD_DX_DIR) - ext3_warning(dir->i_sb, __FUNCTION__, + ext3_warning(dir->i_sb, __func__, "Corrupt dir inode %ld, running e2fsck is " "recommended.", dir->i_ino); return NULL; @@ -913,7 +918,7 @@ restart: wait_on_buffer(bh); if (!buffer_uptodate(bh)) { /* read error, skip block & hope for the best */ - ext3_error(sb, __FUNCTION__, "reading directory #%lu " + ext3_error(sb, __func__, "reading directory #%lu " "offset %lu", dir->i_ino, block); brelse(bh); goto next; @@ -1005,7 +1010,7 @@ static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, retval = ext3_htree_next_block(dir, hash, frame, frames, NULL); if (retval < 0) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "error reading index page in directory #%lu", dir->i_ino); *err = retval; @@ -1530,7 +1535,7 @@ static int ext3_dx_add_entry(handle_t *handle, struct dentry *dentry, if (levels && (dx_get_count(frames->entries) == dx_get_limit(frames->entries))) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Directory index full!"); err = -ENOSPC; goto cleanup; @@ -1832,11 +1837,11 @@ static int empty_dir (struct inode * inode) if (inode->i_size < EXT3_DIR_REC_LEN(1) + EXT3_DIR_REC_LEN(2) || !(bh = ext3_bread (NULL, inode, 0, 0, &err))) { if (err) - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "error %d reading directory #%lu offset 0", err, inode->i_ino); else - ext3_warning(inode->i_sb, __FUNCTION__, + ext3_warning(inode->i_sb, __func__, "bad directory (dir #%lu) - no data block", inode->i_ino); return 1; @@ -1865,7 +1870,7 @@ static int empty_dir (struct inode * inode) offset >> EXT3_BLOCK_SIZE_BITS(sb), 0, &err); if (!bh) { if (err) - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "error %d reading directory" " #%lu offset %lu", err, inode->i_ino, offset); @@ -2318,6 +2323,8 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, EXT3_FEATURE_INCOMPAT_FILETYPE)) new_de->file_type = old_de->file_type; new_dir->i_version++; + new_dir->i_ctime = new_dir->i_mtime = CURRENT_TIME_SEC; + ext3_mark_inode_dirty(handle, new_dir); BUFFER_TRACE(new_bh, "call ext3_journal_dirty_metadata"); ext3_journal_dirty_metadata(handle, new_bh); brelse(new_bh); diff --git a/fs/ext3/resize.c b/fs/ext3/resize.c index 0e97b6e..28cfd0b 100644 --- a/fs/ext3/resize.c +++ b/fs/ext3/resize.c @@ -48,60 +48,60 @@ static int verify_group_input(struct super_block *sb, free_blocks_count, input->reserved_blocks); if (group != sbi->s_groups_count) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Cannot add at group %u (only %lu groups)", input->group, sbi->s_groups_count); else if ((start - le32_to_cpu(es->s_first_data_block)) % EXT3_BLOCKS_PER_GROUP(sb)) - ext3_warning(sb, __FUNCTION__, "Last group not full"); + ext3_warning(sb, __func__, "Last group not full"); else if (input->reserved_blocks > input->blocks_count / 5) - ext3_warning(sb, __FUNCTION__, "Reserved blocks too high (%u)", + ext3_warning(sb, __func__, "Reserved blocks too high (%u)", input->reserved_blocks); else if (free_blocks_count < 0) - ext3_warning(sb, __FUNCTION__, "Bad blocks count %u", + ext3_warning(sb, __func__, "Bad blocks count %u", input->blocks_count); else if (!(bh = sb_bread(sb, end - 1))) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Cannot read last block ("E3FSBLK")", end - 1); else if (outside(input->block_bitmap, start, end)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Block bitmap not in group (block %u)", input->block_bitmap); else if (outside(input->inode_bitmap, start, end)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Inode bitmap not in group (block %u)", input->inode_bitmap); else if (outside(input->inode_table, start, end) || outside(itend - 1, start, end)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Inode table not in group (blocks %u-"E3FSBLK")", input->inode_table, itend - 1); else if (input->inode_bitmap == input->block_bitmap) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Block bitmap same as inode bitmap (%u)", input->block_bitmap); else if (inside(input->block_bitmap, input->inode_table, itend)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Block bitmap (%u) in inode table (%u-"E3FSBLK")", input->block_bitmap, input->inode_table, itend-1); else if (inside(input->inode_bitmap, input->inode_table, itend)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Inode bitmap (%u) in inode table (%u-"E3FSBLK")", input->inode_bitmap, input->inode_table, itend-1); else if (inside(input->block_bitmap, start, metaend)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Block bitmap (%u) in GDT table" " ("E3FSBLK"-"E3FSBLK")", input->block_bitmap, start, metaend - 1); else if (inside(input->inode_bitmap, start, metaend)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Inode bitmap (%u) in GDT table" " ("E3FSBLK"-"E3FSBLK")", input->inode_bitmap, start, metaend - 1); else if (inside(input->inode_table, start, metaend) || inside(itend - 1, start, metaend)) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Inode table (%u-"E3FSBLK") overlaps" "GDT table ("E3FSBLK"-"E3FSBLK")", input->inode_table, itend - 1, start, metaend - 1); @@ -386,7 +386,7 @@ static int verify_reserved_gdb(struct super_block *sb, while ((grp = ext3_list_backups(sb, &three, &five, &seven)) < end) { if (le32_to_cpu(*p++) != grp * EXT3_BLOCKS_PER_GROUP(sb) + blk){ - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "reserved GDT "E3FSBLK " missing grp %d ("E3FSBLK")", blk, grp, @@ -440,7 +440,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, */ if (EXT3_SB(sb)->s_sbh->b_blocknr != le32_to_cpu(EXT3_SB(sb)->s_es->s_first_data_block)) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "won't resize using backup superblock at %llu", (unsigned long long)EXT3_SB(sb)->s_sbh->b_blocknr); return -EPERM; @@ -464,7 +464,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, data = (__le32 *)dind->b_data; if (le32_to_cpu(data[gdb_num % EXT3_ADDR_PER_BLOCK(sb)]) != gdblock) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "new group %u GDT block "E3FSBLK" not reserved", input->group, gdblock); err = -EINVAL; @@ -488,7 +488,7 @@ static int add_new_gdb(handle_t *handle, struct inode *inode, GFP_NOFS); if (!n_group_desc) { err = -ENOMEM; - ext3_warning (sb, __FUNCTION__, + ext3_warning (sb, __func__, "not enough memory for %lu groups", gdb_num + 1); goto exit_inode; } @@ -586,7 +586,7 @@ static int reserve_backup_gdb(handle_t *handle, struct inode *inode, /* Get each reserved primary GDT block and verify it holds backups */ for (res = 0; res < reserved_gdb; res++, blk++) { if (le32_to_cpu(*data) != blk) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "reserved block "E3FSBLK " not at offset %ld", blk, @@ -730,7 +730,7 @@ static void update_backups(struct super_block *sb, */ exit_err: if (err) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "can't update backup for group %d (err %d), " "forcing fsck on next reboot", group, err); sbi->s_mount_state &= ~EXT3_VALID_FS; @@ -770,33 +770,33 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) if (gdb_off == 0 && !EXT3_HAS_RO_COMPAT_FEATURE(sb, EXT3_FEATURE_RO_COMPAT_SPARSE_SUPER)) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Can't resize non-sparse filesystem further"); return -EPERM; } if (le32_to_cpu(es->s_blocks_count) + input->blocks_count < le32_to_cpu(es->s_blocks_count)) { - ext3_warning(sb, __FUNCTION__, "blocks_count overflow\n"); + ext3_warning(sb, __func__, "blocks_count overflow\n"); return -EINVAL; } if (le32_to_cpu(es->s_inodes_count) + EXT3_INODES_PER_GROUP(sb) < le32_to_cpu(es->s_inodes_count)) { - ext3_warning(sb, __FUNCTION__, "inodes_count overflow\n"); + ext3_warning(sb, __func__, "inodes_count overflow\n"); return -EINVAL; } if (reserved_gdb || gdb_off == 0) { if (!EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_RESIZE_INODE)){ - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "No reserved GDT blocks, can't resize"); return -EPERM; } inode = ext3_iget(sb, EXT3_RESIZE_INO); if (IS_ERR(inode)) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "Error opening resize inode"); return PTR_ERR(inode); } @@ -825,7 +825,7 @@ int ext3_group_add(struct super_block *sb, struct ext3_new_group_data *input) lock_super(sb); if (input->group != sbi->s_groups_count) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "multiple resizers run on filesystem!"); err = -EBUSY; goto exit_journal; @@ -988,13 +988,13 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, " too large to resize to %lu blocks safely\n", sb->s_id, n_blocks_count); if (sizeof(sector_t) < 8) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "CONFIG_LBD not enabled\n"); return -EINVAL; } if (n_blocks_count < o_blocks_count) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "can't shrink FS - resize aborted"); return -EBUSY; } @@ -1004,7 +1004,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, EXT3_BLOCKS_PER_GROUP(sb); if (last == 0) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "need to use ext2online to resize further"); return -EPERM; } @@ -1012,7 +1012,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, add = EXT3_BLOCKS_PER_GROUP(sb) - last; if (o_blocks_count + add < o_blocks_count) { - ext3_warning(sb, __FUNCTION__, "blocks_count overflow"); + ext3_warning(sb, __func__, "blocks_count overflow"); return -EINVAL; } @@ -1020,7 +1020,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, add = n_blocks_count - o_blocks_count; if (o_blocks_count + add < n_blocks_count) - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "will only finish group ("E3FSBLK " blocks, %u new)", o_blocks_count + add, add); @@ -1028,7 +1028,7 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, /* See if the device is actually as big as what was requested */ bh = sb_bread(sb, o_blocks_count + add -1); if (!bh) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "can't read last block, resize aborted"); return -ENOSPC; } @@ -1040,22 +1040,23 @@ int ext3_group_extend(struct super_block *sb, struct ext3_super_block *es, handle = ext3_journal_start_sb(sb, 3); if (IS_ERR(handle)) { err = PTR_ERR(handle); - ext3_warning(sb, __FUNCTION__, "error %d on journal start",err); + ext3_warning(sb, __func__, "error %d on journal start",err); goto exit_put; } lock_super(sb); if (o_blocks_count != le32_to_cpu(es->s_blocks_count)) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "multiple resizers run on filesystem!"); unlock_super(sb); + ext3_journal_stop(handle); err = -EBUSY; goto exit_put; } if ((err = ext3_journal_get_write_access(handle, EXT3_SB(sb)->s_sbh))) { - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "error %d on journal write access", err); unlock_super(sb); ext3_journal_stop(handle); diff --git a/fs/ext3/super.c b/fs/ext3/super.c index ad53606..fe3119a 100644 --- a/fs/ext3/super.c +++ b/fs/ext3/super.c @@ -84,7 +84,7 @@ handle_t *ext3_journal_start_sb(struct super_block *sb, int nblocks) * take the FS itself readonly cleanly. */ journal = EXT3_SB(sb)->s_journal; if (is_journal_aborted(journal)) { - ext3_abort(sb, __FUNCTION__, + ext3_abort(sb, __func__, "Detected aborted journal"); return ERR_PTR(-EROFS); } @@ -304,7 +304,7 @@ void ext3_update_dynamic_rev(struct super_block *sb) if (le32_to_cpu(es->s_rev_level) > EXT3_GOOD_OLD_REV) return; - ext3_warning(sb, __FUNCTION__, + ext3_warning(sb, __func__, "updating to rev %d because of new feature flag, " "running e2fsck is recommended", EXT3_DYNAMIC_REV); @@ -685,7 +685,8 @@ static int ext3_acquire_dquot(struct dquot *dquot); static int ext3_release_dquot(struct dquot *dquot); static int ext3_mark_dquot_dirty(struct dquot *dquot); static int ext3_write_info(struct super_block *sb, int type); -static int ext3_quota_on(struct super_block *sb, int type, int format_id, char *path); +static int ext3_quota_on(struct super_block *sb, int type, int format_id, + char *path, int remount); static int ext3_quota_on_mount(struct super_block *sb, int type); static ssize_t ext3_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); @@ -1096,6 +1097,9 @@ clear_qf_name: case Opt_quota: case Opt_usrquota: case Opt_grpquota: + printk(KERN_ERR + "EXT3-fs: quota options not supported.\n"); + break; case Opt_usrjquota: case Opt_grpjquota: case Opt_offusrjquota: @@ -1103,7 +1107,7 @@ clear_qf_name: case Opt_jqfmt_vfsold: case Opt_jqfmt_vfsv0: printk(KERN_ERR - "EXT3-fs: journalled quota options not " + "EXT3-fs: journaled quota options not " "supported.\n"); break; case Opt_noquota: @@ -1218,7 +1222,7 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, inconsistencies, to force a fsck at reboot. But for a plain journaled filesystem we can keep it set as valid forever! :) */ - es->s_state = cpu_to_le16(le16_to_cpu(es->s_state) & ~EXT3_VALID_FS); + es->s_state &= cpu_to_le16(~EXT3_VALID_FS); #endif if (!(__s16) le16_to_cpu(es->s_max_mnt_count)) es->s_max_mnt_count = cpu_to_le16(EXT3_DFL_MAX_MNT_COUNT); @@ -1253,14 +1257,14 @@ static int ext3_setup_super(struct super_block *sb, struct ext3_super_block *es, static int ext3_check_descriptors(struct super_block *sb) { struct ext3_sb_info *sbi = EXT3_SB(sb); - ext3_fsblk_t first_block = le32_to_cpu(sbi->s_es->s_first_data_block); - ext3_fsblk_t last_block; int i; ext3_debug ("Checking group descriptors"); for (i = 0; i < sbi->s_groups_count; i++) { struct ext3_group_desc *gdp = ext3_get_group_desc(sb, i, NULL); + ext3_fsblk_t first_block = ext3_group_first_block_no(sb, i); + ext3_fsblk_t last_block; if (i == sbi->s_groups_count - 1) last_block = le32_to_cpu(sbi->s_es->s_blocks_count) - 1; @@ -1299,7 +1303,6 @@ static int ext3_check_descriptors(struct super_block *sb) le32_to_cpu(gdp->bg_inode_table)); return 0; } - first_block += EXT3_BLOCKS_PER_GROUP(sb); } sbi->s_es->s_free_blocks_count=cpu_to_le32(ext3_count_free_blocks(sb)); @@ -1387,7 +1390,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, if (inode->i_nlink) { printk(KERN_DEBUG "%s: truncating inode %lu to %Ld bytes\n", - __FUNCTION__, inode->i_ino, inode->i_size); + __func__, inode->i_ino, inode->i_size); jbd_debug(2, "truncating inode %lu to %Ld bytes\n", inode->i_ino, inode->i_size); ext3_truncate(inode); @@ -1395,7 +1398,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, } else { printk(KERN_DEBUG "%s: deleting unreferenced inode %lu\n", - __FUNCTION__, inode->i_ino); + __func__, inode->i_ino); jbd_debug(2, "deleting unreferenced inode %lu\n", inode->i_ino); nr_orphans++; @@ -1415,7 +1418,7 @@ static void ext3_orphan_cleanup (struct super_block * sb, /* Turn quotas off */ for (i = 0; i < MAXQUOTAS; i++) { if (sb_dqopt(sb)->files[i]) - vfs_quota_off(sb, i); + vfs_quota_off(sb, i, 0); } #endif sb->s_flags = s_flags; /* Restore MS_RDONLY status */ @@ -2298,9 +2301,9 @@ static void ext3_clear_journal_err(struct super_block * sb, char nbuf[16]; errstr = ext3_decode_error(sb, j_errno, nbuf); - ext3_warning(sb, __FUNCTION__, "Filesystem error recorded " + ext3_warning(sb, __func__, "Filesystem error recorded " "from previous mount: %s", errstr); - ext3_warning(sb, __FUNCTION__, "Marking fs in need of " + ext3_warning(sb, __func__, "Marking fs in need of " "filesystem check."); EXT3_SB(sb)->s_mount_state |= EXT3_ERROR_FS; @@ -2427,7 +2430,7 @@ static int ext3_remount (struct super_block * sb, int * flags, char * data) } if (sbi->s_mount_opt & EXT3_MOUNT_ABORT) - ext3_abort(sb, __FUNCTION__, "Abort forced by user"); + ext3_abort(sb, __func__, "Abort forced by user"); sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((sbi->s_mount_opt & EXT3_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); @@ -2639,8 +2642,14 @@ static int ext3_dquot_drop(struct inode *inode) /* We may delete quota structure so we need to reserve enough blocks */ handle = ext3_journal_start(inode, 2*EXT3_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (IS_ERR(handle)) + if (IS_ERR(handle)) { + /* + * We call dquot_drop() anyway to at least release references + * to quota structures so that umount does not hang. + */ + dquot_drop(inode); return PTR_ERR(handle); + } ret = dquot_drop(inode); err = ext3_journal_stop(handle); if (!ret) @@ -2743,17 +2752,17 @@ static int ext3_quota_on_mount(struct super_block *sb, int type) * Standard function to be called on quota_on */ static int ext3_quota_on(struct super_block *sb, int type, int format_id, - char *path) + char *path, int remount) { int err; struct nameidata nd; if (!test_opt(sb, QUOTA)) return -EINVAL; - /* Not journalling quota? */ - if (!EXT3_SB(sb)->s_qf_names[USRQUOTA] && - !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) - return vfs_quota_on(sb, type, format_id, path); + /* Not journalling quota or remount? */ + if ((!EXT3_SB(sb)->s_qf_names[USRQUOTA] && + !EXT3_SB(sb)->s_qf_names[GRPQUOTA]) || remount) + return vfs_quota_on(sb, type, format_id, path, remount); err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) return err; @@ -2762,13 +2771,13 @@ static int ext3_quota_on(struct super_block *sb, int type, int format_id, path_put(&nd.path); return -EXDEV; } - /* Quotafile not of fs root? */ + /* Quotafile not in fs root? */ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) printk(KERN_WARNING "EXT3-fs: Quota file not on filesystem root. " "Journalled quota will not work.\n"); path_put(&nd.path); - return vfs_quota_on(sb, type, format_id, path); + return vfs_quota_on(sb, type, format_id, path, remount); } /* Read data from quotafile - avoid pagecache and such because we cannot afford diff --git a/fs/ext3/xattr.c b/fs/ext3/xattr.c index 4285654..d4a4f0e 100644 --- a/fs/ext3/xattr.c +++ b/fs/ext3/xattr.c @@ -99,6 +99,8 @@ static struct buffer_head *ext3_xattr_cache_find(struct inode *, struct mb_cache_entry **); static void ext3_xattr_rehash(struct ext3_xattr_header *, struct ext3_xattr_entry *); +static int ext3_xattr_list(struct inode *inode, char *buffer, + size_t buffer_size); static struct mb_cache *ext3_xattr_cache; @@ -232,7 +234,7 @@ ext3_xattr_block_get(struct inode *inode, int name_index, const char *name, ea_bdebug(bh, "b_count=%d, refcount=%d", atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); if (ext3_xattr_check_block(bh)) { -bad_block: ext3_error(inode->i_sb, __FUNCTION__, +bad_block: ext3_error(inode->i_sb, __func__, "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; @@ -374,7 +376,7 @@ ext3_xattr_block_list(struct inode *inode, char *buffer, size_t buffer_size) ea_bdebug(bh, "b_count=%d, refcount=%d", atomic_read(&(bh->b_count)), le32_to_cpu(BHDR(bh)->h_refcount)); if (ext3_xattr_check_block(bh)) { - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; @@ -427,7 +429,7 @@ cleanup: * Returns a negative error number on failure, or the number of bytes * used / required on success. */ -int +static int ext3_xattr_list(struct inode *inode, char *buffer, size_t buffer_size) { int i_error, b_error; @@ -649,7 +651,7 @@ ext3_xattr_block_find(struct inode *inode, struct ext3_xattr_info *i, atomic_read(&(bs->bh->b_count)), le32_to_cpu(BHDR(bs->bh)->h_refcount)); if (ext3_xattr_check_block(bs->bh)) { - ext3_error(sb, __FUNCTION__, + ext3_error(sb, __func__, "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); error = -EIO; @@ -797,10 +799,8 @@ inserted: get_bh(new_bh); } else { /* We need to allocate a new block */ - ext3_fsblk_t goal = le32_to_cpu( - EXT3_SB(sb)->s_es->s_first_data_block) + - (ext3_fsblk_t)EXT3_I(inode)->i_block_group * - EXT3_BLOCKS_PER_GROUP(sb); + ext3_fsblk_t goal = ext3_group_first_block_no(sb, + EXT3_I(inode)->i_block_group); ext3_fsblk_t block = ext3_new_block(handle, inode, goal, &error); if (error) @@ -852,7 +852,7 @@ cleanup_dquot: goto cleanup; bad_block: - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; @@ -1081,14 +1081,14 @@ ext3_xattr_delete_inode(handle_t *handle, struct inode *inode) goto cleanup; bh = sb_bread(inode->i_sb, EXT3_I(inode)->i_file_acl); if (!bh) { - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "inode %lu: block "E3FSBLK" read error", inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; } if (BHDR(bh)->h_magic != cpu_to_le32(EXT3_XATTR_MAGIC) || BHDR(bh)->h_blocks != cpu_to_le32(1)) { - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "inode %lu: bad block "E3FSBLK, inode->i_ino, EXT3_I(inode)->i_file_acl); goto cleanup; @@ -1215,7 +1215,7 @@ again: } bh = sb_bread(inode->i_sb, ce->e_block); if (!bh) { - ext3_error(inode->i_sb, __FUNCTION__, + ext3_error(inode->i_sb, __func__, "inode %lu: block %lu read error", inode->i_ino, (unsigned long) ce->e_block); } else if (le32_to_cpu(BHDR(bh)->h_refcount) >= diff --git a/fs/ext3/xattr.h b/fs/ext3/xattr.h index 6b1ae1c..148a4df 100644 --- a/fs/ext3/xattr.h +++ b/fs/ext3/xattr.h @@ -67,7 +67,6 @@ extern struct xattr_handler ext3_xattr_security_handler; extern ssize_t ext3_listxattr(struct dentry *, char *, size_t); extern int ext3_xattr_get(struct inode *, int, const char *, void *, size_t); -extern int ext3_xattr_list(struct inode *, char *, size_t); extern int ext3_xattr_set(struct inode *, int, const char *, const void *, size_t, int); extern int ext3_xattr_set_handle(handle_t *, struct inode *, int, const char *, const void *, size_t, int); @@ -89,12 +88,6 @@ ext3_xattr_get(struct inode *inode, int name_index, const char *name, } static inline int -ext3_xattr_list(struct inode *inode, void *buffer, size_t size) -{ - return -EOPNOTSUPP; -} - -static inline int ext3_xattr_set(struct inode *inode, int name_index, const char *name, const void *value, size_t size, int flags) { diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 13383ba..c81a8e7 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -813,7 +813,8 @@ static int ext4_acquire_dquot(struct dquot *dquot); static int ext4_release_dquot(struct dquot *dquot); static int ext4_mark_dquot_dirty(struct dquot *dquot); static int ext4_write_info(struct super_block *sb, int type); -static int ext4_quota_on(struct super_block *sb, int type, int format_id, char *path); +static int ext4_quota_on(struct super_block *sb, int type, int format_id, + char *path, int remount); static int ext4_quota_on_mount(struct super_block *sb, int type); static ssize_t ext4_quota_read(struct super_block *sb, int type, char *data, size_t len, loff_t off); @@ -1632,7 +1633,7 @@ static void ext4_orphan_cleanup (struct super_block * sb, /* Turn quotas off */ for (i = 0; i < MAXQUOTAS; i++) { if (sb_dqopt(sb)->files[i]) - vfs_quota_off(sb, i); + vfs_quota_off(sb, i, 0); } #endif sb->s_flags = s_flags; /* Restore MS_RDONLY status */ @@ -3143,7 +3144,7 @@ static int ext4_quota_on_mount(struct super_block *sb, int type) * Standard function to be called on quota_on */ static int ext4_quota_on(struct super_block *sb, int type, int format_id, - char *path) + char *path, int remount) { int err; struct nameidata nd; @@ -3151,9 +3152,9 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, if (!test_opt(sb, QUOTA)) return -EINVAL; /* Not journalling quota? */ - if (!EXT4_SB(sb)->s_qf_names[USRQUOTA] && - !EXT4_SB(sb)->s_qf_names[GRPQUOTA]) - return vfs_quota_on(sb, type, format_id, path); + if ((!EXT4_SB(sb)->s_qf_names[USRQUOTA] && + !EXT4_SB(sb)->s_qf_names[GRPQUOTA]) || remount) + return vfs_quota_on(sb, type, format_id, path, remount); err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) return err; @@ -3168,7 +3169,7 @@ static int ext4_quota_on(struct super_block *sb, int type, int format_id, "EXT4-fs: Quota file not on filesystem root. " "Journalled quota will not work.\n"); path_put(&nd.path); - return vfs_quota_on(sb, type, format_id, path); + return vfs_quota_on(sb, type, format_id, path, remount); } /* Read data from quotafile - avoid pagecache and such because we cannot afford diff --git a/fs/fat/dir.c b/fs/fat/dir.c index 72cbcd6..486725e 100644 --- a/fs/fat/dir.c +++ b/fs/fat/dir.c @@ -124,8 +124,8 @@ static inline int fat_get_entry(struct inode *dir, loff_t *pos, * but ignore that right now. * Ahem... Stack smashing in ring 0 isn't fun. Fixed. */ -static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, - struct nls_table *nls) +static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int len, + int uni_xlate, struct nls_table *nls) { wchar_t *ip, ec; unsigned char *op, nc; @@ -135,10 +135,11 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, ip = uni; op = ascii; - while (*ip) { + while (*ip && ((len - NLS_MAX_CHARSET_SIZE) > 0)) { ec = *ip++; if ( (charlen = nls->uni2char(ec, op, NLS_MAX_CHARSET_SIZE)) > 0) { op += charlen; + len -= charlen; } else { if (uni_xlate == 1) { *op = ':'; @@ -149,16 +150,19 @@ static int uni16_to_x8(unsigned char *ascii, wchar_t *uni, int uni_xlate, ec >>= 4; } op += 5; + len -= 5; } else { *op++ = '?'; + len--; } } - /* We have some slack there, so it's OK */ - if (op>ascii+256) { - op = ascii + 256; - break; - } } + + if (unlikely(*ip)) { + printk(KERN_WARNING "FAT: filename was truncated while " + "converting."); + } + *op = 0; return (op - ascii); } @@ -243,7 +247,7 @@ static int fat_parse_long(struct inode *dir, loff_t *pos, unsigned char id, slot, slots, alias_checksum; if (!*unicode) { - *unicode = (wchar_t *)__get_free_page(GFP_KERNEL); + *unicode = __getname(); if (!*unicode) { brelse(*bh); return -ENOMEM; @@ -311,9 +315,11 @@ int fat_search_long(struct inode *inode, const unsigned char *name, struct nls_table *nls_io = sbi->nls_io; struct nls_table *nls_disk = sbi->nls_disk; wchar_t bufuname[14]; - unsigned char xlate_len, nr_slots; + unsigned char nr_slots; + int xlate_len; wchar_t *unicode = NULL; - unsigned char work[MSDOS_NAME], bufname[260]; /* 256 + 4 */ + unsigned char work[MSDOS_NAME]; + unsigned char *bufname = NULL; int uni_xlate = sbi->options.unicode_xlate; int utf8 = sbi->options.utf8; int anycase = (sbi->options.name_check != 's'); @@ -321,6 +327,10 @@ int fat_search_long(struct inode *inode, const unsigned char *name, loff_t cpos = 0; int chl, i, j, last_u, err; + bufname = __getname(); + if (!bufname) + return -ENOMEM; + err = -ENOENT; while(1) { if (fat_get_entry(inode, &cpos, &bh, &de) == -1) @@ -386,8 +396,8 @@ parse_record: bufuname[last_u] = 0x0000; xlate_len = utf8 - ?utf8_wcstombs(bufname, bufuname, sizeof(bufname)) - :uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); + ?utf8_wcstombs(bufname, bufuname, PATH_MAX) + :uni16_to_x8(bufname, bufuname, PATH_MAX, uni_xlate, nls_io); if (xlate_len == name_len) if ((!anycase && !memcmp(name, bufname, xlate_len)) || (anycase && !nls_strnicmp(nls_io, name, bufname, @@ -396,8 +406,8 @@ parse_record: if (nr_slots) { xlate_len = utf8 - ?utf8_wcstombs(bufname, unicode, sizeof(bufname)) - :uni16_to_x8(bufname, unicode, uni_xlate, nls_io); + ?utf8_wcstombs(bufname, unicode, PATH_MAX) + :uni16_to_x8(bufname, unicode, PATH_MAX, uni_xlate, nls_io); if (xlate_len != name_len) continue; if ((!anycase && !memcmp(name, bufname, xlate_len)) || @@ -416,8 +426,10 @@ Found: sinfo->i_pos = fat_make_i_pos(sb, sinfo->bh, sinfo->de); err = 0; EODir: + if (bufname) + __putname(bufname); if (unicode) - free_page((unsigned long)unicode); + __putname(unicode); return err; } @@ -598,7 +610,7 @@ parse_record: if (isvfat) { bufuname[j] = 0x0000; i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname)) - : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io); + : uni16_to_x8(bufname, bufuname, sizeof(bufname), uni_xlate, nls_io); } fill_name = bufname; @@ -607,10 +619,10 @@ parse_record: /* convert the unicode long name. 261 is maximum size * of unicode buffer. (13 * slots + nul) */ void *longname = unicode + 261; - int buf_size = PAGE_SIZE - (261 * sizeof(unicode[0])); + int buf_size = PATH_MAX - (261 * sizeof(unicode[0])); int long_len = utf8 ? utf8_wcstombs(longname, unicode, buf_size) - : uni16_to_x8(longname, unicode, uni_xlate, nls_io); + : uni16_to_x8(longname, unicode, buf_size, uni_xlate, nls_io); if (!both) { fill_name = longname; @@ -640,7 +652,7 @@ EODir: FillFailed: brelse(bh); if (unicode) - free_page((unsigned long)unicode); + __putname(unicode); out: unlock_kernel(); return ret; diff --git a/fs/fat/fatent.c b/fs/fat/fatent.c index 5fb3669..13ab763 100644 --- a/fs/fat/fatent.c +++ b/fs/fat/fatent.c @@ -450,7 +450,8 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) BUG_ON(nr_cluster > (MAX_BUF_PER_PAGE / 2)); /* fixed limit */ lock_fat(sbi); - if (sbi->free_clusters != -1 && sbi->free_clusters < nr_cluster) { + if (sbi->free_clusters != -1 && sbi->free_clus_valid && + sbi->free_clusters < nr_cluster) { unlock_fat(sbi); return -ENOSPC; } @@ -504,6 +505,7 @@ int fat_alloc_clusters(struct inode *inode, int *cluster, int nr_cluster) /* Couldn't allocate the free entries */ sbi->free_clusters = 0; + sbi->free_clus_valid = 1; sb->s_dirt = 1; err = -ENOSPC; @@ -583,8 +585,6 @@ error: brelse(bhs[i]); unlock_fat(sbi); - fat_clusters_flush(sb); - return err; } @@ -615,7 +615,7 @@ int fat_count_free_clusters(struct super_block *sb) int err = 0, free; lock_fat(sbi); - if (sbi->free_clusters != -1) + if (sbi->free_clusters != -1 && sbi->free_clus_valid) goto out; reada_blocks = FAT_READA_SIZE >> sb->s_blocksize_bits; @@ -643,6 +643,7 @@ int fat_count_free_clusters(struct super_block *sb) } while (fat_ent_next(sbi, &fatent)); } sbi->free_clusters = free; + sbi->free_clus_valid = 1; sb->s_dirt = 1; fatent_brelse(&fatent); out: diff --git a/fs/fat/file.c b/fs/fat/file.c index 2a3bed9..d604bb1 100644 --- a/fs/fat/file.c +++ b/fs/fat/file.c @@ -157,104 +157,6 @@ out: return err; } -static int check_mode(const struct msdos_sb_info *sbi, mode_t mode) -{ - mode_t req = mode & ~S_IFMT; - - /* - * Of the r and x bits, all (subject to umask) must be present. Of the - * w bits, either all (subject to umask) or none must be present. - */ - - if (S_ISREG(mode)) { - req &= ~sbi->options.fs_fmask; - - if ((req & (S_IRUGO | S_IXUGO)) != - ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_fmask)) - return -EPERM; - - if ((req & S_IWUGO) != 0 && - (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_fmask)) - return -EPERM; - } else if (S_ISDIR(mode)) { - req &= ~sbi->options.fs_dmask; - - if ((req & (S_IRUGO | S_IXUGO)) != - ((S_IRUGO | S_IXUGO) & ~sbi->options.fs_dmask)) - return -EPERM; - - if ((req & S_IWUGO) != 0 && - (req & S_IWUGO) != (S_IWUGO & ~sbi->options.fs_dmask)) - return -EPERM; - } else { - return -EPERM; - } - - return 0; -} - -int fat_notify_change(struct dentry *dentry, struct iattr *attr) -{ - struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); - struct inode *inode = dentry->d_inode; - int mask, error = 0; - - lock_kernel(); - - /* - * Expand the file. Since inode_setattr() updates ->i_size - * before calling the ->truncate(), but FAT needs to fill the - * hole before it. - */ - if (attr->ia_valid & ATTR_SIZE) { - if (attr->ia_size > inode->i_size) { - error = fat_cont_expand(inode, attr->ia_size); - if (error || attr->ia_valid == ATTR_SIZE) - goto out; - attr->ia_valid &= ~ATTR_SIZE; - } - } - - error = inode_change_ok(inode, attr); - if (error) { - if (sbi->options.quiet) - error = 0; - goto out; - } - if (((attr->ia_valid & ATTR_UID) && - (attr->ia_uid != sbi->options.fs_uid)) || - ((attr->ia_valid & ATTR_GID) && - (attr->ia_gid != sbi->options.fs_gid))) - error = -EPERM; - - if (error) { - if (sbi->options.quiet) - error = 0; - goto out; - } - - if (attr->ia_valid & ATTR_MODE) { - error = check_mode(sbi, attr->ia_mode); - if (error != 0 && !sbi->options.quiet) - goto out; - } - - error = inode_setattr(inode, attr); - if (error) - goto out; - - if (S_ISDIR(inode->i_mode)) - mask = sbi->options.fs_dmask; - else - mask = sbi->options.fs_fmask; - inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); -out: - unlock_kernel(); - return error; -} - -EXPORT_SYMBOL_GPL(fat_notify_change); - /* Free all clusters after the skip'th cluster. */ static int fat_free(struct inode *inode, int skip) { @@ -355,8 +257,112 @@ int fat_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat) } EXPORT_SYMBOL_GPL(fat_getattr); +static int fat_check_mode(const struct msdos_sb_info *sbi, struct inode *inode, + mode_t mode) +{ + mode_t mask, req = mode & ~S_IFMT; + + if (S_ISREG(mode)) + mask = sbi->options.fs_fmask; + else + mask = sbi->options.fs_dmask; + + /* + * Of the r and x bits, all (subject to umask) must be present. Of the + * w bits, either all (subject to umask) or none must be present. + */ + req &= ~mask; + if ((req & (S_IRUGO | S_IXUGO)) != (inode->i_mode & (S_IRUGO|S_IXUGO))) + return -EPERM; + if ((req & S_IWUGO) && ((req & S_IWUGO) != (S_IWUGO & ~mask))) + return -EPERM; + + return 0; +} + +static int fat_allow_set_time(struct msdos_sb_info *sbi, struct inode *inode) +{ + mode_t allow_utime = sbi->options.allow_utime; + + if (current->fsuid != inode->i_uid) { + if (in_group_p(inode->i_gid)) + allow_utime >>= 3; + if (allow_utime & MAY_WRITE) + return 1; + } + + /* use a default check */ + return 0; +} + +int fat_setattr(struct dentry *dentry, struct iattr *attr) +{ + struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); + struct inode *inode = dentry->d_inode; + int mask, error = 0; + unsigned int ia_valid; + + lock_kernel(); + + /* + * Expand the file. Since inode_setattr() updates ->i_size + * before calling the ->truncate(), but FAT needs to fill the + * hole before it. + */ + if (attr->ia_valid & ATTR_SIZE) { + if (attr->ia_size > inode->i_size) { + error = fat_cont_expand(inode, attr->ia_size); + if (error || attr->ia_valid == ATTR_SIZE) + goto out; + attr->ia_valid &= ~ATTR_SIZE; + } + } + + /* Check for setting the inode time. */ + ia_valid = attr->ia_valid; + if (ia_valid & (ATTR_MTIME_SET | ATTR_ATIME_SET)) { + if (fat_allow_set_time(sbi, inode)) + attr->ia_valid &= ~(ATTR_MTIME_SET | ATTR_ATIME_SET); + } + + error = inode_change_ok(inode, attr); + attr->ia_valid = ia_valid; + if (error) { + if (sbi->options.quiet) + error = 0; + goto out; + } + if (((attr->ia_valid & ATTR_UID) && + (attr->ia_uid != sbi->options.fs_uid)) || + ((attr->ia_valid & ATTR_GID) && + (attr->ia_gid != sbi->options.fs_gid)) || + ((attr->ia_valid & ATTR_MODE) && + fat_check_mode(sbi, inode, attr->ia_mode) < 0)) + error = -EPERM; + + if (error) { + if (sbi->options.quiet) + error = 0; + goto out; + } + + error = inode_setattr(inode, attr); + if (error) + goto out; + + if (S_ISDIR(inode->i_mode)) + mask = sbi->options.fs_dmask; + else + mask = sbi->options.fs_fmask; + inode->i_mode &= S_IFMT | (S_IRWXUGO & ~mask); +out: + unlock_kernel(); + return error; +} +EXPORT_SYMBOL_GPL(fat_setattr); + const struct inode_operations fat_file_inode_operations = { .truncate = fat_truncate, - .setattr = fat_notify_change, + .setattr = fat_setattr, .getattr = fat_getattr, }; diff --git a/fs/fat/inode.c b/fs/fat/inode.c index 53f3cf6..5f522a5 100644 --- a/fs/fat/inode.c +++ b/fs/fat/inode.c @@ -433,11 +433,8 @@ EXPORT_SYMBOL_GPL(fat_build_inode); static void fat_delete_inode(struct inode *inode) { truncate_inode_pages(&inode->i_data, 0); - - if (!is_bad_inode(inode)) { - inode->i_size = 0; - fat_truncate(inode); - } + inode->i_size = 0; + fat_truncate(inode); clear_inode(inode); } @@ -445,8 +442,6 @@ static void fat_clear_inode(struct inode *inode) { struct msdos_sb_info *sbi = MSDOS_SB(inode->i_sb); - if (is_bad_inode(inode)) - return; lock_kernel(); spin_lock(&sbi->inode_hash_lock); fat_cache_inval_inode(inode); @@ -542,7 +537,7 @@ static int fat_statfs(struct dentry *dentry, struct kstatfs *buf) struct msdos_sb_info *sbi = MSDOS_SB(dentry->d_sb); /* If the count of free cluster is still unknown, counts it here. */ - if (sbi->free_clusters == -1) { + if (sbi->free_clusters == -1 || !sbi->free_clus_valid) { int err = fat_count_free_clusters(dentry->d_sb); if (err) return err; @@ -790,6 +785,8 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) seq_printf(m, ",gid=%u", opts->fs_gid); seq_printf(m, ",fmask=%04o", opts->fs_fmask); seq_printf(m, ",dmask=%04o", opts->fs_dmask); + if (opts->allow_utime) + seq_printf(m, ",allow_utime=%04o", opts->allow_utime); if (sbi->nls_disk) seq_printf(m, ",codepage=%s", sbi->nls_disk->charset); if (isvfat) { @@ -845,9 +842,9 @@ static int fat_show_options(struct seq_file *m, struct vfsmount *mnt) enum { Opt_check_n, Opt_check_r, Opt_check_s, Opt_uid, Opt_gid, - Opt_umask, Opt_dmask, Opt_fmask, Opt_codepage, Opt_usefree, Opt_nocase, - Opt_quiet, Opt_showexec, Opt_debug, Opt_immutable, - Opt_dots, Opt_nodots, + Opt_umask, Opt_dmask, Opt_fmask, Opt_allow_utime, Opt_codepage, + Opt_usefree, Opt_nocase, Opt_quiet, Opt_showexec, Opt_debug, + Opt_immutable, Opt_dots, Opt_nodots, Opt_charset, Opt_shortname_lower, Opt_shortname_win95, Opt_shortname_winnt, Opt_shortname_mixed, Opt_utf8_no, Opt_utf8_yes, Opt_uni_xl_no, Opt_uni_xl_yes, Opt_nonumtail_no, Opt_nonumtail_yes, @@ -866,6 +863,7 @@ static match_table_t fat_tokens = { {Opt_umask, "umask=%o"}, {Opt_dmask, "dmask=%o"}, {Opt_fmask, "fmask=%o"}, + {Opt_allow_utime, "allow_utime=%o"}, {Opt_codepage, "codepage=%u"}, {Opt_usefree, "usefree"}, {Opt_nocase, "nocase"}, @@ -937,6 +935,7 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, opts->fs_uid = current->uid; opts->fs_gid = current->gid; opts->fs_fmask = opts->fs_dmask = current->fs->umask; + opts->allow_utime = -1; opts->codepage = fat_default_codepage; opts->iocharset = fat_default_iocharset; if (is_vfat) @@ -1024,6 +1023,11 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, return 0; opts->fs_fmask = option; break; + case Opt_allow_utime: + if (match_octal(&args[0], &option)) + return 0; + opts->allow_utime = option & (S_IWGRP | S_IWOTH); + break; case Opt_codepage: if (match_int(&args[0], &option)) return 0; @@ -1106,6 +1110,9 @@ static int parse_options(char *options, int is_vfat, int silent, int *debug, " for FAT filesystems, filesystem will be case sensitive!\n"); } + /* If user doesn't specify allow_utime, it's initialized from dmask. */ + if (opts->allow_utime == (unsigned short)-1) + opts->allow_utime = ~opts->fs_dmask & (S_IWGRP | S_IWOTH); if (opts->unicode_xlate) opts->utf8 = 0; @@ -1208,7 +1215,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, */ media = b->media; - if (!FAT_VALID_MEDIA(media)) { + if (!fat_valid_media(media)) { if (!silent) printk(KERN_ERR "FAT: invalid media value (0x%02x)\n", media); @@ -1219,7 +1226,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, le16_to_cpu(get_unaligned((__le16 *)&b->sector_size)); if (!is_power_of_2(logical_sector_size) || (logical_sector_size < 512) - || (PAGE_CACHE_SIZE < logical_sector_size)) { + || (logical_sector_size > 4096)) { if (!silent) printk(KERN_ERR "FAT: bogus logical sector size %u\n", logical_sector_size); @@ -1267,6 +1274,7 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->fat_length = le16_to_cpu(b->fat_length); sbi->root_cluster = 0; sbi->free_clusters = -1; /* Don't know yet */ + sbi->free_clus_valid = 0; sbi->prev_free = FAT_START_ENT; if (!sbi->fat_length && b->fat32_length) { @@ -1302,8 +1310,8 @@ int fat_fill_super(struct super_block *sb, void *data, int silent, sbi->fsinfo_sector); } else { if (sbi->options.usefree) - sbi->free_clusters = - le32_to_cpu(fsinfo->free_clusters); + sbi->free_clus_valid = 1; + sbi->free_clusters = le32_to_cpu(fsinfo->free_clusters); sbi->prev_free = le32_to_cpu(fsinfo->next_cluster); } diff --git a/fs/gfs2/ops_address.c b/fs/gfs2/ops_address.c index 90a04a6..f55394e 100644 --- a/fs/gfs2/ops_address.c +++ b/fs/gfs2/ops_address.c @@ -438,7 +438,7 @@ static int stuffed_readpage(struct gfs2_inode *ip, struct page *page) int error; /* - * Due to the order of unstuffing files and ->nopage(), we can be + * Due to the order of unstuffing files and ->fault(), we can be * asked for a zero page in the case of a stuffed file being extended, * so we need to supply one here. It doesn't happen often. */ diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c index 6846785..9783723 100644 --- a/fs/hugetlbfs/inode.c +++ b/fs/hugetlbfs/inode.c @@ -504,7 +504,7 @@ static struct inode *hugetlbfs_get_inode(struct super_block *sb, uid_t uid, inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME; INIT_LIST_HEAD(&inode->i_mapping->private_list); info = HUGETLBFS_I(inode); - mpol_shared_policy_init(&info->policy, MPOL_DEFAULT, NULL); + mpol_shared_policy_init(&info->policy, NULL); switch (mode & S_IFMT) { default: init_special_inode(inode, mode, dev); diff --git a/fs/jbd/commit.c b/fs/jbd/commit.c index a38c718..cd931ef 100644 --- a/fs/jbd/commit.c +++ b/fs/jbd/commit.c @@ -407,22 +407,6 @@ void journal_commit_transaction(journal_t *journal) jbd_debug (3, "JBD: commit phase 2\n"); /* - * First, drop modified flag: all accesses to the buffers - * will be tracked for a new trasaction only -bzzz - */ - spin_lock(&journal->j_list_lock); - if (commit_transaction->t_buffers) { - new_jh = jh = commit_transaction->t_buffers->b_tnext; - do { - J_ASSERT_JH(new_jh, new_jh->b_modified == 1 || - new_jh->b_modified == 0); - new_jh->b_modified = 0; - new_jh = new_jh->b_tnext; - } while (new_jh != jh); - } - spin_unlock(&journal->j_list_lock); - - /* * Now start flushing things to disk, in the order they appear * on the transaction lists. Data blocks go first. */ @@ -488,6 +472,9 @@ void journal_commit_transaction(journal_t *journal) */ commit_transaction->t_state = T_COMMIT; + J_ASSERT(commit_transaction->t_nr_buffers <= + commit_transaction->t_outstanding_credits); + descriptor = NULL; bufs = 0; while (commit_transaction->t_buffers) { diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index 0e081d5..b99c3b3 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -534,7 +534,7 @@ int log_wait_commit(journal_t *journal, tid_t tid) if (!tid_geq(journal->j_commit_request, tid)) { printk(KERN_EMERG "%s: error: j_commit_request=%d, tid=%d\n", - __FUNCTION__, journal->j_commit_request, tid); + __func__, journal->j_commit_request, tid); } spin_unlock(&journal->j_state_lock); #endif @@ -599,7 +599,7 @@ int journal_bmap(journal_t *journal, unsigned long blocknr, printk(KERN_ALERT "%s: journal block not found " "at offset %lu on %s\n", - __FUNCTION__, + __func__, blocknr, bdevname(journal->j_dev, b)); err = -EIO; @@ -728,7 +728,7 @@ journal_t * journal_init_dev(struct block_device *bdev, journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", - __FUNCTION__); + __func__); kfree(journal); journal = NULL; goto out; @@ -782,7 +782,7 @@ journal_t * journal_init_inode (struct inode *inode) journal->j_wbuf = kmalloc(n * sizeof(struct buffer_head*), GFP_KERNEL); if (!journal->j_wbuf) { printk(KERN_ERR "%s: Cant allocate bhs for commit thread\n", - __FUNCTION__); + __func__); kfree(journal); return NULL; } @@ -791,7 +791,7 @@ journal_t * journal_init_inode (struct inode *inode) /* If that failed, give up */ if (err) { printk(KERN_ERR "%s: Cannnot locate journal superblock\n", - __FUNCTION__); + __func__); kfree(journal); return NULL; } @@ -877,7 +877,7 @@ int journal_create(journal_t *journal) */ printk(KERN_EMERG "%s: creation of journal on external device!\n", - __FUNCTION__); + __func__); BUG(); } @@ -1657,7 +1657,7 @@ static struct journal_head *journal_alloc_journal_head(void) jbd_debug(1, "out of memory for journal_head\n"); if (time_after(jiffies, last_warning + 5*HZ)) { printk(KERN_NOTICE "ENOMEM in %s, retrying.\n", - __FUNCTION__); + __func__); last_warning = jiffies; } while (ret == NULL) { @@ -1794,13 +1794,13 @@ static void __journal_remove_journal_head(struct buffer_head *bh) if (jh->b_frozen_data) { printk(KERN_WARNING "%s: freeing " "b_frozen_data\n", - __FUNCTION__); + __func__); jbd_free(jh->b_frozen_data, bh->b_size); } if (jh->b_committed_data) { printk(KERN_WARNING "%s: freeing " "b_committed_data\n", - __FUNCTION__); + __func__); jbd_free(jh->b_committed_data, bh->b_size); } bh->b_private = NULL; diff --git a/fs/jbd/revoke.c b/fs/jbd/revoke.c index d5f8eee..1bb43e9 100644 --- a/fs/jbd/revoke.c +++ b/fs/jbd/revoke.c @@ -138,7 +138,7 @@ repeat: oom: if (!journal_oom_retry) return -ENOMEM; - jbd_debug(1, "ENOMEM in %s, retrying\n", __FUNCTION__); + jbd_debug(1, "ENOMEM in %s, retrying\n", __func__); yield(); goto repeat; } diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 2c9e8f5..67ff202 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -609,6 +609,12 @@ repeat: goto done; /* + * this is the first time this transaction is touching this buffer, + * reset the modified flag + */ + jh->b_modified = 0; + + /* * If there is already a copy-out version of this buffer, then we don't * need to make another one */ @@ -681,7 +687,7 @@ repeat: if (!frozen_buffer) { printk(KERN_EMERG "%s: OOM for frozen_buffer\n", - __FUNCTION__); + __func__); JBUFFER_TRACE(jh, "oom!"); error = -ENOMEM; jbd_lock_bh_state(bh); @@ -820,9 +826,16 @@ int journal_get_create_access(handle_t *handle, struct buffer_head *bh) if (jh->b_transaction == NULL) { jh->b_transaction = transaction; + + /* first access by this transaction */ + jh->b_modified = 0; + JBUFFER_TRACE(jh, "file as BJ_Reserved"); __journal_file_buffer(jh, transaction, BJ_Reserved); } else if (jh->b_transaction == journal->j_committing_transaction) { + /* first access by this transaction */ + jh->b_modified = 0; + JBUFFER_TRACE(jh, "set next transaction"); jh->b_next_transaction = transaction; } @@ -891,7 +904,7 @@ repeat: committed_data = jbd_alloc(jh2bh(jh)->b_size, GFP_NOFS); if (!committed_data) { printk(KERN_EMERG "%s: No memory for committed data\n", - __FUNCTION__); + __func__); err = -ENOMEM; goto out; } @@ -1222,6 +1235,7 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) struct journal_head *jh; int drop_reserve = 0; int err = 0; + int was_modified = 0; BUFFER_TRACE(bh, "entry"); @@ -1240,6 +1254,9 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) goto not_jbd; } + /* keep track of wether or not this transaction modified us */ + was_modified = jh->b_modified; + /* * The buffer's going from the transaction, we must drop * all references -bzzz @@ -1257,7 +1274,12 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) JBUFFER_TRACE(jh, "belongs to current transaction: unfile"); - drop_reserve = 1; + /* + * we only want to drop a reference if this transaction + * modified the buffer + */ + if (was_modified) + drop_reserve = 1; /* * We are no longer going to journal this buffer. @@ -1297,7 +1319,13 @@ int journal_forget (handle_t *handle, struct buffer_head *bh) if (jh->b_next_transaction) { J_ASSERT(jh->b_next_transaction == transaction); jh->b_next_transaction = NULL; - drop_reserve = 1; + + /* + * only drop a reference if this transaction modified + * the buffer + */ + if (was_modified) + drop_reserve = 1; } } @@ -2069,7 +2097,7 @@ void __journal_refile_buffer(struct journal_head *jh) jh->b_transaction = jh->b_next_transaction; jh->b_next_transaction = NULL; __journal_file_buffer(jh, jh->b_transaction, - was_dirty ? BJ_Metadata : BJ_Reserved); + jh->b_modified ? BJ_Metadata : BJ_Reserved); J_ASSERT_JH(jh, jh->b_transaction->t_state == T_RUNNING); if (was_dirty) diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 30f7d0a..2d4358c 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c @@ -653,7 +653,7 @@ static const struct inode_operations msdos_dir_inode_operations = { .mkdir = msdos_mkdir, .rmdir = msdos_rmdir, .rename = msdos_rename, - .setattr = fat_notify_change, + .setattr = fat_setattr, .getattr = fat_getattr, }; diff --git a/fs/namespace.c b/fs/namespace.c index f48f981..fe37680 100644 --- a/fs/namespace.c +++ b/fs/namespace.c @@ -14,7 +14,6 @@ #include <linux/smp_lock.h> #include <linux/init.h> #include <linux/kernel.h> -#include <linux/quotaops.h> #include <linux/acct.h> #include <linux/capability.h> #include <linux/cpumask.h> @@ -1084,7 +1083,6 @@ static int do_umount(struct vfsmount *mnt, int flags) down_write(&sb->s_umount); if (!(sb->s_flags & MS_RDONLY)) { lock_kernel(); - DQUOT_OFF(sb); retval = do_remount_sb(sb, MS_RDONLY, NULL, 0); unlock_kernel(); } diff --git a/fs/ncpfs/inode.c b/fs/ncpfs/inode.c index fbbb9f7..2e5ab12 100644 --- a/fs/ncpfs/inode.c +++ b/fs/ncpfs/inode.c @@ -107,12 +107,6 @@ static const struct super_operations ncp_sops = .show_options = ncp_show_options, }; -extern struct dentry_operations ncp_root_dentry_operations; -#if defined(CONFIG_NCPFS_EXTRAS) || defined(CONFIG_NCPFS_NFS_NS) -extern const struct address_space_operations ncp_symlink_aops; -extern int ncp_symlink(struct inode*, struct dentry*, const char*); -#endif - /* * Fill in the ncpfs-specific information in the inode. */ diff --git a/fs/ncpfs/ioctl.c b/fs/ncpfs/ioctl.c index ad8f167..3a97c95 100644 --- a/fs/ncpfs/ioctl.c +++ b/fs/ncpfs/ioctl.c @@ -389,11 +389,11 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp, struct dentry* dentry = inode->i_sb->s_root; if (dentry) { - struct inode* inode = dentry->d_inode; + struct inode* s_inode = dentry->d_inode; - if (inode) { - sr.volNumber = NCP_FINFO(inode)->volNumber; - sr.dirEntNum = NCP_FINFO(inode)->dirEntNum; + if (s_inode) { + sr.volNumber = NCP_FINFO(s_inode)->volNumber; + sr.dirEntNum = NCP_FINFO(s_inode)->dirEntNum; sr.namespace = server->name_space[sr.volNumber]; } else DPRINTK("ncpfs: s_root->d_inode==NULL\n"); @@ -439,12 +439,12 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp, dentry = inode->i_sb->s_root; server->root_setuped = 1; if (dentry) { - struct inode* inode = dentry->d_inode; + struct inode* s_inode = dentry->d_inode; if (inode) { - NCP_FINFO(inode)->volNumber = vnum; - NCP_FINFO(inode)->dirEntNum = de; - NCP_FINFO(inode)->DosDirNum = dosde; + NCP_FINFO(s_inode)->volNumber = vnum; + NCP_FINFO(s_inode)->dirEntNum = de; + NCP_FINFO(s_inode)->DosDirNum = dosde; } else DPRINTK("ncpfs: s_root->d_inode==NULL\n"); } else @@ -519,7 +519,6 @@ static int __ncp_ioctl(struct inode *inode, struct file *filp, } { struct ncp_lock_ioctl rqdata; - int result; if (copy_from_user(&rqdata, argp, sizeof(rqdata))) return -EFAULT; diff --git a/fs/ncpfs/ncpsign_kernel.c b/fs/ncpfs/ncpsign_kernel.c index 749a18d..7c0b5c2 100644 --- a/fs/ncpfs/ncpsign_kernel.c +++ b/fs/ncpfs/ncpsign_kernel.c @@ -55,7 +55,7 @@ static void nwsign(char *r_data1, char *r_data2, char *outdata) { unsigned int w0,w1,w2,w3; static int rbit[4]={0, 2, 1, 3}; #ifdef __i386__ - unsigned int *data2=(int *)r_data2; + unsigned int *data2=(unsigned int *)r_data2; #else unsigned int data2[16]; for (i=0;i<16;i++) @@ -837,7 +837,7 @@ static struct file *__dentry_open(struct dentry *dentry, struct vfsmount *mnt, if (f->f_flags & O_DIRECT) { if (!f->f_mapping->a_ops || ((!f->f_mapping->a_ops->direct_IO) && - (!f->f_mapping->a_ops->get_xip_page))) { + (!f->f_mapping->a_ops->get_xip_mem))) { fput(f); f = ERR_PTR(-EINVAL); } diff --git a/fs/partitions/msdos.c b/fs/partitions/msdos.c index 5567ec0..7965118 100644 --- a/fs/partitions/msdos.c +++ b/fs/partitions/msdos.c @@ -18,7 +18,7 @@ * * Re-organised Feb 1998 Russell King */ - +#include <linux/msdos_fs.h> #include "check.h" #include "msdos.h" @@ -419,6 +419,7 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) Sector sect; unsigned char *data; struct partition *p; + struct fat_boot_sector *fb; int slot; data = read_dev_sector(bdev, 0, §); @@ -444,8 +445,21 @@ int msdos_partition(struct parsed_partitions *state, struct block_device *bdev) p = (struct partition *) (data + 0x1be); for (slot = 1; slot <= 4; slot++, p++) { if (p->boot_ind != 0 && p->boot_ind != 0x80) { - put_dev_sector(sect); - return 0; + /* + * Even without a valid boot inidicator value + * its still possible this is valid FAT filesystem + * without a partition table. + */ + fb = (struct fat_boot_sector *) data; + if (slot == 1 && fb->reserved && fb->fats + && fat_valid_media(fb->media)) { + printk("\n"); + put_dev_sector(sect); + return 1; + } else { + put_dev_sector(sect); + return 0; + } } } diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c index 2d56397..441a32f 100644 --- a/fs/proc/proc_misc.c +++ b/fs/proc/proc_misc.c @@ -456,6 +456,20 @@ static const struct file_operations proc_slabstats_operations = { #endif #endif +#ifdef CONFIG_MMU +static int vmalloc_open(struct inode *inode, struct file *file) +{ + return seq_open(file, &vmalloc_op); +} + +static const struct file_operations proc_vmalloc_operations = { + .open = vmalloc_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release, +}; +#endif + static int show_stat(struct seq_file *p, void *v) { int i; @@ -869,6 +883,9 @@ void __init proc_misc_init(void) create_seq_entry("slab_allocators", 0 ,&proc_slabstats_operations); #endif #endif +#ifdef CONFIG_MMU + proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations); +#endif create_seq_entry("buddyinfo",S_IRUGO, &fragmentation_file_operations); create_seq_entry("pagetypeinfo", S_IRUGO, &pagetypeinfo_file_ops); create_seq_entry("vmstat",S_IRUGO, &proc_vmstat_file_operations); diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 9dfb5ff..7415eeb 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c @@ -338,8 +338,7 @@ const struct file_operations proc_maps_operations = { #define PSS_SHIFT 12 #ifdef CONFIG_PROC_PAGE_MONITOR -struct mem_size_stats -{ +struct mem_size_stats { struct vm_area_struct *vma; unsigned long resident; unsigned long shared_clean; @@ -347,6 +346,7 @@ struct mem_size_stats unsigned long private_clean; unsigned long private_dirty; unsigned long referenced; + unsigned long swap; u64 pss; }; @@ -363,6 +363,12 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl); for (; addr != end; pte++, addr += PAGE_SIZE) { ptent = *pte; + + if (is_swap_pte(ptent)) { + mss->swap += PAGE_SIZE; + continue; + } + if (!pte_present(ptent)) continue; @@ -421,7 +427,8 @@ static int show_smap(struct seq_file *m, void *v) "Shared_Dirty: %8lu kB\n" "Private_Clean: %8lu kB\n" "Private_Dirty: %8lu kB\n" - "Referenced: %8lu kB\n", + "Referenced: %8lu kB\n" + "Swap: %8lu kB\n", (vma->vm_end - vma->vm_start) >> 10, mss.resident >> 10, (unsigned long)(mss.pss >> (10 + PSS_SHIFT)), @@ -429,7 +436,8 @@ static int show_smap(struct seq_file *m, void *v) mss.shared_dirty >> 10, mss.private_clean >> 10, mss.private_dirty >> 10, - mss.referenced >> 10); + mss.referenced >> 10, + mss.swap >> 10); return ret; } @@ -579,7 +587,7 @@ static int pagemap_pte_hole(unsigned long start, unsigned long end, return err; } -u64 swap_pte_to_pagemap_entry(pte_t pte) +static u64 swap_pte_to_pagemap_entry(pte_t pte) { swp_entry_t e = pte_to_swp_entry(pte); return swp_type(e) | (swp_offset(e) << MAX_SWAPFILES_SHIFT); @@ -69,7 +69,6 @@ static int generic_quotactl_valid(struct super_block *sb, int type, int cmd, qid switch (cmd) { case Q_GETFMT: case Q_GETINFO: - case Q_QUOTAOFF: case Q_SETINFO: case Q_SETQUOTA: case Q_GETQUOTA: @@ -229,12 +228,12 @@ static int do_quotactl(struct super_block *sb, int type, int cmd, qid_t id, void if (IS_ERR(pathname = getname(addr))) return PTR_ERR(pathname); - ret = sb->s_qcop->quota_on(sb, type, id, pathname); + ret = sb->s_qcop->quota_on(sb, type, id, pathname, 0); putname(pathname); return ret; } case Q_QUOTAOFF: - return sb->s_qcop->quota_off(sb, type); + return sb->s_qcop->quota_off(sb, type, 0); case Q_GETFMT: { __u32 fmt; diff --git a/fs/quota_v1.c b/fs/quota_v1.c index f3841f2..a6cf926 100644 --- a/fs/quota_v1.c +++ b/fs/quota_v1.c @@ -139,6 +139,9 @@ static int v1_read_file_info(struct super_block *sb, int type) goto out; } ret = 0; + /* limits are stored as unsigned 32-bit data */ + dqopt->info[type].dqi_maxblimit = 0xffffffff; + dqopt->info[type].dqi_maxilimit = 0xffffffff; dqopt->info[type].dqi_igrace = dqblk.dqb_itime ? dqblk.dqb_itime : MAX_IQ_TIME; dqopt->info[type].dqi_bgrace = dqblk.dqb_btime ? dqblk.dqb_btime : MAX_DQ_TIME; out: diff --git a/fs/quota_v2.c b/fs/quota_v2.c index c519a58..23b647f 100644 --- a/fs/quota_v2.c +++ b/fs/quota_v2.c @@ -59,6 +59,9 @@ static int v2_read_file_info(struct super_block *sb, int type) sb->s_id); return -1; } + /* limits are stored as unsigned 32-bit data */ + info->dqi_maxblimit = 0xffffffff; + info->dqi_maxilimit = 0xffffffff; info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace); info->dqi_igrace = le32_to_cpu(dinfo.dqi_igrace); info->dqi_flags = le32_to_cpu(dinfo.dqi_flags); diff --git a/fs/reiserfs/bitmap.c b/fs/reiserfs/bitmap.c index f491ceb..4646caa 100644 --- a/fs/reiserfs/bitmap.c +++ b/fs/reiserfs/bitmap.c @@ -479,7 +479,7 @@ static void __discard_prealloc(struct reiserfs_transaction_handle *th, if (ei->i_prealloc_count < 0) reiserfs_warning(th->t_super, "zam-4001:%s: inode has negative prealloc blocks count.", - __FUNCTION__); + __func__); #endif while (ei->i_prealloc_count > 0) { reiserfs_free_prealloc_block(th, inode, ei->i_prealloc_block); @@ -517,7 +517,7 @@ void reiserfs_discard_all_prealloc(struct reiserfs_transaction_handle *th) if (!ei->i_prealloc_count) { reiserfs_warning(th->t_super, "zam-4001:%s: inode is in prealloc list but has no preallocated blocks.", - __FUNCTION__); + __func__); } #endif __discard_prealloc(th, ei); @@ -632,7 +632,7 @@ int reiserfs_parse_alloc_options(struct super_block *s, char *options) } reiserfs_warning(s, "zam-4001: %s : unknown option - %s", - __FUNCTION__, this_char); + __func__, this_char); return 1; } @@ -1254,7 +1254,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb, bh = sb_bread(sb, block); if (bh == NULL) reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) " - "reading failed", __FUNCTION__, block); + "reading failed", __func__, block); else { if (buffer_locked(bh)) { PROC_INFO_INC(sb, scan_bitmap.wait); diff --git a/fs/reiserfs/do_balan.c b/fs/reiserfs/do_balan.c index 7ee4208..2f87f5b 100644 --- a/fs/reiserfs/do_balan.c +++ b/fs/reiserfs/do_balan.c @@ -1464,29 +1464,29 @@ static int balance_leaf(struct tree_balance *tb, struct item_head *ih, /* item h } else /* item falls wholly into S_new[i] */ { - int ret_val; + int leaf_mi; struct item_head *pasted; #ifdef CONFIG_REISERFS_CHECK - struct item_head *ih = + struct item_head *ih_check = B_N_PITEM_HEAD(tbS0, item_pos); - if (!is_direntry_le_ih(ih) - && (pos_in_item != ih_item_len(ih) + if (!is_direntry_le_ih(ih_check) + && (pos_in_item != ih_item_len(ih_check) || tb->insert_size[0] <= 0)) reiserfs_panic(tb->tb_sb, "PAP-12235: balance_leaf: pos_in_item must be equal to ih_item_len"); #endif /* CONFIG_REISERFS_CHECK */ - ret_val = + leaf_mi = leaf_move_items(LEAF_FROM_S_TO_SNEW, tb, snum[i], sbytes[i], S_new[i]); - RFALSE(ret_val, + RFALSE(leaf_mi, "PAP-12240: unexpected value returned by leaf_move_items (%d)", - ret_val); + leaf_mi); /* paste into item */ bi.tb = tb; diff --git a/fs/reiserfs/ioctl.c b/fs/reiserfs/ioctl.c index 74363a7..8303320 100644 --- a/fs/reiserfs/ioctl.c +++ b/fs/reiserfs/ioctl.c @@ -12,8 +12,6 @@ #include <linux/smp_lock.h> #include <linux/compat.h> -static int reiserfs_unpack(struct inode *inode, struct file *filp); - /* ** reiserfs_ioctl - handler for ioctl for inode ** supported commands: @@ -159,7 +157,7 @@ int reiserfs_prepare_write(struct file *f, struct page *page, ** Function try to convert tail from direct item into indirect. ** It set up nopack attribute in the REISERFS_I(inode)->nopack */ -static int reiserfs_unpack(struct inode *inode, struct file *filp) +int reiserfs_unpack(struct inode *inode, struct file *filp) { int retval = 0; int index; diff --git a/fs/reiserfs/journal.c b/fs/reiserfs/journal.c index 060eb3f..da86042 100644 --- a/fs/reiserfs/journal.c +++ b/fs/reiserfs/journal.c @@ -1187,7 +1187,7 @@ static int flush_commit_list(struct super_block *s, if (retval) reiserfs_abort(s, retval, "Journal write error in %s", - __FUNCTION__); + __func__); put_fs_excl(); return retval; } @@ -1534,7 +1534,7 @@ static int flush_journal_list(struct super_block *s, reiserfs_warning(s, "clm-2082: Unable to flush buffer %llu in %s", (unsigned long long)saved_bh-> - b_blocknr, __FUNCTION__); + b_blocknr, __func__); } free_cnode: last = cn; @@ -1586,7 +1586,7 @@ static int flush_journal_list(struct super_block *s, if (err) reiserfs_abort(s, -EIO, "Write error while pushing transaction to disk in %s", - __FUNCTION__); + __func__); flush_older_and_return: /* before we can update the journal header block, we _must_ flush all @@ -1616,7 +1616,7 @@ static int flush_journal_list(struct super_block *s, if (err) reiserfs_abort(s, -EIO, "Write error while updating journal header in %s", - __FUNCTION__); + __func__); } remove_all_from_journal_list(s, jl, 0); list_del_init(&jl->j_list); @@ -4316,5 +4316,5 @@ static void __reiserfs_journal_abort_soft(struct super_block *sb, int errno) void reiserfs_journal_abort(struct super_block *sb, int errno) { - return __reiserfs_journal_abort_soft(sb, errno); + __reiserfs_journal_abort_soft(sb, errno); } diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 8867533..c1add28 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -301,7 +301,7 @@ static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen, path_to_entry, de); if (retval == IO_ERROR) { reiserfs_warning(dir->i_sb, "zam-7001: io error in %s", - __FUNCTION__); + __func__); return IO_ERROR; } @@ -496,7 +496,7 @@ static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, reiserfs_warning(dir->i_sb, "zam-7002:%s: \"reiserfs_find_entry\" " "has returned unexpected value (%d)", - __FUNCTION__, retval); + __func__, retval); } return -EEXIST; @@ -907,7 +907,7 @@ static int reiserfs_rmdir(struct inode *dir, struct dentry *dentry) if (inode->i_nlink != 2 && inode->i_nlink != 1) reiserfs_warning(inode->i_sb, "%s: empty directory has nlink " - "!= 2 (%d)", __FUNCTION__, inode->i_nlink); + "!= 2 (%d)", __func__, inode->i_nlink); clear_nlink(inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; @@ -984,7 +984,7 @@ static int reiserfs_unlink(struct inode *dir, struct dentry *dentry) if (!inode->i_nlink) { reiserfs_warning(inode->i_sb, "%s: deleting nonexistent file " - "(%s:%lu), %d", __FUNCTION__, + "(%s:%lu), %d", __func__, reiserfs_bdevname(inode->i_sb), inode->i_ino, inode->i_nlink); inode->i_nlink = 1; diff --git a/fs/reiserfs/objectid.c b/fs/reiserfs/objectid.c index 65feba4..ea0cf8c 100644 --- a/fs/reiserfs/objectid.c +++ b/fs/reiserfs/objectid.c @@ -61,7 +61,7 @@ __u32 reiserfs_get_unused_objectid(struct reiserfs_transaction_handle *th) /* comment needed -Hans */ unused_objectid = le32_to_cpu(map[1]); if (unused_objectid == U32_MAX) { - reiserfs_warning(s, "%s: no more object ids", __FUNCTION__); + reiserfs_warning(s, "%s: no more object ids", __func__); reiserfs_restore_prepared_buffer(s, SB_BUFFER_WITH_SB(s)); return 0; } @@ -114,7 +114,7 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th, if (objectid_to_release == le32_to_cpu(map[i])) { /* This incrementation unallocates the objectid. */ //map[i]++; - map[i] = cpu_to_le32(le32_to_cpu(map[i]) + 1); + le32_add_cpu(&map[i], 1); /* Did we unallocate the last member of an odd sequence, and can shrink oids? */ if (map[i] == map[i + 1]) { @@ -138,8 +138,7 @@ void reiserfs_release_objectid(struct reiserfs_transaction_handle *th, /* size of objectid map is not changed */ if (objectid_to_release + 1 == le32_to_cpu(map[i + 1])) { //objectid_map[i+1]--; - map[i + 1] = - cpu_to_le32(le32_to_cpu(map[i + 1]) - 1); + le32_add_cpu(&map[i + 1], -1); return; } diff --git a/fs/reiserfs/stree.c b/fs/reiserfs/stree.c index d2db241..abbc64d 100644 --- a/fs/reiserfs/stree.c +++ b/fs/reiserfs/stree.c @@ -1419,8 +1419,7 @@ int reiserfs_delete_object(struct reiserfs_transaction_handle *th, inode_generation = &REISERFS_SB(th->t_super)->s_rs->s_inode_generation; - *inode_generation = - cpu_to_le32(le32_to_cpu(*inode_generation) + 1); + le32_add_cpu(inode_generation, 1); } /* USE_INODE_GENERATION_COUNTER */ #endif diff --git a/fs/reiserfs/super.c b/fs/reiserfs/super.c index 393cc22..ed424d7 100644 --- a/fs/reiserfs/super.c +++ b/fs/reiserfs/super.c @@ -304,7 +304,7 @@ static int finish_unfinished(struct super_block *s) /* Turn quotas off */ for (i = 0; i < MAXQUOTAS; i++) { if (sb_dqopt(s)->files[i]) - vfs_quota_off_mount(s, i); + vfs_quota_off(s, i, 0); } if (ms_active_set) /* Restore the flag back */ @@ -634,7 +634,7 @@ static int reiserfs_acquire_dquot(struct dquot *); static int reiserfs_release_dquot(struct dquot *); static int reiserfs_mark_dquot_dirty(struct dquot *); static int reiserfs_write_info(struct super_block *, int); -static int reiserfs_quota_on(struct super_block *, int, int, char *); +static int reiserfs_quota_on(struct super_block *, int, int, char *, int); static struct dquot_operations reiserfs_quota_operations = { .initialize = reiserfs_dquot_initialize, @@ -1890,8 +1890,14 @@ static int reiserfs_dquot_drop(struct inode *inode) ret = journal_begin(&th, inode->i_sb, 2 * REISERFS_QUOTA_DEL_BLOCKS(inode->i_sb)); - if (ret) + if (ret) { + /* + * We call dquot_drop() anyway to at least release references + * to quota structures so that umount does not hang. + */ + dquot_drop(inode); goto out; + } ret = dquot_drop(inode); err = journal_end(&th, inode->i_sb, @@ -2015,13 +2021,17 @@ static int reiserfs_quota_on_mount(struct super_block *sb, int type) * Standard function to be called on quota_on */ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, - char *path) + char *path, int remount) { int err; struct nameidata nd; + struct inode *inode; if (!(REISERFS_SB(sb)->s_mount_opt & (1 << REISERFS_QUOTA))) return -EINVAL; + /* No more checks needed? Path and format_id are bogus anyway... */ + if (remount) + return vfs_quota_on(sb, type, format_id, path, 1); err = path_lookup(path, LOOKUP_FOLLOW, &nd); if (err) return err; @@ -2030,18 +2040,24 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, path_put(&nd.path); return -EXDEV; } + inode = nd.path.dentry->d_inode; /* We must not pack tails for quota files on reiserfs for quota IO to work */ - if (!(REISERFS_I(nd.path.dentry->d_inode)->i_flags & i_nopack_mask)) { - reiserfs_warning(sb, - "reiserfs: Quota file must have tail packing disabled."); - path_put(&nd.path); - return -EINVAL; + if (!(REISERFS_I(inode)->i_flags & i_nopack_mask)) { + err = reiserfs_unpack(inode, NULL); + if (err) { + reiserfs_warning(sb, + "reiserfs: Unpacking tail of quota file failed" + " (%d). Cannot turn on quotas.", err); + path_put(&nd.path); + return -EINVAL; + } + mark_inode_dirty(inode); } /* Not journalling quota? No more tests needed... */ if (!REISERFS_SB(sb)->s_qf_names[USRQUOTA] && !REISERFS_SB(sb)->s_qf_names[GRPQUOTA]) { path_put(&nd.path); - return vfs_quota_on(sb, type, format_id, path); + return vfs_quota_on(sb, type, format_id, path, 0); } /* Quotafile not of fs root? */ if (nd.path.dentry->d_parent->d_inode != sb->s_root->d_inode) @@ -2049,7 +2065,7 @@ static int reiserfs_quota_on(struct super_block *sb, int type, int format_id, "reiserfs: Quota file not on filesystem root. " "Journalled quota will not work."); path_put(&nd.path); - return vfs_quota_on(sb, type, format_id, path); + return vfs_quota_on(sb, type, format_id, path, 0); } /* Read data from quotafile - avoid pagecache and such because we cannot afford @@ -179,7 +179,7 @@ void deactivate_super(struct super_block *s) if (atomic_dec_and_lock(&s->s_active, &sb_lock)) { s->s_count -= S_BIAS-1; spin_unlock(&sb_lock); - DQUOT_OFF(s); + DQUOT_OFF(s, 0); down_write(&s->s_umount); fs->kill_sb(s); put_filesystem(fs); @@ -608,6 +608,7 @@ retry: int do_remount_sb(struct super_block *sb, int flags, void *data, int force) { int retval; + int remount_rw; #ifdef CONFIG_BLOCK if (!(flags & MS_RDONLY) && bdev_read_only(sb->s_bdev)) @@ -625,8 +626,11 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) mark_files_ro(sb); else if (!fs_may_remount_ro(sb)) return -EBUSY; - DQUOT_OFF(sb); + retval = DQUOT_OFF(sb, 1); + if (retval < 0 && retval != -ENOSYS) + return -EBUSY; } + remount_rw = !(flags & MS_RDONLY) && (sb->s_flags & MS_RDONLY); if (sb->s_op->remount_fs) { lock_super(sb); @@ -636,6 +640,8 @@ int do_remount_sb(struct super_block *sb, int flags, void *data, int force) return retval; } sb->s_flags = (sb->s_flags & ~MS_RMT_MASK) | (flags & MS_RMT_MASK); + if (remount_rw) + DQUOT_ON_REMOUNT(sb); return 0; } diff --git a/fs/udf/namei.c b/fs/udf/namei.c index ba5537d..2b34c8c 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c @@ -890,7 +890,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { kernel_lb_addr eloc; - uint32_t elen; + uint32_t bsize; block = udf_new_block(inode->i_sb, inode, iinfo->i_location.partitionReferenceNum, @@ -903,9 +903,9 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, eloc.logicalBlockNum = block; eloc.partitionReferenceNum = iinfo->i_location.partitionReferenceNum; - elen = inode->i_sb->s_blocksize; - iinfo->i_lenExtents = elen; - udf_add_aext(inode, &epos, eloc, elen, 0); + bsize = inode->i_sb->s_blocksize; + iinfo->i_lenExtents = bsize; + udf_add_aext(inode, &epos, eloc, bsize, 0); brelse(epos.bh); block = udf_get_pblock(inode->i_sb, block, diff --git a/fs/ufs/balloc.c b/fs/ufs/balloc.c index 1e7598f..0d9ada1 100644 --- a/fs/ufs/balloc.c +++ b/fs/ufs/balloc.c @@ -277,7 +277,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, if (!page)/* it was truncated */ continue; if (IS_ERR(page)) {/* or EIO */ - ufs_error(inode->i_sb, __FUNCTION__, + ufs_error(inode->i_sb, __func__, "read of page %llu failed\n", (unsigned long long)index); continue; @@ -308,7 +308,7 @@ static void ufs_change_blocknr(struct inode *inode, sector_t beg, ll_rw_block(READ, 1, &bh); wait_on_buffer(bh); if (!buffer_uptodate(bh)) { - ufs_error(inode->i_sb, __FUNCTION__, + ufs_error(inode->i_sb, __func__, "read of block failed\n"); break; } diff --git a/fs/ufs/dir.c b/fs/ufs/dir.c index ef563fc..df0bef1 100644 --- a/fs/ufs/dir.c +++ b/fs/ufs/dir.c @@ -179,7 +179,7 @@ bad_entry: goto fail; Eend: p = (struct ufs_dir_entry *)(kaddr + offs); - ufs_error(sb, __FUNCTION__, + ufs_error(sb, __func__, "entry in directory #%lu spans the page boundary" "offset=%lu", dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs); @@ -284,7 +284,7 @@ struct ufs_dir_entry *ufs_find_entry(struct inode *dir, struct dentry *dentry, kaddr += ufs_last_byte(dir, n) - reclen; while ((char *) de <= kaddr) { if (de->d_reclen == 0) { - ufs_error(dir->i_sb, __FUNCTION__, + ufs_error(dir->i_sb, __func__, "zero-length directory entry"); ufs_put_page(page); goto out; @@ -356,7 +356,7 @@ int ufs_add_link(struct dentry *dentry, struct inode *inode) goto got_it; } if (de->d_reclen == 0) { - ufs_error(dir->i_sb, __FUNCTION__, + ufs_error(dir->i_sb, __func__, "zero-length directory entry"); err = -EIO; goto out_unlock; @@ -456,7 +456,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) struct page *page = ufs_get_page(inode, n); if (IS_ERR(page)) { - ufs_error(sb, __FUNCTION__, + ufs_error(sb, __func__, "bad page in #%lu", inode->i_ino); filp->f_pos += PAGE_CACHE_SIZE - offset; @@ -475,7 +475,7 @@ ufs_readdir(struct file *filp, void *dirent, filldir_t filldir) limit = kaddr + ufs_last_byte(inode, n) - UFS_DIR_REC_LEN(1); for ( ;(char*)de <= limit; de = ufs_next_entry(sb, de)) { if (de->d_reclen == 0) { - ufs_error(sb, __FUNCTION__, + ufs_error(sb, __func__, "zero-length directory entry"); ufs_put_page(page); return -EIO; @@ -536,7 +536,7 @@ int ufs_delete_entry(struct inode *inode, struct ufs_dir_entry *dir, while ((char*)de < (char*)dir) { if (de->d_reclen == 0) { - ufs_error(inode->i_sb, __FUNCTION__, + ufs_error(inode->i_sb, __func__, "zero-length directory entry"); err = -EIO; goto out; @@ -633,7 +633,7 @@ int ufs_empty_dir(struct inode * inode) while ((char *)de <= kaddr) { if (de->d_reclen == 0) { - ufs_error(inode->i_sb, __FUNCTION__, + ufs_error(inode->i_sb, __func__, "zero-length directory entry: " "kaddr=%p, de=%p\n", kaddr, de); goto not_empty; diff --git a/fs/ufs/inode.c b/fs/ufs/inode.c index 5446b88..39f8778 100644 --- a/fs/ufs/inode.c +++ b/fs/ufs/inode.c @@ -929,7 +929,7 @@ void ufs_delete_inode (struct inode * inode) old_i_size = inode->i_size; inode->i_size = 0; if (inode->i_blocks && ufs_truncate(inode, old_i_size)) - ufs_warning(inode->i_sb, __FUNCTION__, "ufs_truncate failed\n"); + ufs_warning(inode->i_sb, __func__, "ufs_truncate failed\n"); ufs_free_inode (inode); unlock_kernel(); return; diff --git a/fs/ufs/swab.h b/fs/ufs/swab.h index 1683d2b..8d974c4 100644 --- a/fs/ufs/swab.h +++ b/fs/ufs/swab.h @@ -40,25 +40,7 @@ cpu_to_fs64(struct super_block *sbp, u64 n) return (__force __fs64)cpu_to_be64(n); } -static __inline u32 -fs64_add(struct super_block *sbp, u32 *n, int d) -{ - if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - return *n = cpu_to_le64(le64_to_cpu(*n)+d); - else - return *n = cpu_to_be64(be64_to_cpu(*n)+d); -} - -static __inline u32 -fs64_sub(struct super_block *sbp, u32 *n, int d) -{ - if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - return *n = cpu_to_le64(le64_to_cpu(*n)-d); - else - return *n = cpu_to_be64(be64_to_cpu(*n)-d); -} - -static __inline u32 +static inline u32 fs32_to_cpu(struct super_block *sbp, __fs32 n) { if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) @@ -80,18 +62,18 @@ static inline void fs32_add(struct super_block *sbp, __fs32 *n, int d) { if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)+d); + le32_add_cpu((__le32 *)n, d); else - *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)+d); + be32_add_cpu((__be32 *)n, d); } static inline void fs32_sub(struct super_block *sbp, __fs32 *n, int d) { if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - *(__le32 *)n = cpu_to_le32(le32_to_cpu(*(__le32 *)n)-d); + le32_add_cpu((__le32 *)n, -d); else - *(__be32 *)n = cpu_to_be32(be32_to_cpu(*(__be32 *)n)-d); + be32_add_cpu((__be32 *)n, -d); } static inline u16 @@ -116,18 +98,18 @@ static inline void fs16_add(struct super_block *sbp, __fs16 *n, int d) { if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)+d); + le16_add_cpu((__le16 *)n, d); else - *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)+d); + be16_add_cpu((__be16 *)n, d); } static inline void fs16_sub(struct super_block *sbp, __fs16 *n, int d) { if (UFS_SB(sbp)->s_bytesex == BYTESEX_LE) - *(__le16 *)n = cpu_to_le16(le16_to_cpu(*(__le16 *)n)-d); + le16_add_cpu((__le16 *)n, -d); else - *(__be16 *)n = cpu_to_be16(be16_to_cpu(*(__be16 *)n)-d); + be16_add_cpu((__be16 *)n, -d); } #endif /* _UFS_SWAB_H */ diff --git a/fs/ufs/ufs.h b/fs/ufs/ufs.h index fcb9231..244a1aa 100644 --- a/fs/ufs/ufs.h +++ b/fs/ufs/ufs.h @@ -66,7 +66,7 @@ struct ufs_inode_info { #ifdef CONFIG_UFS_DEBUG # define UFSD(f, a...) { \ printk ("UFSD (%s, %d): %s:", \ - __FILE__, __LINE__, __FUNCTION__); \ + __FILE__, __LINE__, __func__); \ printk (f, ## a); \ } #else diff --git a/fs/vfat/namei.c b/fs/vfat/namei.c index cd450be..5b66162 100644 --- a/fs/vfat/namei.c +++ b/fs/vfat/namei.c @@ -176,15 +176,10 @@ static inline int vfat_is_used_badchars(const wchar_t *s, int len) for (i = 0; i < len; i++) if (vfat_bad_char(s[i])) return -EINVAL; - return 0; -} -static int vfat_valid_longname(const unsigned char *name, unsigned int len) -{ - if (name[len - 1] == ' ') + if (s[i - 1] == ' ') /* last character cannot be space */ return -EINVAL; - if (len >= 256) - return -ENAMETOOLONG; + return 0; } @@ -477,7 +472,7 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, if (utf8) { int name_len = strlen(name); - *outlen = utf8_mbstowcs((wchar_t *)outname, name, PAGE_SIZE); + *outlen = utf8_mbstowcs((wchar_t *)outname, name, PATH_MAX); /* * We stripped '.'s before and set len appropriately, @@ -485,11 +480,14 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, */ *outlen -= (name_len - len); + if (*outlen > 255) + return -ENAMETOOLONG; + op = &outname[*outlen * sizeof(wchar_t)]; } else { if (nls) { for (i = 0, ip = name, op = outname, *outlen = 0; - i < len && *outlen <= 260; + i < len && *outlen <= 255; *outlen += 1) { if (escape && (*ip == ':')) { @@ -525,18 +523,20 @@ xlate_to_uni(const unsigned char *name, int len, unsigned char *outname, op += 2; } } + if (i < len) + return -ENAMETOOLONG; } else { for (i = 0, ip = name, op = outname, *outlen = 0; - i < len && *outlen <= 260; + i < len && *outlen <= 255; i++, *outlen += 1) { *op++ = *ip++; *op++ = 0; } + if (i < len) + return -ENAMETOOLONG; } } - if (*outlen > 260) - return -ENAMETOOLONG; *longlen = *outlen; if (*outlen % 13) { @@ -565,7 +565,6 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, struct fat_mount_options *opts = &sbi->options; struct msdos_dir_slot *ps; struct msdos_dir_entry *de; - unsigned long page; unsigned char cksum, lcase; unsigned char msdos_name[MSDOS_NAME]; wchar_t *uname; @@ -574,15 +573,11 @@ static int vfat_build_slots(struct inode *dir, const unsigned char *name, loff_t offset; *nr_slots = 0; - err = vfat_valid_longname(name, len); - if (err) - return err; - page = __get_free_page(GFP_KERNEL); - if (!page) + uname = __getname(); + if (!uname) return -ENOMEM; - uname = (wchar_t *)page; err = xlate_to_uni(name, len, (unsigned char *)uname, &ulen, &usize, opts->unicode_xlate, opts->utf8, sbi->nls_io); if (err) @@ -634,7 +629,7 @@ shortname: de->starthi = cpu_to_le16(cluster >> 16); de->size = 0; out_free: - free_page(page); + __putname(uname); return err; } @@ -1003,7 +998,7 @@ static const struct inode_operations vfat_dir_inode_operations = { .mkdir = vfat_mkdir, .rmdir = vfat_rmdir, .rename = vfat_rename, - .setattr = fat_notify_change, + .setattr = fat_setattr, .getattr = fat_getattr, }; |