📄 2.6.5-quotafix.patch
字号:
dqopt->files[type] = NULL;+ iput(inode); out_lock: up(&dqopt->dqonoff_sem);-out_f:- filp_close(f, NULL);+ if (oldflags != -1) {+ down_write(&dqopt->dqptr_sem);+ /* Set the flags back (in the case of accidental quotaon()+ * on a wrong file we don't want to mess up the flags) */+ inode->i_flags &= ~(S_NOATIME | S_NOQUOTA | S_IMMUTABLE);+ inode->i_flags |= oldflags;+ up_write(&dqopt->dqptr_sem);+ }+ up(&inode->i_sem); out_fmt: put_quota_format(fmt); return error; } +/* Actual function called from quotactl() */+int vfs_quota_on(struct super_block *sb, int type, int format_id, char *path)+{+ struct nameidata nd;+ int error;++ error = path_lookup(path, LOOKUP_FOLLOW, &nd);+ if (error < 0)+ return error;+ error = security_quota_on(nd.dentry);+ if (error)+ goto out_path;+ /* Quota file not on the same filesystem? */+ if (nd.mnt->mnt_sb != sb)+ error = -EXDEV;+ else {+ error = vfs_quota_on_inode(nd.dentry->d_inode, type, format_id);+ if (!error)+ sb_dqopt(sb)->mnt[type] = mntget(nd.mnt);+ }++out_path:+ path_release(&nd);+ return error;+}+ /* Generic routine for getting common part of quota structure */ static void do_get_dqblk(struct dquot *dquot, struct if_dqblk *di) {@@ -1430,8 +1600,10 @@ int vfs_set_dqinfo(struct super_block *s mi->dqi_igrace = ii->dqi_igrace; if (ii->dqi_valid & IIF_FLAGS) mi->dqi_flags = (mi->dqi_flags & ~DQF_MASK) | (ii->dqi_flags & DQF_MASK);- mark_info_dirty(mi); spin_unlock(&dq_data_lock);+ mark_info_dirty(sb, type);+ /* Force write to disk */+ sb->dq_op->write_info(sb, type); up(&sb_dqopt(sb)->dqonoff_sem); return 0; }@@ -1564,3 +1736,15 @@ EXPORT_SYMBOL(dqstats); EXPORT_SYMBOL(dq_list_lock); EXPORT_SYMBOL(dq_data_lock); EXPORT_SYMBOL(init_dquot_operations);+EXPORT_SYMBOL(dquot_commit);+EXPORT_SYMBOL(dquot_commit_info);+EXPORT_SYMBOL(dquot_acquire);+EXPORT_SYMBOL(dquot_release);+EXPORT_SYMBOL(dquot_initialize);+EXPORT_SYMBOL(dquot_drop);+EXPORT_SYMBOL(dquot_alloc_space);+EXPORT_SYMBOL(dquot_alloc_inode);+EXPORT_SYMBOL(dquot_free_space);+EXPORT_SYMBOL(dquot_free_inode);+EXPORT_SYMBOL(dquot_transfer);+Index: linux-2.6.5-7.283/fs/quota_v2.c===================================================================--- linux-2.6.5-7.283.orig/fs/quota_v2.c+++ linux-2.6.5-7.283/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_vfsmnt->mnt_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; info->dqi_flags &= ~DQF_INFO_DIRTY; dinfo.dqi_bgrace = cpu_to_le32(info->dqi_bgrace);@@ -94,13 +81,13 @@ 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_vfsmnt->mnt_sb->s_id);+ sb->s_id); return -1; } return 0;@@ -144,38 +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, struct mem_dqinfo *info)+static int get_free_dqblk(struct super_block *sb, int type) { dqbuf_t buf = getdqbuf();+ struct mem_dqinfo *info = sb_dqinfo(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int ret, blk; @@ -183,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(info);+ mark_info_dirty(sb, type); ret = blk; out_buf: freedqbuf(buf);@@ -201,8 +175,9 @@ out_buf: } /* Insert empty block to the list */-static int put_free_dqblk(struct file *filp, struct mem_dqinfo *info, 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(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int err; @@ -210,16 +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(info);- 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, struct mem_dqinfo *info, 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(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;@@ -227,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(info);+ 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:@@ -255,9 +233,10 @@ out_buf: } /* Insert given block to the beginning of list with free entries */-static int insert_free_dqentry(struct file *filp, struct mem_dqinfo *info, 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(sb, type); struct v2_disk_dqdbheader *dh = (struct v2_disk_dqdbheader *)buf; int err; @@ -265,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(info);+ mark_info_dirty(sb, type); return 0; out_buf: freedqbuf(tmpbuf);@@ -286,8 +265,8 @@ out_buf: /* Find space for dquot */ static uint find_free_dqentry(struct dquot *dquot, int *err) {- struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];- struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info+dquot->dq_type;+ struct super_block *sb = dquot->dq_sb;+ struct mem_dqinfo *info = sb_dqopt(sb)->info+dquot->dq_type; uint blk, i; struct v2_disk_dqdbheader *dh; struct v2_disk_dqblk *ddquot;@@ -303,22 +282,23 @@ static uint find_free_dqentry(struct dqu ddquot = GETENTRIES(buf); if (info->u.v2_i.dqi_free_entry) { blk = info->u.v2_i.dqi_free_entry;- if ((*err = read_blk(filp, blk, buf)) < 0)+ if ((*err = read_blk(sb, dquot->dq_type, blk, buf)) < 0) goto out_buf; } else {- blk = get_free_dqblk(filp, info);+ blk = get_free_dqblk(sb, dquot->dq_type); if ((int)blk < 0) { *err = blk; freedqbuf(buf); return 0; } memset(buf, 0, V2_DQBLKSIZE);- info->u.v2_i.dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */- mark_info_dirty(info);+ /* This is enough as block is already zeroed and entry list is empty... */+ info->u.v2_i.dqi_free_entry = blk;+ mark_info_dirty(sb, dquot->dq_type); } if (le16_to_cpu(dh->dqdh_entries)+1 >= V2_DQSTRINBLK) /* Block will be full? */- if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) {+ if ((*err = remove_free_dqentry(sb, dquot->dq_type, buf, blk)) < 0) { printk(KERN_ERR "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", blk); goto out_buf; }@@ -333,7 +313,7 @@ static uint find_free_dqentry(struct dqu goto out_buf; } #endif- if ((*err = write_blk(filp, blk, buf)) < 0) {+ if ((*err = write_blk(sb, dquot->dq_type, blk, buf)) < 0) { printk(KERN_ERR "VFS: find_free_dqentry(): Can't write quota data block %u.\n", blk); goto out_buf; }@@ -348,8 +328,7 @@ out_buf: /* Insert reference to structure into the trie */ static int do_insert_tree(struct dquot *dquot, uint *treeblk, int depth) {- struct file *filp = sb_dqopt(dquot->dq_sb)->files[dquot->dq_type];- struct mem_dqinfo *info = sb_dqopt(dquot->dq_sb)->info + dquot->dq_type;+ struct super_block *sb = dquot->dq_sb; dqbuf_t buf;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -