lustre_quota_fmt.c
来自「lustre 1.6.5 source code」· C语言 代码 · 共 1,080 行 · 第 1/3 页
C
1,080 行
goto out_buf; if (info->dqi_free_entry) { if ((err = read_blk(filp, info->dqi_free_entry, tmpbuf)) < 0) goto out_buf; ((struct lustre_disk_dqdbheader *)tmpbuf)->dqdh_prev_free = cpu_to_le32(blk); if ((err = write_blk(filp, info->dqi_free_entry, tmpbuf)) < 0) goto out_buf; } freedqbuf(tmpbuf); info->dqi_free_entry = blk; lustre_mark_info_dirty(info); return 0;out_buf: freedqbuf(tmpbuf); return err;}/* Find space for dquot */static uint find_free_dqentry(struct lustre_dquot *dquot, int *err, lustre_quota_version_t version){ struct lustre_quota_info *lqi = dquot->dq_info; struct file *filp = lqi->qi_files[dquot->dq_type]; struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type]; uint blk, i; struct lustre_disk_dqdbheader *dh; void *ddquot; int dqblk_sz = lustre_disk_dqblk_sz[version]; int dqstrinblk = lustre_dqstrinblk[version]; char fakedquot[dqblk_sz]; dqbuf_t buf; *err = 0; if (!(buf = getdqbuf())) { *err = -ENOMEM; return 0; } dh = (struct lustre_disk_dqdbheader *)buf; ddquot = GETENTRIES(buf, version); if (info->dqi_free_entry) { blk = info->dqi_free_entry; if ((*err = read_blk(filp, blk, buf)) < 0) goto out_buf; } else { blk = get_free_dqblk(filp, info); if ((int)blk < 0) { *err = blk; freedqbuf(buf); return 0; } memset(buf, 0, LUSTRE_DQBLKSIZE); info->dqi_free_entry = blk; /* This is enough as block is already zeroed and entry list is empty... */ lustre_mark_info_dirty(info); } /* Will block be full */ if (le16_to_cpu(dh->dqdh_entries) + 1 >= dqstrinblk) if ((*err = remove_free_dqentry(filp, info, buf, blk)) < 0) { CERROR("VFS: 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++); if (i == dqstrinblk) { CERROR("VFS: Data block full but it shouldn't.\n"); *err = -EIO; goto out_buf; } if ((*err = write_blk(filp, blk, buf)) < 0) { CERROR("VFS: Can't write quota data block %u.\n", blk); goto out_buf; } dquot->dq_off = (blk << LUSTRE_DQBLKSIZE_BITS) + sizeof(struct lustre_disk_dqdbheader) + i * dqblk_sz; freedqbuf(buf); return blk;out_buf: freedqbuf(buf); return 0;}/* Insert reference to structure into the trie */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; struct file *filp = lqi->qi_files[dquot->dq_type]; struct lustre_mem_dqinfo *info = &lqi->qi_info[dquot->dq_type]; dqbuf_t buf; int ret = 0, newson = 0, newact = 0; u32 *ref; uint newblk; if (!(buf = getdqbuf())) return -ENOMEM; if (!*treeblk) { ret = get_free_dqblk(filp, info); if (ret < 0) goto out_buf; *treeblk = ret; memset(buf, 0, LUSTRE_DQBLKSIZE); newact = 1; } else { if ((ret = read_blk(filp, *treeblk, buf)) < 0) { CERROR("VFS: Can't read tree quota block %u.\n", *treeblk); goto out_buf; } } ref = (u32 *) buf; newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]); if (!newblk) newson = 1; if (depth == LUSTRE_DQTREEDEPTH - 1) { if (newblk) { CERROR("VFS: Inserting already present quota entry " "(block %u).\n", ref[GETIDINDEX(dquot->dq_id, depth)]); ret = -EIO; goto out_buf; } newblk = find_free_dqentry(dquot, &ret, version); } else ret = do_insert_tree(dquot, &newblk, depth + 1, version); if (newson && ret >= 0) { ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(newblk); ret = write_blk(filp, *treeblk, buf); } else if (newact && ret < 0) put_free_dqblk(filp, info, buf, *treeblk);out_buf: freedqbuf(buf); return ret;}/* Wrapper for inserting quota structure into tree */static inline int dq_insert_tree(struct lustre_dquot *dquot, lustre_quota_version_t version){ int tmp = LUSTRE_DQTREEOFF; return do_insert_tree(dquot, &tmp, 0, version);}/* * We don't have to be afraid of deadlocks as we never have quotas on quota files... */static int lustre_write_dquot(struct lustre_dquot *dquot, lustre_quota_version_t version){ int type = dquot->dq_type; struct file *filp; mm_segment_t fs; loff_t offset; ssize_t ret; int dqblk_sz = lustre_disk_dqblk_sz[version]; char ddquot[dqblk_sz], empty[dqblk_sz]; 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) { CERROR("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)) DQF_PUT(ddquot, version, dqb_itime, 1); fs = get_fs(); set_fs(KERNEL_DS); ret = filp->f_op->write(filp, ddquot, dqblk_sz, &offset); set_fs(fs); if (ret != dqblk_sz) { printk(KERN_WARNING "VFS: dquota write failed on dev %s\n", filp->f_dentry->d_sb->s_id); if (ret >= 0) ret = -ENOSPC; } else ret = 0; return ret;}/* Free dquot entry in data block */static int free_dqentry(struct lustre_dquot *dquot, uint blk, lustre_quota_version_t version){ struct file *filp = dquot->dq_info->qi_files[dquot->dq_type]; struct lustre_mem_dqinfo *info = &dquot->dq_info->qi_info[dquot->dq_type]; struct lustre_disk_dqdbheader *dh; dqbuf_t buf = getdqbuf(); int dqstrinblk = lustre_dqstrinblk[version]; int ret = 0; if (!buf) return -ENOMEM; if (dquot->dq_off >> LUSTRE_DQBLKSIZE_BITS != blk) { CERROR("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; } if ((ret = read_blk(filp, blk, buf)) < 0) { CERROR("VFS: Can't read quota data block %u\n", blk); goto out_buf; } dh = (struct lustre_disk_dqdbheader *)buf; dh->dqdh_entries = cpu_to_le16(le16_to_cpu(dh->dqdh_entries) - 1); if (!le16_to_cpu(dh->dqdh_entries)) { /* Block got free? */ if ((ret = remove_free_dqentry(filp, info, buf, blk)) < 0 || (ret = put_free_dqblk(filp, info, buf, blk)) < 0) { CERROR("VFS: Can't move quota data block (%u) " "to free list.\n", blk); goto out_buf; } } else { memset(buf + (dquot->dq_off & ((1<<LUSTRE_DQBLKSIZE_BITS) - 1)), 0, lustre_disk_dqblk_sz[version]); if (le16_to_cpu(dh->dqdh_entries) == dqstrinblk - 1) { /* Insert will write block itself */ if ((ret = insert_free_dqentry(filp, info, buf, blk)) < 0) { CERROR("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) { CERROR("VFS: Can't write quota data block %u\n", blk); goto out_buf; } } dquot->dq_off = 0; /* Quota is now unattached */out_buf: freedqbuf(buf); return ret;}/* Remove reference to dquot from tree */static int remove_tree(struct lustre_dquot *dquot, uint * blk, int depth, lustre_quota_version_t version){ struct file *filp = dquot->dq_info->qi_files[dquot->dq_type]; struct lustre_mem_dqinfo *info = &dquot->dq_info->qi_info[dquot->dq_type]; dqbuf_t buf = getdqbuf(); int ret = 0; uint newblk; u32 *ref = (u32 *) buf; if (!buf) return -ENOMEM; if ((ret = read_blk(filp, *blk, buf)) < 0) { CERROR("VFS: Can't read quota data block %u\n", *blk); goto out_buf; } newblk = le32_to_cpu(ref[GETIDINDEX(dquot->dq_id, depth)]); if (depth == LUSTRE_DQTREEDEPTH - 1) { ret = free_dqentry(dquot, newblk, version); newblk = 0; } else ret = remove_tree(dquot, &newblk, depth + 1, version); if (ret >= 0 && !newblk) { int i; ref[GETIDINDEX(dquot->dq_id, depth)] = cpu_to_le32(0); for (i = 0; i < LUSTRE_DQBLKSIZE && !buf[i]; i++) /* Block got empty? */ ; /* don't put the root block into free blk list! */ if (i == LUSTRE_DQBLKSIZE && *blk != LUSTRE_DQTREEOFF) { put_free_dqblk(filp, info, buf, *blk); *blk = 0; } else if ((ret = write_blk(filp, *blk, buf)) < 0) CERROR("VFS: Can't write quota tree block %u.\n", *blk); }out_buf: freedqbuf(buf); return ret;}/* Delete dquot from tree */static int lustre_delete_dquot(struct lustre_dquot *dquot, lustre_quota_version_t version){ uint tmp = LUSTRE_DQTREEOFF; if (!dquot->dq_off) /* Even not allocated? */ return 0; return remove_tree(dquot, &tmp, 0, version);}/* Find entry in block */static loff_t find_block_dqentry(struct lustre_dquot *dquot, uint blk, lustre_quota_version_t version){ struct file *filp = dquot->dq_info->qi_files[dquot->dq_type]; dqbuf_t buf = getdqbuf(); loff_t ret = 0; int i; char *ddquot = GETENTRIES(buf, version); int dqblk_sz = lustre_disk_dqblk_sz[version]; int dqstrinblk = lustre_dqstrinblk[version]; if (!buf) return -ENOMEM; if ((ret = read_blk(filp, blk, buf)) < 0) { CERROR("VFS: Can't read quota tree block %u.\n", blk); goto out_buf; } if (dquot->dq_id) for (i = 0; i < dqstrinblk && DQF_GET(ddquot+i*dqblk_sz, version, 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 (!DQF_GET(ddquot + i*dqblk_sz, version, dqb_id) && memcmp(fakedquot, ddquot + i*dqblk_sz, dqblk_sz)) break; } if (i == dqstrinblk) { CERROR("VFS: Quota for id %u referenced but not present.\n", dquot->dq_id); ret = -EIO; goto out_buf; } else ret = (blk << LUSTRE_DQBLKSIZE_BITS) + sizeof(struct lustre_disk_dqdbheader) + i * dqblk_sz;out_buf: freedqbuf(buf); return ret;}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?