summaryrefslogtreecommitdiffstats
path: root/kernel/fs/coda/cnode.c
blob: 7740b1c871c183ea55994e84812273effa58a476 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/* cnode related routines for the coda kernel code
   (C) 1996 Peter Braam
   */

#include <linux/types.h>
#include <linux/string.h>
#include <linux/time.h>

#include <linux/coda.h>
#include <linux/coda_psdev.h>
#include "coda_linux.h"

static inline int coda_fideq(struct CodaFid *fid1, struct CodaFid *fid2)
{
	return memcmp(fid1, fid2, sizeof(*fid1)) == 0;
}

static const struct inode_operations coda_symlink_inode_operations = {
	.readlink	= generic_readlink,
	.follow_link	= page_follow_link_light,
	.put_link	= page_put_link,
	.setattr	= coda_setattr,
};

/* cnode.c */
static void coda_fill_inode(struct inode *inode, struct coda_vattr *attr)
{
        coda_vattr_to_iattr(inode, attr);

        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->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);

	inode = iget5_locked(sb, hash, coda_test_inode, coda_set_inode, fid);

	if (!inode)
		return ERR_PTR(-ENOMEM);

	if (inode->i_state & 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;
		unlock_new_inode(inode);
	}

	/* always replace the attributes, type might have changed */
	coda_fill_inode(inode, attr);
	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
 * and new values of the identifier to handle any in-flight upcalls.
 * The real solution is to use globally unique UUIDs as identifiers, but
 * retrofitting the existing userspace code for this is non-trivial. */
void coda_replace_fid(struct inode *inode, struct CodaFid *oldfid, 
		      struct CodaFid *newfid)
{
	struct coda_inode_info *cii = ITOC(inode);
	unsigned long hash = coda_f2i(newfid);
	
	BUG_ON(!coda_fideq(&cii->c_fid, oldfid));

	/* replace fid and rehash inode */
	/* XXX we probably need to hold some lock here! */
	remove_inode_hash(inode);
	cii->c_fid = *newfid;
	inode->i_ino = hash;
	__insert_inode_hash(inode, hash);
}

/* convert a fid to an inode. */
struct inode *coda_fid_to_inode(struct CodaFid *fid, struct super_block *sb) 
{
	struct inode *inode;
	unsigned long hash = coda_f2i(fid);

	if ( !sb ) {
		pr_warn("%s: no sb!\n", __func__);
		return NULL;
	}

	inode = ilookup5(sb, hash, coda_test_inode, fid);
	if ( !inode )
		return NULL;

	/* we should never see newly created inodes because we intentionally
	 * fail in the initialization callback */
	BUG_ON(inode->i_state & I_NEW);

	return inode;
}

