From 2489007e7d740ccbc3e0a202914e243ad5178787 Mon Sep 17 00:00:00 2001 From: codeworkx Date: Sat, 22 Sep 2012 09:48:20 +0200 Subject: merge opensource jb u5 Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2 --- fs/bio.c | 4 ++++ fs/buffer.c | 46 ++++++++++++++++++++++++++++++++++++++++ fs/drop_caches.c | 16 ++++++++++++++ fs/ecryptfs/miscdev.c | 2 +- fs/ext4/dir.c | 4 ++++ fs/ext4/ext4.h | 5 +++++ fs/ext4/ialloc.c | 6 +++++- fs/ext4/inode.c | 11 ++++++++++ fs/ext4/mballoc.c | 7 +++++++ fs/ext4/namei.c | 14 ++++++++++--- fs/ext4/super.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++++++ fs/fuse/dev.c | 20 ++++++++++-------- fs/jbd2/checkpoint.c | 3 +-- fs/jbd2/transaction.c | 12 +++++++++++ fs/proc/base.c | 40 +++++++++++++++++++++++++++++++++-- 15 files changed, 230 insertions(+), 18 deletions(-) (limited to 'fs') diff --git a/fs/bio.c b/fs/bio.c index 9bfade8..59d91d4 100644 --- a/fs/bio.c +++ b/fs/bio.c @@ -1689,4 +1689,8 @@ static int __init init_bio(void) return 0; } +#ifdef CONFIG_FAST_RESUME +beforeresume_initcall(init_bio); +#else subsys_initcall(init_bio); +#endif diff --git a/fs/buffer.c b/fs/buffer.c index 1a80b04..c780e39 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -996,8 +997,13 @@ grow_dev_page(struct block_device *bdev, sector_t block, struct page *page; struct buffer_head *bh; +#ifdef CONFIG_DMA_CMA + page = find_or_create_page(inode->i_mapping, index, + (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)); +#else page = find_or_create_page(inode->i_mapping, index, (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE); +#endif if (!page) return NULL; @@ -1270,6 +1276,16 @@ static void bh_lru_install(struct buffer_head *bh) { struct buffer_head *evictee = NULL; +#ifdef CONFIG_DMA_CMA + /* + * Pages are busy when their buffers stay on bh_lru list. + * The CMA pages are expected to be migrated at any time, + * therefore they should never go on any local LRU lists. + */ + if (is_cma_pageblock(bh->b_page)) + return; +#endif + check_irqs_on(); bh_lru_lock(); if (__this_cpu_read(bh_lrus.bhs[0]) != bh) { @@ -1438,6 +1454,35 @@ void invalidate_bh_lrus(void) } EXPORT_SYMBOL_GPL(invalidate_bh_lrus); +#ifdef CONFIG_DMA_CMA +static void evict_bh_lru(void *arg) +{ + struct bh_lru *b = &get_cpu_var(bh_lrus); + struct buffer_head *bh = arg; + int i; + + for (i = 0; i < BH_LRU_SIZE; i++) { + if (b->bhs[i] == bh) { + printk(KERN_INFO "%s[%d] drop buffer head %p.\n", + __func__, __LINE__, b->bhs[i]); + brelse(b->bhs[i]); + b->bhs[i] = NULL; + break; + } + } + + put_cpu_var(bh_lrus); +} + +void evict_bh_lrus(struct buffer_head *bh) +{ + on_each_cpu(evict_bh_lru, bh, 1); +} +#else +static inline void evict_bh_lrus(struct buffer_head *bh) {} +#endif +EXPORT_SYMBOL_GPL(evict_bh_lrus); + void set_bh_page(struct buffer_head *bh, struct page *page, unsigned long offset) { @@ -3085,6 +3130,7 @@ drop_buffers(struct page *page, struct buffer_head **buffers_to_free) bh = head; do { + evict_bh_lrus(bh); if (buffer_write_io_error(bh) && page->mapping) set_bit(AS_EIO, &page->mapping->flags); if (buffer_busy(bh)) diff --git a/fs/drop_caches.c b/fs/drop_caches.c index c00e055..cd5575b 100644 --- a/fs/drop_caches.c +++ b/fs/drop_caches.c @@ -49,6 +49,16 @@ static void drop_slab(void) } while (nr_objects > 10); } +#ifdef CONFIG_DMA_CMA +void perform_drop_caches(unsigned int mode) +{ + if (mode & 1) + iterate_supers(drop_pagecache_sb, NULL); + if (mode & 2) + drop_slab(); +} +#endif + int drop_caches_sysctl_handler(ctl_table *table, int write, void __user *buffer, size_t *length, loff_t *ppos) { @@ -57,11 +67,17 @@ int drop_caches_sysctl_handler(ctl_table *table, int write, ret = proc_dointvec_minmax(table, write, buffer, length, ppos); if (ret) return ret; + +#ifndef CONFIG_DMA_CMA if (write) { if (sysctl_drop_caches & 1) iterate_supers(drop_pagecache_sb, NULL); if (sysctl_drop_caches & 2) drop_slab(); } +#else + if (write) + perform_drop_caches(sysctl_drop_caches); +#endif return 0; } diff --git a/fs/ecryptfs/miscdev.c b/fs/ecryptfs/miscdev.c index 0dc5a3d..7b132c2 100644 --- a/fs/ecryptfs/miscdev.c +++ b/fs/ecryptfs/miscdev.c @@ -421,7 +421,7 @@ ecryptfs_miscdev_write(struct file *file, const char __user *buf, || count > (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES)) { printk(KERN_WARNING "%s: Acceptable packet size range is " - "[%d-%lu], but amount of data written is [%zu].", + "[%d-%u], but amount of data written is [%zu].", __func__, (1 + 4 + 1), (1 + 4 + 2 + sizeof(struct ecryptfs_message) + 4 + ECRYPTFS_MAX_ENCRYPTED_KEY_BYTES), count); diff --git a/fs/ext4/dir.c b/fs/ext4/dir.c index 164c560..f00b0a0 100644 --- a/fs/ext4/dir.c +++ b/fs/ext4/dir.c @@ -90,6 +90,10 @@ int __ext4_check_dir_entry(const char *function, unsigned int line, else return 0; + /* for debugging, sangwoo2.lee */ + print_bh(dir->i_sb, bh, 0, EXT4_BLOCK_SIZE(dir->i_sb)); + /* for debugging */ + if (filp) ext4_error_file(filp, function, line, bh ? bh->b_blocknr : 0, "bad entry in directory: %s - offset=%u(%u), " diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 1a34c1c..73490d9 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -1931,6 +1931,11 @@ extern __le16 ext4_group_desc_csum(struct ext4_sb_info *sbi, __u32 group, struct ext4_group_desc *gdp); extern int ext4_group_desc_csum_verify(struct ext4_sb_info *sbi, __u32 group, struct ext4_group_desc *gdp); +/* for debugging, sangwoo2.lee */ +extern void print_bh(struct super_block *sb, struct buffer_head *bh, int start, int len); +extern void print_block_data(struct super_block *sb, sector_t blocknr, unsigned char *data_to_dump, int start, int len); +/* for debugging */ + static inline ext4_fsblk_t ext4_blocks_count(struct ext4_super_block *es) { diff --git a/fs/ext4/ialloc.c b/fs/ext4/ialloc.c index 21bb2f6..b5c25ba 100644 --- a/fs/ext4/ialloc.c +++ b/fs/ext4/ialloc.c @@ -285,8 +285,12 @@ out: if (!fatal) fatal = err; ext4_mark_super_dirty(sb); - } else + } else { + /* for debugging, sangwoo2.lee */ + print_bh(sb, bitmap_bh, 0, EXT4_BLOCK_SIZE(sb)); + /* for debugging */ ext4_error(sb, "bit already cleared for inode %lu", ino); + } error_return: brelse(bitmap_bh); diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 55d3e51..83cd4cf 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -1182,6 +1182,11 @@ static int __check_block_validity(struct inode *inode, const char *func, { if (!ext4_data_block_valid(EXT4_SB(inode->i_sb), map->m_pblk, map->m_len)) { + /* for debugging, sangwoo2.lee */ + printk(KERN_ERR "printing inode..\n"); + print_block_data(inode->i_sb, 0, (unsigned char *)inode, 0, EXT4_INODE_SIZE(inode->i_sb)); + /* for debugging */ + ext4_error_inode(inode, func, line, map->m_pblk, "lblock %lu mapped to illegal pblock " "(length %d)", (unsigned long) map->m_lblk, @@ -4941,6 +4946,12 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino) if (inode->i_mode == 0 || !(EXT4_SB(inode->i_sb)->s_mount_state & EXT4_ORPHAN_FS)) { /* this inode is deleted */ + /* for debugging, sangwoo2.lee */ + printk(KERN_ERR "iloc info, offset : %lu, group# : %u\n", iloc.offset, iloc.block_group); + printk(KERN_ERR "sb info, inodes per group : %lu, inode size : %d\n", EXT4_SB(sb)->s_inodes_per_group, EXT4_SB(sb)->s_inode_size); + print_bh(sb, iloc.bh, 0, EXT4_BLOCK_SIZE(sb)); + /* for debugging */ + ret = -ESTALE; goto bad_inode; } diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 0f1be7f..d37c2e3 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -731,6 +731,10 @@ void ext4_mb_generate_buddy(struct super_block *sb, grp->bb_fragments = fragments; if (free != grp->bb_free) { + /* for more specific debugging, sangwoo2.lee */ + print_block_data(sb, 0, bitmap, 0, EXT4_BLOCK_SIZE(sb)); + /* for more specific debugging */ + ext4_grp_locked_error(sb, group, 0, 0, "%u blocks in bitmap, %u in gd", free, grp->bb_free); @@ -1338,6 +1342,9 @@ static void mb_free_blocks(struct inode *inode, struct ext4_buddy *e4b, blocknr = ext4_group_first_block_no(sb, e4b->bd_group); blocknr += block; + /* for debugging, sangwoo2.lee */ + print_block_data(sb, blocknr, EXT4_MB_BITMAP(e4b), 0, EXT4_BLOCK_SIZE(sb)); + /* for debugging */ ext4_grp_locked_error(sb, e4b->bd_group, inode ? inode->i_ino : 0, blocknr, diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c index 3d36d5a..5767c50 100644 --- a/fs/ext4/namei.c +++ b/fs/ext4/namei.c @@ -1031,17 +1031,25 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, stru inode = NULL; if (bh) { __u32 ino = le32_to_cpu(de->inode); - brelse(bh); if (!ext4_valid_inum(dir->i_sb, ino)) { + /* for debugging, sangwoo2.lee */ + printk(KERN_ERR "Name of directory entry has bad inode# : %s\n", de->name); + print_bh(dir->i_sb, bh, 0, EXT4_BLOCK_SIZE(dir->i_sb)); + /* for debugging */ + brelse(bh); + EXT4_ERROR_INODE(dir, "bad inode number: %u", ino); return ERR_PTR(-EIO); } + brelse(bh); + inode = ext4_iget(dir->i_sb, ino); if (IS_ERR(inode)) { if (PTR_ERR(inode) == -ESTALE) { + /* In case of -ESTALE, printing debugging data is already done in ext4_iget */ EXT4_ERROR_INODE(dir, - "deleted inode referenced: %u", - ino); + "deleted inode referenced: %u at parent inode : %lu", + ino, dir->i_ino); return ERR_PTR(-EIO); } else { return ERR_CAST(inode); diff --git a/fs/ext4/super.c b/fs/ext4/super.c index df121b2..e10a393 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -433,6 +433,7 @@ void __ext4_error(struct super_block *sb, const char *function, printk(KERN_CRIT "EXT4-fs error (device %s): %s:%d: comm %s: %pV\n", sb->s_id, function, line, current->comm, &vaf); va_end(args); + save_error_info(sb, function, line); ext4_handle_error(sb); } @@ -3721,8 +3722,16 @@ no_journal: return 0; cantfind_ext4: + + /* for debugging, sangwoo2.lee */ + /* If you wanna use the flag 'MS_SILENT', call 'print_bh' function within below 'if'. */ + printk("printing data of superblock-bh\n"); + print_bh(sb, bh, 0, EXT4_BLOCK_SIZE(sb)); + /* for debugging */ + if (!silent) ext4_msg(sb, KERN_ERR, "VFS: Can't find ext4 filesystem"); + goto failed_mount; failed_mount4: @@ -4821,6 +4830,55 @@ out: #endif +/* for debugging, sangwoo2.lee */ +void print_bh(struct super_block *sb, struct buffer_head *bh, int start, int len) +{ + print_block_data(sb, bh->b_blocknr, bh->b_data, start, len); +} + +void print_block_data(struct super_block *sb, sector_t blocknr, unsigned char *data_to_dump, int start, int len) +{ + int i, j; + int bh_offset = (start / 16) * 16; + char row_data[17] = { 0, }; + char row_hex[50] = { 0, }; + char ch; + + printk(KERN_ERR "As EXT4-fs error, printing data in hex\n"); + printk(KERN_ERR " [partition info] s_id : %s, start block# : %llu\n", sb->s_id, sb->s_bdev->bd_part->start_sect); + printk(KERN_ERR " dump block# : %llu, start offset(byte) : %d, length(byte) : %d\n", blocknr, start, len); + printk(KERN_ERR "-----------------------------------------------------------------------------\n"); + + for (i = 0; i < (len + 15) / 16; i++) + { + for (j = 0; j < 16; j++) + { + ch = *(data_to_dump + bh_offset + j); + if (start <= bh_offset + j && start + len > bh_offset + j) + { + if (isascii(ch) && isprint(ch)) + sprintf(row_data + j, "%c", ch); + else + sprintf(row_data + j, "."); + + sprintf(row_hex + (j * 3), "%2.2x ", ch); + } + else + { + sprintf(row_data + j, " "); + sprintf(row_hex + (j * 3), "-- "); + } + } + + printk(KERN_ERR "0x%4.4x : %s | %s\n", bh_offset, row_hex, row_data); + bh_offset += 16; + + } + printk(KERN_ERR "-----------------------------------------------------------------------------\n"); +} +/* for debugging */ + + static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, const char *dev_name, void *data) { diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 5a6c6dc..9f241a4 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -242,25 +242,27 @@ static u64 fuse_get_unique(struct fuse_conn *fc) static inline int is_rt(struct fuse_conn *fc) { - /* Returns 1 if request is RT class */ - /* && FUSE_HANDLE_RT_CLASS bit of fc->flags is set. */ - /* FUSE_HANDLE_RT_CLASS bit is set by 'handle_rt_class' */ - /* mount option while mounting a file system. */ + /* + * Returns 1 if a process is RT class. + */ struct io_context *ioc; + int ret = 0; if (!fc) return 0; - if (!(fc->flags & FUSE_HANDLE_RT_CLASS)) /* Don't handle RT class */ return 0; ioc = get_io_context(GFP_NOWAIT, 0); - if (ioc && IOPRIO_PRIO_CLASS(ioc->ioprio) == IOPRIO_CLASS_RT) - return 1; + if(!ioc) + return 0; - return 0; -} + if(IOPRIO_PRIO_CLASS(ioc->ioprio) == IOPRIO_CLASS_RT) + ret = 1; + put_io_context(ioc); + return ret; +} static void queue_request(struct fuse_conn *fc, struct fuse_req *req) { diff --git a/fs/jbd2/checkpoint.c b/fs/jbd2/checkpoint.c index 2c62c5a..3a98cb0 100644 --- a/fs/jbd2/checkpoint.c +++ b/fs/jbd2/checkpoint.c @@ -543,8 +543,7 @@ int jbd2_cleanup_journal_tail(journal_t *journal) * correctness. Fortunately jbd2_cleanup_journal_tail() * doesn't get called all that often. */ - if ((journal->j_fs_dev != journal->j_dev) && - (journal->j_flags & JBD2_BARRIER)) + if (journal->j_flags & JBD2_BARRIER) blkdev_issue_flush(journal->j_fs_dev, GFP_KERNEL, NULL); if (!(journal->j_flags & JBD2_ABORT)) jbd2_journal_update_superblock(journal, 1); diff --git a/fs/jbd2/transaction.c b/fs/jbd2/transaction.c index 8088e00..f32ec4c 100644 --- a/fs/jbd2/transaction.c +++ b/fs/jbd2/transaction.c @@ -1683,8 +1683,20 @@ int jbd2_journal_try_to_free_buffers(journal_t *journal, __journal_try_to_free_buffer(journal, bh); jbd2_journal_put_journal_head(jh); jbd_unlock_bh_state(bh); +#ifndef CONFIG_DMA_CMA if (buffer_jbd(bh)) goto busy; +#else + if (buffer_jbd(bh)) { + /* + * Workaround: In case of CMA page, just commit journal. + */ + if (is_cma_pageblock(page)) + jbd2_journal_force_commit(journal); + else + goto busy; + } +#endif } while ((bh = bh->b_this_page) != head); ret = try_to_free_buffers(page); diff --git a/fs/proc/base.c b/fs/proc/base.c index 8cabc8d..1a140ca 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -841,8 +841,8 @@ static ssize_t mem_rw(struct file *file, char __user *buf, count -= this_len; } *ppos = addr; - mmput(mm); + mmput(mm); free: free_page((unsigned long) page); return copied; @@ -854,11 +854,16 @@ static ssize_t mem_read(struct file *file, char __user *buf, return mem_rw(file, buf, count, ppos, 0); } +#define mem_write NULL + +#ifndef mem_write +/* This is a security hazard */ static ssize_t mem_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { return mem_rw(file, (char __user*)buf, count, ppos, 1); } +#endif loff_t mem_lseek(struct file *file, loff_t offset, int orig) { @@ -881,7 +886,6 @@ static int mem_release(struct inode *inode, struct file *file) struct mm_struct *mm = file->private_data; if (mm) mmdrop(mm); - return 0; } @@ -1209,6 +1213,32 @@ static const struct file_operations proc_oom_score_adj_operations = { .llseek = default_llseek, }; +#ifdef CONFIG_ANDROID +static ssize_t oom_killed_read(struct file *file, char __user *buf, + size_t count, loff_t *ppos) +{ + struct task_struct *task = get_proc_task(file->f_path.dentry->d_inode); + char buffer[PROC_NUMBUF]; + int oom_killed = 0; + unsigned long flags; + size_t len; + + if (!task) + return -ESRCH; + if (lock_task_sighand(task, &flags)) { + oom_killed = sigismember(&task->pending.signal, SIGKILL); + unlock_task_sighand(task, &flags); + } + put_task_struct(task); + len = snprintf(buffer, sizeof(buffer), "%d\n", oom_killed); + return simple_read_from_buffer(buf, count, ppos, buffer, len); +} + +static const struct file_operations proc_oom_killed_operations = { + .read = oom_killed_read, +}; +#endif + #ifdef CONFIG_AUDITSYSCALL #define TMPBUFLEN 21 static ssize_t proc_loginuid_read(struct file * file, char __user * buf, @@ -2809,6 +2839,9 @@ static const struct pid_entry tgid_base_stuff[] = { INF("oom_score", S_IRUGO, proc_oom_score), ANDROID("oom_adj",S_IRUGO|S_IWUSR, oom_adjust), REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), +#ifdef CONFIG_ANDROID + REG("oom_killed", S_IRUGO, proc_oom_killed_operations), +#endif #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), @@ -3154,6 +3187,9 @@ static const struct pid_entry tid_base_stuff[] = { INF("oom_score", S_IRUGO, proc_oom_score), REG("oom_adj", S_IRUGO|S_IWUSR, proc_oom_adjust_operations), REG("oom_score_adj", S_IRUGO|S_IWUSR, proc_oom_score_adj_operations), +#ifdef CONFIG_ANDROID + REG("oom_killed", S_IRUGO, proc_oom_killed_operations), +#endif #ifdef CONFIG_AUDITSYSCALL REG("loginuid", S_IWUSR|S_IRUGO, proc_loginuid_operations), REG("sessionid", S_IRUGO, proc_sessionid_operations), -- cgit v1.1