fs/coda/cnode.c

Source file repositories/reference/linux-study-clean/fs/coda/cnode.c

File Facts

System
Linux kernel
Corpus path
fs/coda/cnode.c
Extension
.c
Size
5119 bytes
Lines
180
Domain
Core OS
Bucket
VFS And Filesystem Core
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

if (S_ISREG(inode->i_mode)) {
                inode->i_op = &coda_file_inode_operations;
                inode->i_fop = &coda_file_operations;
        } else if (S_ISDIR(inode->i_mode)) {
                inode->i_op = &coda_dir_inode_operations;
                inode->i_fop = &coda_dir_operations;
        } else if (S_ISLNK(inode->i_mode)) {
		inode->i_op = &coda_symlink_inode_operations;
		inode_nohighmem(inode);
		inode->i_data.a_ops = &coda_symlink_aops;
		inode->i_mapping = &inode->i_data;
	} else
                init_special_inode(inode, inode->i_mode, huge_decode_dev(attr->va_rdev));
}

static int coda_test_inode(struct inode *inode, void *data)
{
	struct CodaFid *fid = (struct CodaFid *)data;
	struct coda_inode_info *cii = ITOC(inode);
	return coda_fideq(&cii->c_fid, fid);
}

static int coda_set_inode(struct inode *inode, void *data)
{
	struct CodaFid *fid = (struct CodaFid *)data;
	struct coda_inode_info *cii = ITOC(inode);
	cii->c_fid = *fid;
	return 0;
}

struct inode * coda_iget(struct super_block * sb, struct CodaFid * fid,
			 struct coda_vattr * attr)
{
	struct inode *inode;
	struct coda_inode_info *cii;
	unsigned long hash = coda_f2i(fid);
	umode_t inode_type = coda_inode_type(attr);

retry:
	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);
	if (!inode)
		return ERR_PTR(-ENOMEM);

	if (inode_state_read_once(inode) & I_NEW) {
		cii = ITOC(inode);
		/* we still need to set i_ino for things like stat(2) */
		inode->i_ino = hash;
		/* inode is locked and unique, no need to grab cii->c_lock */
		cii->c_mapcount = 0;
		coda_fill_inode(inode, attr);
		unlock_new_inode(inode);
	} else if ((inode->i_mode & S_IFMT) != inode_type) {
		/* Inode has changed type, mark bad and grab a new one */
		remove_inode_hash(inode);
		coda_flag_inode(inode, C_PURGE);
		iput(inode);
		goto retry;
	}
	return inode;
}

/* this is effectively coda_iget:
   - get attributes (might be cached)
   - get the inode for the fid using vfs iget
   - link the two up if this is needed
   - fill in the attributes
*/
struct inode *coda_cnode_make(struct CodaFid *fid, struct super_block *sb)
{
        struct coda_vattr attr;
	struct inode *inode;
        int error;
        
	/* We get inode numbers from Venus -- see venus source */
	error = venus_getattr(sb, fid, &attr);
	if (error)
		return ERR_PTR(error);

	inode = coda_iget(sb, fid, &attr);
	if (IS_ERR(inode))
		pr_warn("%s: coda_iget failed\n", __func__);
	return inode;
}


/* Although we treat Coda file identifiers as immutable, there is one
 * special case for files created during a disconnection where they may
 * not be globally unique. When an identifier collision is detected we
 * first try to flush the cached inode from the kernel and finally
 * resort to renaming/rehashing in-place. Userspace remembers both old

Annotation

Implementation Notes