/* the CONTROL inode is made without asking attributes from Venus */
struct inode *coda_cnode_makectl(struct super_block *sb)
{
	struct inode *inode = new_inode(sb);
	if (inode) {
		inode->i_ino = CTL_INO;
		inode->i_op = &coda_ioctl_inode_operations;
		inode->i_fop = &coda_ioctl_operations;
		inode->i_mode = 0444;
		return inode;
	}
	return ERR_PTR(-ENOMEM);
}
"n">from C version HXCOMM DEF(command, args, callback, arg_string, help) is used to construct HXCOMM monitor info commands HXCOMM HXCOMM can be used for comments, discarded from both texi and C STEXI @table @option @item info @var{subcommand} @findex info Show various information about the system state. @table @option ETEXI { .name = "version", .args_type = "", .params = "", .help = "show the version of QEMU", .mhandler.cmd = hmp_info_version, }, STEXI @item info version @findex version Show the version of QEMU. ETEXI { .name = "network", .args_type = "", .params = "", .help = "show the network state", .mhandler.cmd = hmp_info_network, }, STEXI @item info network @findex network Show the network state. ETEXI { .name = "chardev", .args_type = "", .params = "", .help = "show the character devices", .mhandler.cmd = hmp_info_chardev, }, STEXI @item info chardev @findex chardev Show the character devices. ETEXI { .name = "block", .args_type = "nodes:-n,verbose:-v,device:B?", .params = "[-n] [-v] [device]", .help = "show info of one block device or all block devices " "(-n: show named nodes; -v: show details)", .mhandler.cmd = hmp_info_block, }, STEXI @item info block @findex block Show info of one block device or all block devices. ETEXI { .name = "blockstats", .args_type = "", .params = "", .help = "show block device statistics", .mhandler.cmd = hmp_info_blockstats, }, STEXI @item info blockstats @findex blockstats Show block device statistics. ETEXI { .name = "block-jobs", .args_type = "", .params = "", .help = "show progress of ongoing block device operations", .mhandler.cmd = hmp_info_block_jobs, }, STEXI @item info block-jobs @findex block-jobs Show progress of ongoing block device operations. ETEXI { .name = "registers", .args_type = "", .params = "", .help = "show the cpu registers", .mhandler.cmd = hmp_info_registers, }, STEXI @item info registers @findex registers Show the cpu registers. ETEXI #if defined(TARGET_I386) { .name = "lapic", .args_type = "", .params = "", .help = "show local apic state", .mhandler.cmd = hmp_info_local_apic, }, #endif STEXI @item info lapic @findex lapic Show local APIC state ETEXI #if defined(TARGET_I386) { .name = "ioapic", .args_type = "", .params = "", .help = "show io apic state", .mhandler.cmd = hmp_info_io_apic, }, #endif STEXI @item info ioapic @findex ioapic Show io APIC state ETEXI { .name = "cpus", .args_type = "", .params = "", .help = "show infos for each CPU", .mhandler.cmd = hmp_info_cpus, }, STEXI @item info cpus @findex cpus Show infos for each CPU. ETEXI { .name = "history", .args_type = "", .params = "", .help = "show the command line history", .mhandler.cmd = hmp_info_history, }, STEXI @item info history @findex history Show the command line history. ETEXI #if defined(TARGET_I386) || defined(TARGET_PPC) || defined(TARGET_MIPS) || \ defined(TARGET_LM32) || (defined(TARGET_SPARC) && !defined(TARGET_SPARC64)) { .name = "irq", .args_type = "", .params = "", .help = "show the interrupts statistics (if available)", #ifdef TARGET_SPARC .mhandler.cmd = sun4m_hmp_info_irq, #elif defined(TARGET_LM32) .mhandler.cmd = lm32_hmp_info_irq, #else .mhandler.cmd = hmp_info_irq, #endif }, STEXI @item info irq @findex irq Show the interrupts statistics (if available). ETEXI { .name = "pic", .args_type = "", .params = "", .help = "show i8259 (PIC) state", #ifdef TARGET_SPARC .mhandler.cmd = sun4m_hmp_info_pic, #elif defined(TARGET_LM32) .mhandler.cmd = lm32_hmp_info_pic, #else .mhandler.cmd = hmp_info_pic, #endif }, #endif STEXI @item info pic @findex pic Show i8259 (PIC) state. ETEXI { .name = "pci", .args_type = "", .params = "", .help = "show PCI info", .mhandler.cmd = hmp_info_pci, }, STEXI @item info pci @findex pci Show PCI information. ETEXI #if defined(TARGET_I386) || defined(TARGET_SH4) || defined(TARGET_SPARC) || \ defined(TARGET_PPC) || defined(TARGET_XTENSA) { .name = "tlb", .args_type = "", .params = "", .help = "show virtual to physical memory mappings", .mhandler.cmd = hmp_info_tlb, }, #endif STEXI @item info tlb @findex tlb Show virtual to physical memory mappings. ETEXI #if defined(TARGET_I386) { .name = "mem", .args_type = "", .params = "", .help = "show the active virtual memory mappings", .mhandler.cmd = hmp_info_mem, }, #endif STEXI @item info mem @findex mem Show the active virtual memory mappings. ETEXI { .name = "mtree", .args_type = "", .params = "", .help = "show memory tree", .mhandler.cmd = hmp_info_mtree, }, STEXI @item info mtree @findex mtree Show memory tree. ETEXI { .name = "jit", .args_type = "", .params = "", .help = "show dynamic compiler info", .mhandler.cmd = hmp_info_jit, }, STEXI @item info jit @findex jit Show dynamic compiler info. ETEXI { .name = "opcount", .args_type = "", .params = "", .help = "show dynamic compiler opcode counters", .mhandler.cmd = hmp_info_opcount, }, STEXI @item info opcount @findex opcount Show dynamic compiler opcode counters ETEXI { .name = "kvm", .args_type = "", .params = "", .help = "show KVM information", .mhandler.cmd = hmp_info_kvm, }, STEXI @item info kvm @findex kvm Show KVM information. ETEXI { .name = "numa", .args_type = "", .params = "", .help = "show NUMA information", .mhandler.cmd = hmp_info_numa, }, STEXI @item info numa @findex numa Show NUMA information. ETEXI { .name = "usb", .args_type = "", .params = "", .help = "show guest USB devices", .mhandler.cmd = hmp_info_usb, }, STEXI @item info usb @findex usb Show guest USB devices. ETEXI { .name = "usbhost", .args_type = "", .params = "", .help = "show host USB devices", .mhandler.cmd = hmp_info_usbhost, }, STEXI @item info usbhost @findex usbhost Show host USB devices. ETEXI { .name = "profile", .args_type = "", .params = "", .help = "show profiling information", .mhandler.cmd = hmp_info_profile, }, STEXI @item info profile @findex profile Show profiling information. ETEXI { .name = "capture", .args_type = "", .params = "", .help = "show capture information", .mhandler.cmd = hmp_info_capture, }, STEXI @item info capture @findex capture Show capture information. ETEXI { .name = "snapshots", .args_type = "", .params = "", .help = "show the currently saved VM snapshots", .mhandler.cmd = hmp_info_snapshots, }, STEXI @item info snapshots @findex snapshots Show the currently saved VM snapshots. ETEXI { .name = "status", .args_type = "", .params = "", .help = "show the current VM status (running|paused)", .mhandler.cmd = hmp_info_status, }, STEXI @item info status @findex status Show the current VM status (running|paused). ETEXI { .name = "mice", .args_type = "", .params = "", .help = "show which guest mouse is receiving events", .mhandler.cmd = hmp_info_mice, }, STEXI @item info mice @findex mice Show which guest mouse is receiving events. ETEXI { .name = "vnc", .args_type = "", .params = "", .help = "show the vnc server status", .mhandler.cmd = hmp_info_vnc, }, STEXI @item info vnc @findex vnc Show the vnc server status. ETEXI #if defined(CONFIG_SPICE) { .name = "spice", .args_type = "", .params = "", .help = "show the spice server status", .mhandler.cmd = hmp_info_spice, }, #endif STEXI @item info spice @findex spice Show the spice server status. ETEXI { .name = "name", .args_type = "", .params = "", .help = "show the current VM name", .mhandler.cmd = hmp_info_name, }, STEXI @item info name @findex name Show the current VM name. ETEXI { .name = "uuid", .args_type = "", .params = "", .help = "show the current VM UUID", .mhandler.cmd = hmp_info_uuid, }, STEXI @item info uuid @findex uuid Show the current VM UUID. ETEXI { .name = "cpustats", .args_type = "", .params = "", .help = "show CPU statistics", .mhandler.cmd = hmp_info_cpustats, }, STEXI @item info cpustats @findex cpustats Show CPU statistics. ETEXI #if defined(CONFIG_SLIRP) { .name = "usernet", .args_type = "", .params = "", .help = "show user network stack connection states", .mhandler.cmd = hmp_info_usernet, }, #endif STEXI @item info usernet @findex usernet Show user network stack connection states. ETEXI { .name = "migrate", .args_type = "", .params = "", .help = "show migration status", .mhandler.cmd = hmp_info_migrate, }, STEXI @item info migrate @findex migrate Show migration status. ETEXI { .name = "migrate_capabilities", .args_type = "", .params = "", .help = "show current migration capabilities", .mhandler.cmd = hmp_info_migrate_capabilities, }, STEXI @item info migrate_capabilities @findex migrate_capabilities Show current migration capabilities. ETEXI { .name = "migrate_parameters", .args_type = "", .params = "", .help = "show current migration parameters", .mhandler.cmd = hmp_info_migrate_parameters, }, STEXI @item info migrate_parameters @findex migrate_parameters Show current migration parameters. ETEXI { .name = "migrate_cache_size", .args_type = "", .params = "", .help = "show current migration xbzrle cache size", .mhandler.cmd = hmp_info_migrate_cache_size, }, STEXI @item info migrate_cache_size @findex migrate_cache_size Show current migration xbzrle cache size. ETEXI { .name = "balloon", .args_type = "", .params = "", .help = "show balloon information", .mhandler.cmd = hmp_info_balloon, }, STEXI @item info balloon @findex balloon Show balloon information. ETEXI { .name = "qtree", .args_type = "", .params = "", .help = "show device tree", .mhandler.cmd = hmp_info_qtree, }, STEXI @item info qtree @findex qtree Show device tree. ETEXI { .name = "qdm", .args_type = "", .params = "", .help = "show qdev device model list", .mhandler.cmd = hmp_info_qdm, }, STEXI @item info qdm @findex qdm Show qdev device model list. ETEXI { .name = "qom-tree", .args_type = "path:s?", .params = "[path]", .help = "show QOM composition tree", .mhandler.cmd = hmp_info_qom_tree, }, STEXI @item info qom-tree @findex qom-tree Show QOM composition tree. ETEXI { .name = "roms", .args_type = "", .params = "", .help = "show roms", .mhandler.cmd = hmp_info_roms, }, STEXI @item info roms @findex roms Show roms. ETEXI { .name = "trace-events", .args_type = "", .params = "", .help = "show available trace-events & their state", .mhandler.cmd = hmp_info_trace_events, }, STEXI @item info trace-events @findex trace-events Show available trace-events & their state. ETEXI { .name = "tpm", .args_type = "", .params = "", .help = "show the TPM device", .mhandler.cmd = hmp_info_tpm, }, STEXI @item info tpm @findex tpm Show the TPM device. ETEXI { .name = "memdev", .args_type = "", .params = "", .help = "show memory backends", .mhandler.cmd = hmp_info_memdev, }, STEXI @item info memdev @findex memdev Show memory backends ETEXI { .name = "memory-devices", .args_type = "", .params = "", .help = "show memory devices", .mhandler.cmd = hmp_info_memory_devices, }, STEXI @item info memory-devices @findex memory-devices Show memory devices. ETEXI { .name = "iothreads", .args_type = "", .params = "", .help = "show iothreads", .mhandler.cmd = hmp_info_iothreads, }, STEXI @item info iothreads @findex iothreads Show iothread's identifiers. ETEXI { .name = "rocker", .args_type = "name:s", .params = "name", .help = "Show rocker switch", .mhandler.cmd = hmp_rocker, }, STEXI @item info rocker @var{name} @findex rocker Show rocker switch. ETEXI { .name = "rocker-ports", .args_type = "name:s", .params = "name", .help = "Show rocker ports", .mhandler.cmd = hmp_rocker_ports, }, STEXI @item info rocker_ports @var{name}-ports @findex ocker-ports Show rocker ports. ETEXI { .name = "rocker-of-dpa-flows", .args_type = "name:s,tbl_id:i?", .params = "name [tbl_id]", .help = "Show rocker OF-DPA flow tables", .mhandler.cmd = hmp_rocker_of_dpa_flows, }, STEXI @item info rocker_of_dpa_flows @var{name} [@var{tbl_id}] @findex rocker-of-dpa-flows Show rocker OF-DPA flow tables. ETEXI { .name = "rocker-of-dpa-groups", .args_type = "name:s,type:i?", .params = "name [type]", .help = "Show rocker OF-DPA groups", .mhandler.cmd = hmp_rocker_of_dpa_groups, }, STEXI @item info rocker-of-dpa-groups @var{name} [@var{type}] @findex rocker-of-dpa-groups Show rocker OF-DPA groups. ETEXI #if defined(TARGET_S390X) { .name = "skeys", .args_type = "addr:l", .params = "address", .help = "Display the value of a storage key", .mhandler.cmd = hmp_info_skeys, }, #endif STEXI @item info skeys @var{address} @findex skeys Display the value of a storage key (s390 only) ETEXI { .name = "dump", .args_type = "", .params = "", .help = "Display the latest dump status", .mhandler.cmd = hmp_info_dump, }, STEXI @item info dump @findex dump Display the latest dump status. ETEXI STEXI @end table ETEXI STEXI @end table ETEXI