On 15-Jul 14:57, Martin KaFai Lau wrote: > On Thu, Jul 09, 2020 at 12:12:37PM +0200, KP Singh wrote: > > From: KP Singh <kpsingh@xxxxxxxxxx> > > > > Similar to bpf_local_storage for sockets, add local storage for inodes. > > The life-cycle of storage is managed with the life-cycle of the inode. > > i.e. the storage is destroyed along with the owning inode. > > > > The BPF LSM allocates an __rcu pointer to the bpf_local_storage in the > > security blob which are now stackable and can co-exist with other LSMs. > > > > Signed-off-by: KP Singh <kpsingh@xxxxxxxxxx> > > [ ... ] > > > > +static void *bpf_inode_storage_lookup_elem(struct bpf_map *map, void *key) > > +{ > > + struct bpf_local_storage_data *sdata; > > + struct inode *inode; > > + int err = -EINVAL; > > + > > + if (key) { > > + inode = *(struct inode **)(key); > The bpf_inode_storage_lookup_elem() here and the (update|delete)_elem() below > are called from the userspace syscall. How the userspace may provide this key? I realized this when I replied about the _fd_ name in the sk helpers. I am going to mark them as unsupported for now for inodes. We could, probably and separately, use a combination of the device and inode number as a key from userspace. - KP > > > + sdata = inode_storage_lookup(inode, map, true); > > + return sdata ? sdata->data : NULL; > > + } > > + > > + return ERR_PTR(err); > > +} > > + > > +static int bpf_inode_storage_update_elem(struct bpf_map *map, void *key, > > + void *value, u64 map_flags) > > +{ > > + struct bpf_local_storage_data *sdata; > > + struct inode *inode; > > + int err = -EINVAL; > > + > > + if (key) { > > + inode = *(struct inode **)(key); > > + sdata = map->ops->map_local_storage_update(inode, map, value, > > + map_flags); > > + return PTR_ERR_OR_ZERO(sdata); > > + } > > + return err; > > +} > > + > > +static int inode_storage_delete(struct inode *inode, struct bpf_map *map) > > +{ > > + struct bpf_local_storage_data *sdata; > > + > > + sdata = inode_storage_lookup(inode, map, false); > > + if (!sdata) > > + return -ENOENT; > > + > > + bpf_selem_unlink_map_elem(SELEM(sdata)); > > + > > + return 0; > > +} > > + > > +static int bpf_inode_storage_delete_elem(struct bpf_map *map, void *key) > > +{ > > + struct inode *inode; > > + int err = -EINVAL; > > + > > + if (key) { > > + inode = *(struct inode **)(key); > > + err = inode_storage_delete(inode, map); > > + } > > + > > + return err; > > +} > > + > > [ ... ] > > > +static int inode_storage_map_btf_id; > > +const struct bpf_map_ops inode_storage_map_ops = { > > + .map_alloc_check = bpf_local_storage_map_alloc_check, > > + .map_alloc = inode_storage_map_alloc, > > + .map_free = inode_storage_map_free, > > + .map_get_next_key = notsupp_get_next_key, > > + .map_lookup_elem = bpf_inode_storage_lookup_elem, > > + .map_update_elem = bpf_inode_storage_update_elem, > > + .map_delete_elem = bpf_inode_storage_delete_elem, > > + .map_check_btf = bpf_local_storage_map_check_btf, > > + .map_btf_name = "bpf_local_storage_map", > > + .map_btf_id = &inode_storage_map_btf_id, > > + .map_local_storage_alloc = inode_storage_alloc, > > + .map_selem_alloc = inode_selem_alloc, > > + .map_local_storage_update = inode_storage_update, > > + .map_local_storage_unlink = unlink_inode_storage, > > +}; > > +