// SPDX-License-Identifier: GPL-2.0 /* * Copyright (C) 2005-2019 Junjiro R. Okajima */ /* * mount and super_block operations */ #include #include "aufs.h" /* * super_operations */ static struct inode *aufs_alloc_inode(struct super_block *sb __maybe_unused) { struct au_icntnr *c; c = au_cache_alloc_icntnr(); if (c) { au_icntnr_init(c); inode_set_iversion(&c->vfs_inode, 1); /* sigen(sb); */ c->iinfo.ii_hinode = NULL; return &c->vfs_inode; } return NULL; } static void aufs_destroy_inode_cb(struct rcu_head *head) { struct inode *inode = container_of(head, struct inode, i_rcu); au_cache_free_icntnr(container_of(inode, struct au_icntnr, vfs_inode)); } static void aufs_destroy_inode(struct inode *inode) { if (!au_is_bad_inode(inode)) au_iinfo_fin(inode); call_rcu(&inode->i_rcu, aufs_destroy_inode_cb); } struct inode *au_iget_locked(struct super_block *sb, ino_t ino) { struct inode *inode; int err; inode = iget_locked(sb, ino); if (unlikely(!inode)) { inode = ERR_PTR(-ENOMEM); goto out; } if (!(inode->i_state & I_NEW)) goto out; err = au_iinfo_init(inode); if (!err) inode_inc_iversion(inode); else { iget_failed(inode); inode = ERR_PTR(err); } out: /* never return NULL */ AuDebugOn(!inode); return inode; } /* ---------------------------------------------------------------------- */ static const struct super_operations aufs_sop = { .alloc_inode = aufs_alloc_inode, .destroy_inode = aufs_destroy_inode, /* always deleting, no clearing */ .drop_inode = generic_delete_inode };