brintos

brintos / linux-shallow public Read only

0
0
Text · 5.0 KiB · 62a3d25 Raw
180 lines · c
1// SPDX-License-Identifier: GPL-2.02/* cnode related routines for the coda kernel code3   (C) 1996 Peter Braam4   */5 6#include <linux/types.h>7#include <linux/string.h>8#include <linux/time.h>9 10#include <linux/coda.h>11#include <linux/pagemap.h>12#include "coda_psdev.h"13#include "coda_linux.h"14 15static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)16{17	return memcmp(fid1, fid2, sizeof(*fid1)) == 0;18}19 20static const struct inode_operations coda_symlink_inode_operations = {21	.get_link	= page_get_link,22	.setattr	= coda_setattr,23};24 25/* cnode.c */26static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)27{28        coda_vattr_to_iattr(inode, attr);29 30        if (S_ISREG(inode->i_mode)) {31                inode->i_op = &coda_file_inode_operations;32                inode->i_fop = &coda_file_operations;33        } else if (S_ISDIR(inode->i_mode)) {34                inode->i_op = &coda_dir_inode_operations;35                inode->i_fop = &coda_dir_operations;36        } else if (S_ISLNK(inode->i_mode)) {37		inode->i_op = &coda_symlink_inode_operations;38		inode_nohighmem(inode);39		inode->i_data.a_ops = &coda_symlink_aops;40		inode->i_mapping = &inode->i_data;41	} else42                init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev));43}44 45static int coda_test_inode(struct inode *inode, void *data)46{47	struct CodaFid *fid = (struct CodaFid *)data;48	struct coda_inode_info *cii = ITOC(inode);49	return coda_fideq(&cii->c_fid, fid);50}51 52static int coda_set_inode(struct inode *inode, void *data)53{54	struct CodaFid *fid = (struct CodaFid *)data;55	struct coda_inode_info *cii = ITOC(inode);56	cii->c_fid = *fid;57	return 0;58}59 60struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,61			 struct coda_vattr * attr)62{63	struct inode *inode;64	struct coda_inode_info *cii;65	unsigned long hash = coda_f2i(fid);66	umode_t inode_type = coda_inode_type(attr);67 68retry:69	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);70	if (!inode)71		return ERR_PTR(-ENOMEM);72 73	if (inode->i_state & I_NEW) {74		cii = ITOC(inode);75		/* we still need to set i_ino for things like stat(2) */76		inode->i_ino = hash;77		/* inode is locked and unique, no need to grab cii->c_lock */78		cii->c_mapcount = 0;79		coda_fill_inode(inode, attr);80		unlock_new_inode(inode);81	} else if ((inode->i_mode & S_IFMT) != inode_type) {82		/* Inode has changed type, mark bad and grab a new one */83		remove_inode_hash(inode);84		coda_flag_inode(inode, C_PURGE);85		iput(inode);86		goto retry;87	}88	return inode;89}90 91/* this is effectively coda_iget:92   - get attributes (might be cached)93   - get the inode for the fid using vfs iget94   - link the two up if this is needed95   - fill in the attributes96*/97struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)98{99        struct coda_vattr attr;100	struct inode *inode;101        int error;102        103	/* We get inode numbers from Venus -- see venus source */104	error = venus_getattr(sb, fid, &attr);105	if (error)106		return ERR_PTR(error);107 108	inode = coda_iget(sb, fid, &attr);109	if (IS_ERR(inode))110		pr_warn("%s: coda_iget failed\n", __func__);111	return inode;112}113 114 115/* Although we treat Coda file identifiers as immutable, there is one116 * special case for files created during a disconnection where they may117 * not be globally unique. When an identifier collision is detected we118 * first try to flush the cached inode from the kernel and finally119 * resort to renaming/rehashing in-place. Userspace remembers both old120 * and new values of the identifier to handle any in-flight upcalls.121 * The real solution is to use globally unique UUIDs as identifiers, but122 * retrofitting the existing userspace code for this is non-trivial. */123void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 124		      struct CodaFid *newfid)125{126	struct coda_inode_info *cii = ITOC(inode);127	unsigned long hash = coda_f2i(newfid);128	129	BUG_ON(!coda_fideq(&cii->c_fid, oldfid));130 131	/* replace fid and rehash inode */132	/* XXX we probably need to hold some lock here! */133	remove_inode_hash(inode);134	cii->c_fid = *newfid;135	inode->i_ino = hash;136	__insert_inode_hash(inode, hash);137}138 139/* convert a fid to an inode. */140struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 141{142	struct inode *inode;143	unsigned long hash = coda_f2i(fid);144 145	inode = ilookup5(sb, hash, coda_test_inode, fid);146	if ( !inode )147		return NULL;148 149	/* we should never see newly created inodes because we intentionally150	 * fail in the initialization callback */151	BUG_ON(inode->i_state & I_NEW);152 153	return inode;154}155 156struct coda_file_info *coda_ftoc(struct file *file)157{158	struct coda_file_info *cfi = file->private_data;159 160	BUG_ON(!cfi || cfi->cfi_magic != CODA_MAGIC);161 162	return cfi;163 164}165 166/* the CONTROL inode is made without asking attributes from Venus */167struct inode *coda_cnode_makectl(struct super_block *sb)168{169	struct inode *inode = new_inode(sb);170	if (inode) {171		inode->i_ino = CTL_INO;172		inode->i_op = &coda_ioctl_inode_operations;173		inode->i_fop = &coda_ioctl_operations;174		inode->i_mode = 0444;175		return inode;176	}177	return ERR_PTR(-ENOMEM);178}179 180