📄 quota-deadlock-on-pagelock-core.patch
字号:
#include <asm/byteorder.h> MODULE_AUTHOR("Jan Kara");@@ -41,23 +40,14 @@ static void v1_mem2disk_dqblk(struct v1_ static int v1_read_dqblk(struct dquot *dquot) { int type = dquot->dq_type;- struct file *filp;- mm_segment_t fs;- loff_t offset; struct v1_disk_dqblk dqblk; - filp = sb_dqopt(dquot->dq_sb)->files[type];- if (filp == (struct file *)NULL)+ if (!sb_dqopt(dquot->dq_sb)->files[type]) return -EINVAL; - /* Now we are sure filp is valid */- offset = v1_dqoff(dquot->dq_id); /* Set structure to 0s in case read fails/is after end of file */ memset(&dqblk, 0, sizeof(struct v1_disk_dqblk));- fs = get_fs();- set_fs(KERNEL_DS);- filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);- set_fs(fs);+ dquot->dq_sb->s_op->quota_read(dquot->dq_sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); v1_disk2mem_dqblk(&dquot->dq_dqb, &dqblk); if (dquot->dq_dqb.dqb_bhardlimit == 0 && dquot->dq_dqb.dqb_bsoftlimit == 0 &&@@ -71,26 +61,18 @@ static int v1_read_dqblk(struct dquot *d static int v1_commit_dqblk(struct dquot *dquot) { short type = dquot->dq_type;- struct file *filp;- mm_segment_t fs;- loff_t offset; ssize_t ret; struct v1_disk_dqblk dqblk; - filp = sb_dqopt(dquot->dq_sb)->files[type];- offset = v1_dqoff(dquot->dq_id);- fs = get_fs();- set_fs(KERNEL_DS);- v1_mem2disk_dqblk(&dqblk, &dquot->dq_dqb); if (dquot->dq_id == 0) { dqblk.dqb_btime = sb_dqopt(dquot->dq_sb)->info[type].dqi_bgrace; dqblk.dqb_itime = sb_dqopt(dquot->dq_sb)->info[type].dqi_igrace; } ret = 0;- if (filp)- ret = filp->f_op->write(filp, (char *)&dqblk,- sizeof(struct v1_disk_dqblk), &offset);+ if (sb_dqopt(dquot->dq_sb)->files[type])+ ret = dquot->dq_sb->s_op->quota_write(dquot->dq_sb, type, (char *)&dqblk,+ sizeof(struct v1_disk_dqblk), v1_dqoff(dquot->dq_id)); if (ret != sizeof(struct v1_disk_dqblk)) { printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", dquot->dq_sb->s_id);@@ -101,7 +83,6 @@ static int v1_commit_dqblk(struct dquot ret = 0; out:- set_fs(fs); dqstats.writes++; return ret;@@ -121,14 +102,11 @@ struct v2_disk_dqheader { static int v1_check_quota_file(struct super_block *sb, int type) {- struct file *f = sb_dqopt(sb)->files[type];- struct inode *inode = f->f_dentry->d_inode;+ struct inode *inode = sb_dqopt(sb)->files[type]; ulong blocks; size_t off; struct v2_disk_dqheader dqhead;- mm_segment_t fs; ssize_t size;- loff_t offset = 0; loff_t isize; static const uint quota_magics[] = V2_INITQMAGICS; @@ -140,10 +118,7 @@ static int v1_check_quota_file(struct su if ((blocks % sizeof(struct v1_disk_dqblk) * BLOCK_SIZE + off) % sizeof(struct v1_disk_dqblk)) return 0; /* Doublecheck whether we didn't get file with new format - with old quotactl() this could happen */- fs = get_fs();- set_fs(KERNEL_DS);- size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);- set_fs(fs);+ size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0); if (size != sizeof(struct v2_disk_dqheader)) return 1; /* Probably not new format */ if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type])@@ -155,16 +130,10 @@ static int v1_check_quota_file(struct su static int v1_read_file_info(struct super_block *sb, int type) { struct quota_info *dqopt = sb_dqopt(sb);- mm_segment_t fs;- loff_t offset;- struct file *filp = dqopt->files[type]; struct v1_disk_dqblk dqblk; int ret; - offset = v1_dqoff(0);- fs = get_fs();- set_fs(KERNEL_DS);- if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {+ if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk, sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) { if (ret >= 0) ret = -EIO; goto out;@@ -173,38 +142,31 @@ static int v1_read_file_info(struct supe 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:- set_fs(fs); return ret; } static int v1_write_file_info(struct super_block *sb, int type) { struct quota_info *dqopt = sb_dqopt(sb);- mm_segment_t fs;- struct file *filp = dqopt->files[type]; struct v1_disk_dqblk dqblk;- loff_t offset; int ret; dqopt->info[type].dqi_flags &= ~DQF_INFO_DIRTY;- offset = v1_dqoff(0);- fs = get_fs();- set_fs(KERNEL_DS);- if ((ret = filp->f_op->read(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset)) != sizeof(struct v1_disk_dqblk)) {+ if ((ret = sb->s_op->quota_read(sb, type, (char *)&dqblk,+ sizeof(struct v1_disk_dqblk), v1_dqoff(0))) != sizeof(struct v1_disk_dqblk)) { if (ret >= 0) ret = -EIO; goto out; } dqblk.dqb_itime = dqopt->info[type].dqi_igrace; dqblk.dqb_btime = dqopt->info[type].dqi_bgrace;- offset = v1_dqoff(0);- ret = filp->f_op->write(filp, (char *)&dqblk, sizeof(struct v1_disk_dqblk), &offset);+ ret = sb->s_op->quota_write(sb, type, (char *)&dqblk,+ sizeof(struct v1_disk_dqblk), v1_dqoff(0)); if (ret == sizeof(struct v1_disk_dqblk)) ret = 0; else if (ret > 0) ret = -EIO; out:- set_fs(fs); return ret; } diff -rup RH_2_6_9_55.orig/fs/quota_v2.c RH_2_6_9_55/fs/quota_v2.c--- RH_2_6_9_55.orig/fs/quota_v2.c+++ RH_2_6_9_55/fs/quota_v2.c@@ -13,7 +13,6 @@ #include <linux/slab.h> #include <asm/byteorder.h>-#include <asm/uaccess.h> MODULE_AUTHOR("Jan Kara"); MODULE_DESCRIPTION("Quota format v2 support");@@ -30,19 +29,15 @@ typedef char *dqbuf_t; static int v2_check_quota_file(struct super_block *sb, int type) { struct v2_disk_dqheader dqhead;- struct file *f = sb_dqopt(sb)->files[type];- mm_segment_t fs; ssize_t size;- loff_t offset = 0; static const uint quota_magics[] = V2_INITQMAGICS; static const uint quota_versions[] = V2_INITQVERSIONS; - fs = get_fs();- set_fs(KERNEL_DS);- size = f->f_op->read(f, (char *)&dqhead, sizeof(struct v2_disk_dqheader), &offset);- set_fs(fs);- if (size != sizeof(struct v2_disk_dqheader))+ size = sb->s_op->quota_read(sb, type, (char *)&dqhead, sizeof(struct v2_disk_dqheader), 0);+ if (size != sizeof(struct v2_disk_dqheader)) {+ printk("failed read\n"); return 0;+ } if (le32_to_cpu(dqhead.dqh_magic) != quota_magics[type] || le32_to_cpu(dqhead.dqh_version) != quota_versions[type]) return 0;@@ -52,20 +47,15 @@ static int v2_check_quota_file(struct su /* Read information header from quota file */ static int v2_read_file_info(struct super_block *sb, int type) {- mm_segment_t fs; struct v2_disk_dqinfo dinfo; struct mem_dqinfo *info = sb_dqopt(sb)->info+type;- struct file *f = sb_dqopt(sb)->files[type]; ssize_t size;- loff_t offset = V2_DQINFOOFF; - fs = get_fs();- set_fs(KERNEL_DS);- size = f->f_op->read(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);- set_fs(fs);+ size = sb->s_op->quota_read(sb, type, (char *)&dinfo,+ sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); if (size != sizeof(struct v2_disk_dqinfo)) { printk(KERN_WARNING "Can't read info structure on device %s.\n",- f->f_dentry->d_sb->s_id);+ sb->s_id); return -1; } info->dqi_bgrace = le32_to_cpu(dinfo.dqi_bgrace);@@ -80,12 +70,9 @@ static int v2_read_file_info(struct supe /* Write information header to quota file */ static int v2_write_file_info(struct super_block *sb, int type) {- mm_segment_t fs; struct v2_disk_dqinfo dinfo; struct mem_dqinfo *info = sb_dqopt(sb)->info+type;- struct file *f = sb_dqopt(sb)->files[type]; ssize_t size;- loff_t offset = V2_DQINFOOFF; spin_lock(&dq_data_lock); info->dqi_flags &= ~DQF_INFO_DIRTY;@@ -96,13 +83,11 @@ static int v2_write_file_info(struct sup dinfo.dqi_blocks = cpu_to_le32(info->u.v2_i.dqi_blocks); dinfo.dqi_free_blk = cpu_to_le32(info->u.v2_i.dqi_free_blk); dinfo.dqi_free_entry = cpu_to_le32(info->u.v2_i.dqi_free_entry);- fs = get_fs();- set_fs(KERNEL_DS);- size = f->f_op->write(f, (char *)&dinfo, sizeof(struct v2_disk_dqinfo), &offset);- set_fs(fs);+ size = sb->s_op->quota_write(sb, type, (char *)&dinfo,+ sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF); if (size != sizeof(struct v2_disk_dqinfo)) { printk(KERN_WARNING "Can't write info structure on device %s.\n",- f->f_dentry->d_sb->s_id);+ sb->s_id); return -1; } return 0;@@ -146,39 +131,24 @@ static inline void freedqbuf(dqbuf_t buf kfree(buf); } -static ssize_t read_blk(struct file *filp, uint blk, dqbuf_t buf)+static inline ssize_t read_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf) {- mm_segment_t fs;- ssize_t ret;- loff_t offset = blk<<V2_DQBLKSIZE_BITS;- memset(buf, 0, V2_DQBLKSIZE);- fs = get_fs();- set_fs(KERNEL_DS);- ret = filp->f_op->read(filp, (char *)buf, V2_DQBLKSIZE, &offset);- set_fs(fs);- return ret;+ return sb->s_op->quota_read(sb, type, (char *)buf,+ V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS); } -static ssize_t write_blk(struct file *filp, uint blk, dqbuf_t buf)+static inline ssize_t write_blk(struct super_block *sb, int type, uint blk, dqbuf_t buf) {- mm_segment_t fs;- ssize_t ret;- loff_t offset = blk<<V2_DQBLKSIZE_BITS;-- fs = get_fs();- set_fs(KERNEL_DS);- ret = filp->f_op->write(filp, (char *)buf, V2_DQBLKSIZE, &offset);- set_fs(fs);- return ret;-+ return sb->s_op->quota_write(sb, type, (char *)buf,+ V2_DQBLKSIZE, blk << V2_DQBLKSIZE_BITS); } /* Remove empty block from list and return it */-static int get_free_dqblk(struct file *filp, int type)+static int get_free_dqblk(struct super_block *sb, int type) { dqbuf_t buf = getdqbuf();- struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);+ struct mem_dqinfo *info = sb_dqinfo(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int ret, blk; @@ -186,17 +156,18 @@ static int get_free_dqblk(struct file *f return -ENOMEM; if (info->u.v2_i.dqi_free_blk) { blk = info->u.v2_i.dqi_free_blk;- if ((ret = read_blk(filp, blk, buf)) < 0)+ if ((ret = read_blk(sb, type, blk, buf)) < 0) goto out_buf; info->u.v2_i.dqi_free_blk = le32_to_cpu(dh->dqdh_next_free); } else { memset(buf, 0, V2_DQBLKSIZE);- if ((ret = write_blk(filp, info->u.v2_i.dqi_blocks, buf)) < 0) /* Assure block allocation... */+ /* Assure block allocation... */+ if ((ret = write_blk(sb, type, info->u.v2_i.dqi_blocks, buf)) < 0) goto out_buf; blk = info->u.v2_i.dqi_blocks++; }- mark_info_dirty(filp->f_dentry->d_sb, type);+ mark_info_dirty(sb, type); ret = blk; out_buf: freedqbuf(buf);@@ -204,9 +175,9 @@ out_buf: } /* Insert empty block to the list */-static int put_free_dqblk(struct file *filp, int type, dqbuf_t buf, uint blk)+static int put_free_dqblk(struct super_block *sb, int type, dqbuf_t buf, uint blk) {- struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);+ struct mem_dqinfo *info = sb_dqinfo(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int err; @@ -214,17 +185,18 @@ static int put_free_dqblk(struct file *f dh->dqdh_prev_free = cpu_to_le32(0); dh->dqdh_entries = cpu_to_le16(0); info->u.v2_i.dqi_free_blk = blk;- mark_info_dirty(filp->f_dentry->d_sb, type);- if ((err = write_blk(filp, blk, buf)) < 0) /* Some strange block. We had better leave it... */+ mark_info_dirty(sb, type);+ /* Some strange block. We had better leave it... */+ if ((err = write_blk(sb, type, blk, buf)) < 0) return err; return 0; } /* Remove given block from the list of blocks with free entries */-static int remove_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)+static int remove_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk) { dqbuf_t tmpbuf = getdqbuf();- struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);+ struct mem_dqinfo *info = sb_dqinfo(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; uint nextblk = le32_to_cpu(dh->dqdh_next_free), prevblk = le32_to_cpu(dh->dqdh_prev_free); int err;@@ -232,26 +204,27 @@ static int remove_free_dqentry(struct fi if (!tmpbuf) return -ENOMEM; if (nextblk) {- if ((err = read_blk(filp, nextblk, tmpbuf)) < 0)+ if ((err = read_blk(sb, type, nextblk, tmpbuf)) < 0) goto out_buf; ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = dh->dqdh_prev_free;- if ((err = write_blk(filp, nextblk, tmpbuf)) < 0)+ if ((err = write_blk(sb, type, nextblk, tmpbuf)) < 0) goto out_buf; } if (prevblk) {- if ((err = read_blk(filp, prevblk, tmpbuf)) < 0)+ if ((err = read_blk(sb, type, prevblk, tmpbuf)) < 0) goto out_buf; ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_next_free = dh->dqdh_next_free;- if ((err = write_blk(filp, prevblk, tmpbuf)) < 0)+ if ((err = write_blk(sb, type, prevblk, tmpbuf)) < 0) goto out_buf; } else { info->u.v2_i.dqi_free_entry = nextblk;- mark_info_dirty(filp->f_dentry->d_sb, type);+ mark_info_dirty(sb, type); } freedqbuf(tmpbuf); dh->dqdh_next_free = dh->dqdh_prev_free = cpu_to_le32(0);- if (write_blk(filp, blk, buf) < 0) /* No matter whether write succeeds block is out of list */+ /* No matter whether write succeeds block is out of list */+ if (write_blk(sb, type, blk, buf) < 0) printk(KERN_ERR "VFS: Can't write block (%u) with free entries.\n", blk); return 0; out_buf:@@ -260,10 +233,10 @@ out_buf: } /* Insert given block to the beginning of list with free entries */-static int insert_free_dqentry(struct file *filp, int type, dqbuf_t buf, uint blk)+static int insert_free_dqentry(struct super_block *sb, int type, dqbuf_t buf, uint blk) { dqbuf_t tmpbuf = getdqbuf();- struct mem_dqinfo *info = sb_dqinfo(filp->f_dentry->d_sb, type);+ struct mem_dqinfo *info = sb_dqinfo(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int err; @@ -271,18 +244,18 @@ static int insert_free_dqentry(struct fi return -ENOMEM; dh->dqdh_next_free = cpu_to_le32(info->u.v2_i.dqi_free_entry); dh->dqdh_prev_free = cpu_to_le32(0);- if ((err = write_blk(filp, blk, buf)) < 0)+ if ((err = write_blk(sb, type, blk, buf)) < 0) goto out_buf; if (info->u.v2_i.dqi_free_entry) {- if ((err = read_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)+ if ((err = read_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0) goto out_buf; ((struct v2_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk);- if ((err = write_blk(filp, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0)+ if ((err = write_blk(sb, type, info->u.v2_i.dqi_free_entry, tmpbuf)) < 0) goto out_buf; } freedqbuf(tmpbuf); info->u.v2_i.dqi_free_entry = blk;- mark_info_dirty(filp->f_dentry->d_sb, type);+ mark_info_dirty(sb, type); return 0; out_buf: freedqbuf(tmpbuf);@@ -292,8 +265,8 @@ out_buf:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -