aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/bio.c4
-rw-r--r--fs/buffer.c46
-rw-r--r--fs/drop_caches.c16
-rw-r--r--fs/ecryptfs/miscdev.c2
-rw-r--r--fs/ext4/dir.c4
-rw-r--r--fs/ext4/ext4.h5
-rw-r--r--fs/ext4/ialloc.c6
-rw-r--r--fs/ext4/inode.c11
-rw-r--r--fs/ext4/mballoc.c7
-rw-r--r--fs/ext4/namei.c14
-rw-r--r--fs/ext4/super.c58
-rw-r--r--fs/fuse/dev.c20
-rw-r--r--fs/jbd2/checkpoint.c3
-rw-r--r--fs/jbd2/transaction.c12
-rw-r--r--fs/proc/base.c40
15 files changed, 230 insertions, 18 deletions
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 <linux/bio.h>
#include <linux/notifier.h>
#include <linux/cpu.h>
+#include <linux/smp.h>
#include <linux/bitops.h>
#include <linux/mpage.h>
#include <linux/bit_spinlock.h>
@@ -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),