On Mon 03-04-23 10:47:57, cem@xxxxxxxxxx wrote: > From: Lukas Czerner <lczerner@xxxxxxxxxx> > > Add new shmem quota format, its quota_format_ops together with > dquot_operations > > Signed-off-by: Lukas Czerner <lczerner@xxxxxxxxxx> > Signed-off-by: Carlos Maiolino <cmaiolino@xxxxxxxxxx> Just two small things below. > diff --git a/mm/shmem_quota.c b/mm/shmem_quota.c > new file mode 100644 > index 0000000000000..c415043a71e67 > --- /dev/null > +++ b/mm/shmem_quota.c ... > +/* > + * Load dquot with limits from existing entry, or create the new entry if > + * it does not exist. > + */ > +static int shmem_acquire_dquot(struct dquot *dquot) > +{ > + struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); > + struct rb_node **n = &((struct rb_root *)info->dqi_priv)->rb_node; > + struct rb_node *parent = NULL, *new_node = NULL; > + struct quota_id *new_entry, *entry; > + qid_t id = from_kqid(&init_user_ns, dquot->dq_id); > + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); > + int ret = 0; > + > + mutex_lock(&dquot->dq_lock); > + > + down_write(&dqopt->dqio_sem); > + while (*n) { > + parent = *n; > + entry = rb_entry(parent, struct quota_id, node); > + > + if (id < entry->id) > + n = &(*n)->rb_left; > + else if (id > entry->id) > + n = &(*n)->rb_right; > + else > + goto found; > + } > + > + /* We don't have entry for this id yet, create it */ > + new_entry = kzalloc(sizeof(struct quota_id), GFP_NOFS); > + if (!new_entry) { > + ret = -ENOMEM; > + goto out_unlock; > + } > + > + new_entry->id = id; > + new_node = &new_entry->node; > + rb_link_node(new_node, parent, n); > + rb_insert_color(new_node, (struct rb_root *)info->dqi_priv); > + entry = new_entry; > + > +found: > + /* Load the stored limits from the tree */ > + spin_lock(&dquot->dq_dqb_lock); > + dquot->dq_dqb.dqb_bhardlimit = entry->bhardlimit; > + dquot->dq_dqb.dqb_bsoftlimit = entry->bsoftlimit; > + dquot->dq_dqb.dqb_ihardlimit = entry->ihardlimit; > + dquot->dq_dqb.dqb_isoftlimit = entry->isoftlimit; > + > + if (!dquot->dq_dqb.dqb_bhardlimit && > + !dquot->dq_dqb.dqb_bsoftlimit && > + !dquot->dq_dqb.dqb_ihardlimit && > + !dquot->dq_dqb.dqb_isoftlimit) > + set_bit(DQ_FAKE_B, &dquot->dq_flags); > + spin_unlock(&dquot->dq_dqb_lock); > + > + /* Make sure flags update is visible after dquot has been filled */ > + smp_mb__before_atomic(); > + set_bit(DQ_ACTIVE_B, &dquot->dq_flags); I'm slightly wondering whether we shouldn't have a dquot_mark_active() helper for this to hide the barrier details... > +out_unlock: > + up_write(&dqopt->dqio_sem); > + mutex_unlock(&dquot->dq_lock); > + return ret; > +} > + > +/* > + * Store limits from dquot in the tree unless it's fake. If it is fake > + * remove the id from the tree since there is no useful information in > + * there. > + */ > +static int shmem_release_dquot(struct dquot *dquot) > +{ > + struct mem_dqinfo *info = sb_dqinfo(dquot->dq_sb, dquot->dq_id.type); > + struct rb_node *node = ((struct rb_root *)info->dqi_priv)->rb_node; > + qid_t id = from_kqid(&init_user_ns, dquot->dq_id); > + struct quota_info *dqopt = sb_dqopt(dquot->dq_sb); > + struct quota_id *entry = NULL; > + > + mutex_lock(&dquot->dq_lock); > + /* Check whether we are not racing with some other dqget() */ > + if (dquot_is_busy(dquot)) > + goto out_dqlock; > + > + down_write(&dqopt->dqio_sem); > + while (node) { > + entry = rb_entry(node, struct quota_id, node); > + > + if (id < entry->id) > + node = node->rb_left; > + else if (id > entry->id) > + node = node->rb_right; > + else > + goto found; > + } > + > + up_write(&dqopt->dqio_sem); > + mutex_unlock(&dquot->dq_lock); We should report some kind of error here, shouldn't we? We do expect to have the quota_id allocated from shmem_acquire_dquot() and we will be possibly loosing set limits here. Otherwise the patch looks good to me. Honza -- Jan Kara <jack@xxxxxxxx> SUSE Labs, CR