quota: Push dqio_sem down to ->read_file_info()
[sfrench/cifs-2.6.git] / fs / quota / quota_v2.c
index 5e47012d2f57b0c47e2ad0ffedeec3c0ab54b2fa..373d7cfea5b021a5cda159abc715a78a55769302 100644 (file)
@@ -90,29 +90,38 @@ static int v2_read_file_info(struct super_block *sb, int type)
 {
        struct v2_disk_dqinfo dinfo;
        struct v2_disk_dqheader dqhead;
-       struct mem_dqinfo *info = sb_dqinfo(sb, type);
+       struct quota_info *dqopt = sb_dqopt(sb);
+       struct mem_dqinfo *info = &dqopt->info[type];
        struct qtree_mem_dqinfo *qinfo;
        ssize_t size;
        unsigned int version;
+       int ret;
 
-       if (!v2_read_header(sb, type, &dqhead))
-               return -1;
+       down_read(&dqopt->dqio_sem);
+       if (!v2_read_header(sb, type, &dqhead)) {
+               ret = -1;
+               goto out;
+       }
        version = le32_to_cpu(dqhead.dqh_version);
        if ((info->dqi_fmt_id == QFMT_VFS_V0 && version != 0) ||
-           (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1))
-               return -1;
+           (info->dqi_fmt_id == QFMT_VFS_V1 && version != 1)) {
+               ret = -1;
+               goto out;
+       }
 
        size = sb->s_op->quota_read(sb, type, (char *)&dinfo,
               sizeof(struct v2_disk_dqinfo), V2_DQINFOOFF);
        if (size != sizeof(struct v2_disk_dqinfo)) {
                quota_error(sb, "Can't read info structure");
-               return -1;
+               ret = -1;
+               goto out;
        }
        info->dqi_priv = kmalloc(sizeof(struct qtree_mem_dqinfo), GFP_NOFS);
        if (!info->dqi_priv) {
                printk(KERN_WARNING
                       "Not enough memory for quota information structure.\n");
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto out;
        }
        qinfo = info->dqi_priv;
        if (version == 0) {
@@ -147,7 +156,10 @@ static int v2_read_file_info(struct super_block *sb, int type)
                qinfo->dqi_entry_size = sizeof(struct v2r1_disk_dqblk);
                qinfo->dqi_ops = &v2r1_qtree_ops;
        }
-       return 0;
+       ret = 0;
+out:
+       up_read(&dqopt->dqio_sem);
+       return ret;
 }
 
 /* Write information header to quota file */