X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Flvfs%2Flustre_quota_fmt.c;h=937e49695507a8c161f0fa24309dc6aba24d8acc;hb=72f87638570508d5d02868d4e90b131670ae2b17;hp=ee713e44f9cc310b4619732ad2e10dddcbc8ff92;hpb=cefa8cda2ba2d288ccaa4ec077a6c627592503ea;p=fs%2Flustre-release.git diff --git a/lustre/lvfs/lustre_quota_fmt.c b/lustre/lvfs/lustre_quota_fmt.c index ee713e4..937e496 100644 --- a/lustre/lvfs/lustre_quota_fmt.c +++ b/lustre/lvfs/lustre_quota_fmt.c @@ -73,6 +73,20 @@ static const int lustre_disk_dqblk_sz[] = { [LUSTRE_QUOTA_V2] = sizeof(struct lustre_disk_dqblk_v2) }; +static const union +{ + struct lustre_disk_dqblk_v2 r1; +} fakedquot[] = { + [LUSTRE_QUOTA_V2] = {.r1 = {.dqb_itime = __constant_cpu_to_le64(1LLU)} } +}; + +static const union +{ + struct lustre_disk_dqblk_v2 r1; +} emptydquot[] = { + [LUSTRE_QUOTA_V2] = {.r1 = { 0 } } +}; + int check_quota_file(struct file *f, struct inode *inode, int type, lustre_quota_version_t version) { @@ -83,6 +97,12 @@ int check_quota_file(struct file *f, struct inode *inode, int type, static const uint quota_magics[] = LUSTRE_INITQMAGICS; const uint *quota_versions = lustre_initqversions[version]; + if (!inode && !f) { + CERROR("check_quota_file failed!\n"); + libcfs_debug_dumpstack(NULL); + return -EINVAL; + } + if (f) { fs = get_fs(); set_fs(KERNEL_DS); @@ -96,7 +116,8 @@ int check_quota_file(struct file *f, struct inode *inode, int type, #else struct super_block *sb = inode->i_sb; size = sb->s_op->quota_read(sb, type, (char *)&dqhead, - sizeof(struct lustre_disk_dqheader), 0); + sizeof(struct lustre_disk_dqheader), + 0); #endif } if (size != sizeof(struct lustre_disk_dqheader)) @@ -147,7 +168,8 @@ int lustre_read_quota_file_info(struct file* f, struct lustre_mem_dqinfo* info) */ int lustre_read_quota_info(struct lustre_quota_info *lqi, int type) { - return lustre_read_quota_file_info(lqi->qi_files[type], &lqi->qi_info[type]); + return lustre_read_quota_file_info(lqi->qi_files[type], + &lqi->qi_info[type]); } /** @@ -416,7 +438,6 @@ static uint find_free_dqentry(struct lustre_dquot *dquot, int *err, void *ddquot; int dqblk_sz = lustre_disk_dqblk_sz[version]; int dqstrinblk = lustre_dqstrinblk[version]; - char fakedquot[dqblk_sz]; dqbuf_t buf; *err = 0; @@ -448,28 +469,29 @@ static uint find_free_dqentry(struct lustre_dquot *dquot, int *err, if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk) if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) { CDEBUG(D_ERROR, - "VFS: find_free_dqentry(): Can't remove block (%u) from entry free list.\n", - blk); + "VFS: find_free_dqentry(): Can't remove block " + "(%u) from entry free list.\n", blk); goto out_buf; } dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) + 1); - memset(fakedquot, 0, dqblk_sz); /* Find free structure in block */ for (i = 0; i < dqstrinblk && - memcmp(fakedquot, (char*)ddquot + i * dqblk_sz, - sizeof(fakedquot)); i++); + memcmp((char *)&emptydquot[version], + (char *)ddquot + i * dqblk_sz, dqblk_sz); + i++); if (i == dqstrinblk) { CDEBUG(D_ERROR, - "VFS: find_free_dqentry(): Data block full but it shouldn't.\n"); + "VFS: find_free_dqentry(): Data block full but it " + "shouldn't.\n"); *err = -EIO; goto out_buf; } if ((*err = write_blk(filp, blk, buf)) < 0) { CDEBUG(D_ERROR, - "VFS: find_free_dqentry(): Can't write quota data block %u.\n", - blk); + "VFS: find_free_dqentry(): Can't write quota data " + "block %u.\n", blk); goto out_buf; } dquot->dq_off = @@ -486,7 +508,7 @@ out_buf: /** * Insert reference to structure into the trie */ -static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth, +static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth, lustre_quota_version_t version) { struct lustre_quota_info *lqi = dquot->dq_info; @@ -522,7 +544,8 @@ static int do_insert_tree(struct lustre_dquot *dquot, uint * treeblk, int depth, if (newblk) { CDEBUG(D_ERROR, - "VFS: Inserting already present quota entry (block %u).\n", + "VFS: Inserting already present quota entry " + "(block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]); ret = -EIO; goto out_buf; @@ -564,30 +587,30 @@ static int lustre_write_dquot(struct lustre_dquot *dquot, loff_t offset; ssize_t ret; int dqblk_sz = lustre_disk_dqblk_sz[version]; - char ddquot[dqblk_sz], empty[dqblk_sz]; + struct lustre_disk_dqblk_v2 ddquot; - ret = mem2diskdqb(ddquot, &dquot->dq_dqb, dquot->dq_id, version); + ret = mem2diskdqb(&ddquot, &dquot->dq_dqb, dquot->dq_id, version); if (ret < 0) return ret; if (!dquot->dq_off) if ((ret = dq_insert_tree(dquot, version)) < 0) { CDEBUG(D_ERROR, - "VFS: Error %Zd occurred while creating quota.\n", - ret); + "VFS: Error %Zd occurred while creating " + "quota.\n", ret); return ret; } filp = dquot->dq_info->qi_files[type]; offset = dquot->dq_off; - /* Argh... We may need to write structure full of zeroes but that would be - * treated as an empty place by the rest of the code. Format change would - * be definitely cleaner but the problems probably are not worth it */ - memset(empty, 0, dqblk_sz); - if (!memcmp(empty, ddquot, dqblk_sz)) - ((struct lustre_disk_dqblk_v2 *)ddquot)->dqb_itime = cpu_to_le64(1); + /* Argh... We may need to write structure full of zeroes but that would + * be treated as an empty place by the rest of the code. Format change + * would be definitely cleaner but the problems probably are not worth + * it */ + if (!memcmp((char *)&emptydquot[version], (char *)&ddquot, dqblk_sz)) + ddquot.dqb_itime = cpu_to_le64(1); fs = get_fs(); set_fs(KERNEL_DS); - ret = filp->f_op->write(filp, ddquot, + ret = filp->f_op->write(filp, (char *)&ddquot, dqblk_sz, &offset); set_fs(fs); if (ret != dqblk_sz) { @@ -619,7 +642,8 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk, return -ENOMEM; if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) { CDEBUG(D_ERROR, - "VFS: Quota structure has offset to other block (%u) than it should (%u).\n", + "VFS: Quota structure has offset to other block (%u) " + "than it should (%u).\n", blk, (uint) (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS)); goto out_buf; } @@ -633,8 +657,8 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk, if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 || (ret = put_free_dqblk(filp, info, buf, blk)) < 0) { CDEBUG(D_ERROR, - "VFS: Can't move quota data block (%u) to free list.\n", - blk); + "VFS: Can't move quota data block (%u) to free " + "list.\n", blk); goto out_buf; } } else { @@ -645,8 +669,8 @@ static int free_dqentry(struct lustre_dquot *dquot, uint blk, if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) { CDEBUG(D_ERROR, - "VFS: Can't insert quota data block (%u) to free entry list.\n", - blk); + "VFS: Can't insert quota data block " + "(%u) to free entry list.\n", blk); goto out_buf; } } else if ((ret = write_blk(filp, blk, buf)) < 0) { @@ -728,7 +752,8 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk, dqbuf_t buf = getdqbuf(); loff_t ret = 0; int i; - struct lustre_disk_dqblk_v2 *ddquot = (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version); + struct lustre_disk_dqblk_v2 *ddquot = + (struct lustre_disk_dqblk_v2 *)GETENTRIES(buf, version); int dqblk_sz = lustre_disk_dqblk_sz[version]; int dqstrinblk = lustre_dqstrinblk[version]; @@ -745,13 +770,10 @@ static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk, le32_to_cpu(ddquot[i].dqb_id) != dquot->dq_id; i++) ; else { /* ID 0 as a bit more complicated searching... */ - char fakedquot[dqblk_sz]; - - memset(fakedquot, 0, sizeof(fakedquot)); for (i = 0; i < dqstrinblk; i++) if (!le32_to_cpu(ddquot[i].dqb_id) - && memcmp(fakedquot, ddquot + i, - dqblk_sz)) + && memcmp((char *)&emptydquot[version], + (char *)&ddquot[i], dqblk_sz)) break; } if (i == dqstrinblk) { @@ -773,7 +795,7 @@ out_buf: /** * Find entry for given id in the tree */ -static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth, +static loff_t find_tree_dqentry(struct lustre_dquot *dquot, uint blk, int depth, lustre_quota_version_t version) { struct file *filp = dquot->dq_info->qi_files[dquot->dq_type]; @@ -821,7 +843,7 @@ int lustre_read_dquot(struct lustre_dquot *dquot) /* Invalidated quota? */ if (!dquot->dq_info || !(filp = dquot->dq_info->qi_files[type])) { CDEBUG(D_ERROR, "VFS: Quota invalidated while reading!\n"); - return -EIO; + return -ESRCH; } version = dquot->dq_info->qi_version; @@ -839,29 +861,28 @@ int lustre_read_dquot(struct lustre_dquot *dquot) memset(&dquot->dq_dqb, 0, sizeof(struct lustre_mem_dqblk)); ret = offset; } else { - char ddquot[dqblk_sz], empty[dqblk_sz]; + struct lustre_disk_dqblk_v2 ddquot; dquot->dq_off = offset; fs = get_fs(); set_fs(KERNEL_DS); - if ((ret = filp->f_op->read(filp, ddquot, dqblk_sz, &offset)) != - dqblk_sz) { + if ((ret = filp->f_op->read(filp, (char *)&ddquot, + dqblk_sz, &offset)) != dqblk_sz) { if (ret >= 0) ret = -EIO; CDEBUG(D_ERROR, - "VFS: Error while reading quota structure for id %u.\n", - dquot->dq_id); - memset(ddquot, 0, dqblk_sz); + "VFS: Error while reading quota structure for id " + "%u.\n", dquot->dq_id); + memset((char *)&ddquot, 0, dqblk_sz); } else { ret = 0; /* We need to escape back all-zero structure */ - memset(empty, 0, dqblk_sz); - ((struct lustre_disk_dqblk_v2 *)empty)->dqb_itime = cpu_to_le64(1); - if (!memcmp(empty, ddquot, dqblk_sz)) - ((struct lustre_disk_dqblk_v2 *)empty)->dqb_itime = cpu_to_le64(0); + if (!memcmp((char *)&fakedquot[version], + (char *)&ddquot, dqblk_sz)) + ddquot.dqb_itime = cpu_to_le64(0); } set_fs(fs); - disk2memdqb(&dquot->dq_dqb, ddquot, version); + disk2memdqb(&dquot->dq_dqb, &ddquot, version); } return ret; @@ -896,7 +917,8 @@ int lustre_commit_dquot(struct lustre_dquot *dquot) return rc; } -int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, int fakemagics) +int lustre_init_quota_header(struct lustre_quota_info *lqi, int type, + int fakemagics) { static const uint quota_magics[] = LUSTRE_INITQMAGICS; static const uint fake_magics[] = LUSTRE_BADQMAGICS; @@ -1066,6 +1088,8 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, ENTRY; + LASSERT(ergo(fp == NULL, inode != NULL)); + if (check_quota_file(fp, inode, type, LUSTRE_QUOTA_V2) == 0) version = LUSTRE_QUOTA_V2; else { @@ -1095,7 +1119,6 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, list_for_each_entry(blk_item, &blk_list, link) { loff_t ret = 0; int i, dqblk_sz = lustre_disk_dqblk_sz[version]; - char fakedquot[dqblk_sz]; memset(buf, 0, LUSTRE_DQBLKSIZE); if ((ret = quota_read(fp, inode, type, blk_item->blk, buf))<0) { @@ -1105,18 +1128,23 @@ int lustre_get_qids(struct file *fp, struct inode *inode, int type, GOTO(out_free, rc = ret); } - memset(fakedquot, 0, dqblk_sz); for (i = 0; i < lustre_dqstrinblk[version]; i++) { struct dquot_id *dqid; /* skip empty entry */ - if (!memcmp(fakedquot, ddquot + i, dqblk_sz)) + if (!memcmp((char *)&emptydquot[version], + (char *)&ddquot[i], dqblk_sz)) continue; - dqid = kmalloc(sizeof(*dqid), GFP_NOFS); - if (!dqid) + OBD_ALLOC_GFP(dqid, sizeof(*dqid), GFP_NOFS); + if (!dqid) GOTO(out_free, rc = -ENOMEM); - dqid->di_id = le32_to_cpu(ddquot[i].dqb_id); + dqid->di_id = le32_to_cpu(ddquot[i].dqb_id); + dqid->di_flag = le64_to_cpu(ddquot[i].dqb_ihardlimit) ? + QI_SET : 0; + dqid->di_flag |= le64_to_cpu(ddquot[i].dqb_bhardlimit) ? + QB_SET : 0; + INIT_LIST_HEAD(&dqid->di_link); list_add(&dqid->di_link, list); }