mirror of
https://github.com/xen-project/xen.git
synced 2026-10-29 18:50:05 +01:00
Merge.
This commit is contained in:
commit
23c5fd855d
18 files changed
+278
-106
No files matched your search
@@ -674,10 +674,10 @@ CONFIG_EXT2_FS=y
|
||||
CONFIG_EXT2_FS_XATTR=y
|
||||
CONFIG_EXT2_FS_POSIX_ACL=y
|
||||
CONFIG_EXT2_FS_SECURITY=y
|
||||
CONFIG_EXT3_FS=m
|
||||
CONFIG_EXT3_FS=y
|
||||
CONFIG_EXT3_FS_XATTR=y
|
||||
CONFIG_EXT3_FS_POSIX_ACL=y
|
||||
CONFIG_EXT3_FS_SECURITY=y
|
||||
# CONFIG_EXT3_FS_POSIX_ACL is not set
|
||||
# CONFIG_EXT3_FS_SECURITY is not set
|
||||
CONFIG_JBD=m
|
||||
# CONFIG_JBD_DEBUG is not set
|
||||
CONFIG_FS_MBCACHE=y
|
||||
|
||||
@@ -128,8 +128,12 @@ static int __init init_syscall32(void)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
__initcall(init_syscall32);
|
||||
|
||||
/*
|
||||
* This must be done early in case we have an initrd containing 32-bit
|
||||
* binaries (e.g., hotplug). This could be pushed upstream to arch/x86_64.
|
||||
*/
|
||||
core_initcall(init_syscall32);
|
||||
|
||||
/* May not be __init: called during resume */
|
||||
void syscall32_cpu_init(void)
|
||||
|
||||
@@ -43,7 +43,7 @@ ENTRY(_start)
|
||||
cld
|
||||
/* Copy the necessary stuff from xen_start_info structure. */
|
||||
movq $xen_start_info_union,%rdi
|
||||
movq $64,%rcx /* sizeof (union xen_start_info_union) / sizeof (long) */
|
||||
movq $256,%rcx
|
||||
rep movsq
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
|
||||
@@ -428,8 +428,9 @@ static void __init contig_initmem_init(void)
|
||||
{
|
||||
unsigned long bootmap_size = init_bootmem(start_pfn, end_pfn);
|
||||
free_bootmem(0, end_pfn << PAGE_SHIFT);
|
||||
/* XXX KAF: Why can't we leave low 1MB of memory free? */
|
||||
reserve_bootmem(0, (PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1));
|
||||
reserve_bootmem(HIGH_MEMORY,
|
||||
(PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1)
|
||||
- HIGH_MEMORY);
|
||||
}
|
||||
#else
|
||||
static void __init contig_initmem_init(void)
|
||||
|
||||
@@ -441,6 +441,31 @@ static inline void __set_pte(pte_t *dst, pte_t val)
|
||||
*dst = val;
|
||||
}
|
||||
|
||||
static inline int make_readonly(unsigned long paddr)
|
||||
{
|
||||
int readonly = 0;
|
||||
|
||||
/* Make new page tables read-only. */
|
||||
if ((paddr < ((table_start << PAGE_SHIFT) + tables_space)) &&
|
||||
(paddr >= (table_start << PAGE_SHIFT)))
|
||||
readonly = 1;
|
||||
|
||||
/* Make old page tables read-only. */
|
||||
if ((paddr < ((xen_start_info.pt_base - __START_KERNEL_map) +
|
||||
(xen_start_info.nr_pt_frames << PAGE_SHIFT))) &&
|
||||
(paddr >= (xen_start_info.pt_base - __START_KERNEL_map)))
|
||||
readonly = 1;
|
||||
|
||||
/*
|
||||
* No need for writable mapping of kernel image. This also ensures that
|
||||
* page and descriptor tables embedded inside don't have writable mappings.
|
||||
*/
|
||||
if ((paddr >= __pa_symbol(&_text)) && (paddr < __pa_symbol(&_end)))
|
||||
readonly = 1;
|
||||
|
||||
return readonly;
|
||||
}
|
||||
|
||||
void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
|
||||
{
|
||||
long i, j, k;
|
||||
@@ -477,9 +502,7 @@ void __init phys_pud_init(pud_t *pud, unsigned long address, unsigned long end)
|
||||
pte = alloc_low_page(&pte_phys);
|
||||
pte_save = pte;
|
||||
for (k = 0; k < PTRS_PER_PTE; pte++, k++, paddr += PTE_SIZE) {
|
||||
if (paddr < (table_start << PAGE_SHIFT)
|
||||
+ tables_space)
|
||||
{
|
||||
if (make_readonly(paddr)) {
|
||||
__set_pte(pte,
|
||||
__pte(paddr | (_KERNPG_TABLE & ~_PAGE_RW)));
|
||||
continue;
|
||||
|
||||
@@ -75,24 +75,12 @@ static void frontend_changed(struct xenbus_watch *watch, const char *node)
|
||||
err = xenbus_gather(be->frontpath, "grant-id", "%lu", &sharedmfn,
|
||||
"event-channel", "%u", &evtchn, NULL);
|
||||
if (err) {
|
||||
xenbus_dev_error(be->dev, err,
|
||||
xenbus_dev_error(be->dev, err,
|
||||
"reading %s/grant-id and event-channel",
|
||||
be->frontpath);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Domains must use same shared frame for all vbds. */
|
||||
if (evtchn != be->blkif->remote_evtchn ||
|
||||
sharedmfn != be->blkif->shmem_frame) {
|
||||
xenbus_dev_error(be->dev, err,
|
||||
"Shared frame/evtchn %li/%u not same as"
|
||||
" old %li/%u",
|
||||
sharedmfn, evtchn,
|
||||
be->blkif->shmem_frame,
|
||||
be->blkif->remote_evtchn);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Supply the information about the device the frontend needs */
|
||||
err = xenbus_transaction_start(be->dev->nodename);
|
||||
if (err) {
|
||||
@@ -189,6 +177,9 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
|
||||
err = register_xenbus_watch(&be->watch);
|
||||
if (err) {
|
||||
be->watch.node = NULL;
|
||||
xenbus_dev_error(dev, err,
|
||||
"adding frontend watch on %s",
|
||||
be->frontpath);
|
||||
goto device_fail;
|
||||
}
|
||||
}
|
||||
@@ -223,12 +214,15 @@ static void backend_changed(struct xenbus_watch *watch, const char *node)
|
||||
if (IS_ERR(be->blkif)) {
|
||||
err = PTR_ERR(be->blkif);
|
||||
be->blkif = NULL;
|
||||
xenbus_dev_error(dev, err, "creating block interface");
|
||||
goto device_fail;
|
||||
}
|
||||
|
||||
err = vbd_create(be->blkif, handle, be->pdev, be->readonly);
|
||||
if (err)
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, err, "creating vbd structure");
|
||||
goto device_fail;
|
||||
}
|
||||
|
||||
frontend_changed(&be->watch, be->frontpath);
|
||||
}
|
||||
@@ -250,8 +244,10 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
int err;
|
||||
|
||||
be = kmalloc(sizeof(*be), GFP_KERNEL);
|
||||
if (!be)
|
||||
if (!be) {
|
||||
xenbus_dev_error(dev, -ENOMEM, "allocating backend structure");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memset(be, 0, sizeof(*be));
|
||||
|
||||
@@ -259,8 +255,11 @@ static int blkback_probe(struct xenbus_device *dev,
|
||||
be->backend_watch.node = dev->nodename;
|
||||
be->backend_watch.callback = backend_changed;
|
||||
err = register_xenbus_watch(&be->backend_watch);
|
||||
if (err)
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, err, "adding backend watch on %s",
|
||||
dev->nodename);
|
||||
goto free_be;
|
||||
}
|
||||
|
||||
dev->data = be;
|
||||
|
||||
|
||||
@@ -1165,8 +1165,10 @@ static int talk_to_backend(struct xenbus_device *dev,
|
||||
|
||||
/* Create shared ring, alloc event channel. */
|
||||
err = setup_blkring(dev, info);
|
||||
if (err)
|
||||
if (err) {
|
||||
xenbus_dev_error(dev, err, "setting up block ring");
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = xenbus_transaction_start(dev->nodename);
|
||||
if (err) {
|
||||
@@ -1329,9 +1331,9 @@ static int wait_for_blkif(void)
|
||||
int i;
|
||||
|
||||
/*
|
||||
* We should read 'nr_interfaces' from response message and wait
|
||||
* for notifications before proceeding. For now we assume that we
|
||||
* will be notified of exactly one interface.
|
||||
* We should figure out how many and which devices we need to
|
||||
* proceed and only wait for those. For now, continue once the
|
||||
* first device is around.
|
||||
*/
|
||||
for ( i=0; blkif_state != BLKIF_STATE_CONNECTED && (i < 10*HZ); i++ )
|
||||
{
|
||||
|
||||
@@ -200,6 +200,7 @@ static char *be_state_name[] = {
|
||||
[BEST_CONNECTED] = "connected",
|
||||
};
|
||||
|
||||
#define DEBUG
|
||||
#ifdef DEBUG
|
||||
#define DPRINTK(fmt, args...) \
|
||||
printk(KERN_ALERT "xen_net (%s:%d) " fmt, __FUNCTION__, __LINE__, ##args)
|
||||
@@ -919,6 +920,7 @@ static void vif_show(struct net_private *np)
|
||||
/* Send a connect message to xend to tell it to bring up the interface. */
|
||||
static void send_interface_connect(struct net_private *np)
|
||||
{
|
||||
int err;
|
||||
ctrl_msg_t cmsg = {
|
||||
.type = CMSG_NETIF_FE,
|
||||
.subtype = CMSG_NETIF_FE_INTERFACE_CONNECT,
|
||||
@@ -929,24 +931,22 @@ static void send_interface_connect(struct net_private *np)
|
||||
msg->handle = np->handle;
|
||||
msg->tx_shmem_frame = virt_to_mfn(np->tx);
|
||||
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
|
||||
msg->tx_shmem_ref = (u32)gnttab_claim_grant_reference(&gref_tx_head);
|
||||
if(msg->tx_shmem_ref < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't claim tx_shmem reference\n");
|
||||
err = gnttab_grant_foreign_access(rdomid, msg->tx_shmem_frame, 0);
|
||||
if (err < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't grant access to tx_shmem\n");
|
||||
BUG();
|
||||
}
|
||||
gnttab_grant_foreign_access_ref (msg->tx_shmem_ref, rdomid,
|
||||
msg->tx_shmem_frame, 0);
|
||||
msg->tx_shmem_ref = err;
|
||||
#endif
|
||||
|
||||
msg->rx_shmem_frame = virt_to_mfn(np->rx);
|
||||
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
|
||||
msg->rx_shmem_ref = (u32)gnttab_claim_grant_reference(&gref_rx_head);
|
||||
if(msg->rx_shmem_ref < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't claim rx_shmem reference\n");
|
||||
err = gnttab_grant_foreign_access(rdomid, msg->rx_shmem_frame, 0);
|
||||
if (err < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't grant access to rx_shmem\n");
|
||||
BUG();
|
||||
}
|
||||
gnttab_grant_foreign_access_ref (msg->rx_shmem_ref, rdomid,
|
||||
msg->rx_shmem_frame, 0);
|
||||
msg->rx_shmem_ref = err;
|
||||
#endif
|
||||
|
||||
ctrl_if_send_message_block(&cmsg, NULL, 0, TASK_UNINTERRUPTIBLE);
|
||||
@@ -1416,8 +1416,8 @@ static int __init netif_init(void)
|
||||
if (xen_start_info.flags & SIF_INITDOMAIN)
|
||||
return 0;
|
||||
#ifdef CONFIG_XEN_NETDEV_GRANT_TX
|
||||
/* A grant for every ring slot, plus one for the ring itself */
|
||||
if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE + 1,
|
||||
/* A grant for every ring slot */
|
||||
if (gnttab_alloc_grant_references(NETIF_TX_RING_SIZE,
|
||||
&gref_tx_head) < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't alloc tx grant refs\n");
|
||||
return 1;
|
||||
@@ -1425,8 +1425,8 @@ static int __init netif_init(void)
|
||||
printk(KERN_ALERT "Netdev frontend (TX) is using grant tables.\n");
|
||||
#endif
|
||||
#ifdef CONFIG_XEN_NETDEV_GRANT_RX
|
||||
/* A grant for every ring slot, plus one for the ring itself */
|
||||
if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE + 1,
|
||||
/* A grant for every ring slot */
|
||||
if (gnttab_alloc_grant_references(NETIF_RX_RING_SIZE,
|
||||
&gref_rx_head) < 0) {
|
||||
printk(KERN_ALERT "#### netfront can't alloc rx grant refs\n");
|
||||
return 1;
|
||||
|
||||
@@ -627,6 +627,8 @@ int do_xenbus_probe(void *unused)
|
||||
/* Watch for changes. */
|
||||
register_xenbus_watch(&fe_watch);
|
||||
register_xenbus_watch(&be_watch);
|
||||
/* Notify others that xenstore is up */
|
||||
notifier_call_chain(&xenstore_chain, 0, 0);
|
||||
up(&xenbus_lock);
|
||||
return 0;
|
||||
}
|
||||
@@ -637,7 +639,7 @@ static int __init xenbus_probe_init(void)
|
||||
bus_register(&xenbus_backend.bus);
|
||||
device_register(&xenbus_frontend.dev);
|
||||
device_register(&xenbus_backend.dev);
|
||||
|
||||
|
||||
if (!xen_start_info.store_evtchn)
|
||||
return 0;
|
||||
|
||||
|
||||
@@ -8,23 +8,12 @@
|
||||
|
||||
static char * __init machine_specific_memory_setup(void)
|
||||
{
|
||||
char *who;
|
||||
unsigned long start_pfn, max_pfn;
|
||||
|
||||
who = "Xen";
|
||||
|
||||
/* In dom0, we have to start the fake e820 map above the first
|
||||
* 1MB, in other domains, it can start at 0. */
|
||||
if (xen_start_info.flags & SIF_INITDOMAIN)
|
||||
start_pfn = 0x100;
|
||||
else
|
||||
start_pfn = 0;
|
||||
max_pfn = xen_start_info.nr_pages;
|
||||
unsigned long max_pfn = xen_start_info.nr_pages;
|
||||
|
||||
e820.nr_map = 0;
|
||||
add_memory_region(PFN_PHYS(start_pfn), PFN_PHYS(max_pfn) - PFN_PHYS(start_pfn), E820_RAM);
|
||||
add_memory_region(0, PFN_PHYS(max_pfn), E820_RAM);
|
||||
|
||||
return who;
|
||||
return "Xen";
|
||||
}
|
||||
|
||||
void __init machine_specific_modify_cpu_capabilities(struct cpuinfo_x86 *c)
|
||||
|
||||
@@ -32,3 +32,16 @@ expect mkdir failed: File exists
|
||||
mkdir /dir
|
||||
expect mkdir failed: File exists
|
||||
mkdir /dir/test2
|
||||
|
||||
# Mkdir implicitly creates directories.
|
||||
mkdir /dir/1/2/3/4
|
||||
expect test2
|
||||
expect 1
|
||||
dir /dir
|
||||
expect 2
|
||||
dir /dir/1
|
||||
expect 3
|
||||
dir /dir/1/2
|
||||
expect 4
|
||||
dir /dir/1/2/3
|
||||
dir /dir/1/2/3/4
|
||||
@@ -18,3 +18,22 @@ read /test
|
||||
write /test create contents3
|
||||
expect contents3
|
||||
read /test
|
||||
|
||||
# Write should implicitly create directories
|
||||
write /dir/test create contents
|
||||
expect test
|
||||
dir /dir
|
||||
expect contents
|
||||
read /dir/test
|
||||
write /dir/1/2/3/4 excl contents4
|
||||
expect test
|
||||
expect 1
|
||||
dir /dir
|
||||
expect 2
|
||||
dir /dir/1
|
||||
expect 3
|
||||
dir /dir/1/2
|
||||
expect 4
|
||||
dir /dir/1/2/3
|
||||
expect contents4
|
||||
read /dir/1/2/3/4
|
||||
@@ -117,3 +117,11 @@ setid 3
|
||||
write /dir/subdir/subfile excl contents
|
||||
expect 3 READ/WRITE
|
||||
getperm /dir/subdir/subfile
|
||||
|
||||
# Inheritence works through multiple directories, too.
|
||||
write /dir/subdir/1/2/3/4 excl contents
|
||||
expect 3 READ/WRITE
|
||||
getperm /dir/subdir/1/2/3/4
|
||||
mkdir /dir/subdir/a/b/c/d
|
||||
expect 3 READ/WRITE
|
||||
getperm /dir/subdir/a/b/c/d
|
||||
@@ -8,7 +8,7 @@ run_test()
|
||||
rm -rf $XENSTORED_ROOTDIR
|
||||
mkdir $XENSTORED_ROOTDIR
|
||||
if [ $VALGRIND -eq 1 ]; then
|
||||
valgrind -q --logfile-fd=3 ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork 3>testsuite/tmp/vgout > /tmp/pid 2> testsuite/tmp/xenstored_errors &
|
||||
valgrind --suppressions=testsuite/vg-suppressions -q ./xenstored_test --output-pid --trace-file=testsuite/tmp/trace --no-fork > /tmp/pid 2> testsuite/tmp/xenstored_errors &
|
||||
while [ ! -s /tmp/pid ]; do sleep 0; done
|
||||
PID=`cat /tmp/pid`
|
||||
rm /tmp/pid
|
||||
@@ -17,10 +17,10 @@ run_test()
|
||||
PID=`./xenstored_test --output-pid --trace-file=testsuite/tmp/trace`
|
||||
fi
|
||||
if ./xs_test $2 $1; then
|
||||
if [ -s testsuite/tmp/vgout ]; then
|
||||
if [ -s testsuite/tmp/xenstored_errors ]; then
|
||||
kill $PID
|
||||
echo VALGRIND errors:
|
||||
cat testsuite/tmp/vgout
|
||||
echo Errors:
|
||||
cat testsuite/tmp/xenstored_errors
|
||||
return 1
|
||||
fi
|
||||
echo shutdown | ./xs_test
|
||||
@@ -52,11 +52,10 @@ for f in testsuite/[0-9]*.test $SLOWTESTS; do
|
||||
case `basename $f` in $MATCH) RUN=1;; esac
|
||||
[ -n "$RUN" ] || continue
|
||||
|
||||
if run_test $f > /dev/null; then
|
||||
if run_test $f -x >/tmp/out; then
|
||||
echo -n .
|
||||
else
|
||||
echo Test $f failed, running verbosely...
|
||||
run_test $f -x || true
|
||||
cat /tmp/out
|
||||
# That will have filled the screen, repeat message.
|
||||
echo Test $f failed
|
||||
exit 1
|
||||
|
||||
@@ -423,14 +423,24 @@ static char *node_dir(struct transaction *trans, const char *node)
|
||||
return node_dir_inside_transaction(trans, node);
|
||||
}
|
||||
|
||||
static char *datafile(const char *dir)
|
||||
{
|
||||
return talloc_asprintf(dir, "%s/.data", dir);
|
||||
}
|
||||
|
||||
static char *node_datafile(struct transaction *trans, const char *node)
|
||||
{
|
||||
return talloc_asprintf(node, "%s/.data", node_dir(trans, node));
|
||||
return datafile(node_dir(trans, node));
|
||||
}
|
||||
|
||||
static char *permfile(const char *dir)
|
||||
{
|
||||
return talloc_asprintf(dir, "%s/.perms", dir);
|
||||
}
|
||||
|
||||
static char *node_permfile(struct transaction *trans, const char *node)
|
||||
{
|
||||
return talloc_asprintf(node, "%s/.perms", node_dir(trans, node));
|
||||
return permfile(node_dir(trans, node));
|
||||
}
|
||||
|
||||
struct buffered_data *new_buffer(void *ctx)
|
||||
@@ -557,15 +567,14 @@ static const char *onearg(struct buffered_data *in)
|
||||
}
|
||||
|
||||
/* If it fails, returns NULL and sets errno. */
|
||||
static struct xs_permissions *get_perms(struct transaction *transaction,
|
||||
const char *node, unsigned int *num)
|
||||
static struct xs_permissions *get_perms(const char *dir, unsigned int *num)
|
||||
{
|
||||
unsigned int size;
|
||||
char *strings;
|
||||
struct xs_permissions *ret;
|
||||
int *fd;
|
||||
|
||||
fd = talloc_open(node_permfile(transaction, node), O_RDONLY, 0);
|
||||
fd = talloc_open(permfile(dir), O_RDONLY, 0);
|
||||
if (!fd)
|
||||
return NULL;
|
||||
strings = read_all(fd, &size);
|
||||
@@ -573,14 +582,14 @@ static struct xs_permissions *get_perms(struct transaction *transaction,
|
||||
return NULL;
|
||||
|
||||
*num = xs_count_strings(strings, size);
|
||||
ret = talloc_array(node, struct xs_permissions, *num);
|
||||
ret = talloc_array(dir, struct xs_permissions, *num);
|
||||
if (!xs_strings_to_perms(ret, *num, strings))
|
||||
corrupt(NULL, "Permissions corrupt for %s", node);
|
||||
corrupt(NULL, "Permissions corrupt for %s", dir);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static char *perms_to_strings(const char *node,
|
||||
static char *perms_to_strings(const void *ctx,
|
||||
struct xs_permissions *perms, unsigned int num,
|
||||
unsigned int *len)
|
||||
{
|
||||
@@ -592,7 +601,7 @@ static char *perms_to_strings(const char *node,
|
||||
if (!xs_perm_to_string(&perms[i], buffer))
|
||||
return NULL;
|
||||
|
||||
strings = talloc_realloc(node, strings, char,
|
||||
strings = talloc_realloc(ctx, strings, char,
|
||||
*len + strlen(buffer) + 1);
|
||||
strcpy(strings + *len, buffer);
|
||||
*len += strlen(buffer) + 1;
|
||||
@@ -625,16 +634,23 @@ int destroy_path(void *path)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Create a self-destructing temporary path */
|
||||
static char *temppath(const char *path)
|
||||
{
|
||||
char *tmppath = talloc_asprintf(path, "%s.tmp", path);
|
||||
talloc_set_destructor(tmppath, destroy_path);
|
||||
return tmppath;
|
||||
}
|
||||
|
||||
/* Create a self-destructing temporary file */
|
||||
static char *tempfile(const char *path, void *contents, unsigned int len)
|
||||
{
|
||||
int *fd;
|
||||
char *tmppath = talloc_asprintf(path, "%s.tmp", path);
|
||||
char *tmppath = temppath(path);
|
||||
|
||||
fd = talloc_open(tmppath, O_WRONLY|O_CREAT|O_EXCL, 0640);
|
||||
if (!fd)
|
||||
return NULL;
|
||||
talloc_set_destructor(tmppath, destroy_path);
|
||||
if (!xs_write_all(*fd, contents, len))
|
||||
return NULL;
|
||||
|
||||
@@ -732,7 +748,7 @@ static enum xs_perm_type ask_parents(struct connection *conn,
|
||||
|
||||
do {
|
||||
node = get_parent(node);
|
||||
perms = get_perms(conn->transaction, node, &num);
|
||||
perms = get_perms(node_dir(conn->transaction, node), &num);
|
||||
if (perms)
|
||||
break;
|
||||
} while (!streq(node, "/"));
|
||||
@@ -788,7 +804,7 @@ bool check_node_perms(struct connection *conn, const char *node,
|
||||
return false;
|
||||
}
|
||||
|
||||
perms = get_perms(conn->transaction, node, &num);
|
||||
perms = get_perms(node_dir(conn->transaction, node), &num);
|
||||
|
||||
if (perms) {
|
||||
if (perm_for_id(conn->id, perms, num) & perm)
|
||||
@@ -875,44 +891,64 @@ static void do_read(struct connection *conn, const char *node)
|
||||
send_reply(conn, XS_READ, value, size);
|
||||
}
|
||||
|
||||
/* Create a new directory. Optionally put data in it (if data != NULL) */
|
||||
static bool new_directory(struct connection *conn,
|
||||
const char *node, void *data, unsigned int datalen)
|
||||
/* Commit this directory, eg. comitting a/b.tmp/c causes a/b.tmp -> a.b */
|
||||
static bool commit_dir(char *dir)
|
||||
{
|
||||
char *dot, *slash, *dest;
|
||||
|
||||
dot = strrchr(dir, '.');
|
||||
slash = strchr(dot, '/');
|
||||
if (slash)
|
||||
*slash = '\0';
|
||||
|
||||
dest = talloc_asprintf(dir, "%.*s", dot - dir, dir);
|
||||
return rename(dir, dest) == 0;
|
||||
}
|
||||
|
||||
/* Create a temporary directory. Put data in it (if data != NULL) */
|
||||
static char *tempdir(struct connection *conn,
|
||||
const char *node, void *data, unsigned int datalen)
|
||||
{
|
||||
struct xs_permissions *perms;
|
||||
char *permstr;
|
||||
unsigned int num, len;
|
||||
int *fd;
|
||||
char *dir = node_dir(conn->transaction, node);
|
||||
char *dir;
|
||||
|
||||
if (mkdir(dir, 0750) != 0)
|
||||
return false;
|
||||
dir = temppath(node_dir(conn->transaction, node));
|
||||
if (mkdir(dir, 0750) != 0) {
|
||||
if (errno != ENOENT)
|
||||
return NULL;
|
||||
|
||||
/* Set destructor so we clean up if neccesary. */
|
||||
talloc_set_destructor(dir, destroy_path);
|
||||
dir = tempdir(conn, get_parent(node), NULL, 0);
|
||||
if (!dir)
|
||||
return NULL;
|
||||
|
||||
perms = get_perms(conn->transaction, get_parent(node), &num);
|
||||
dir = talloc_asprintf(dir, "%s%s", dir, strrchr(node, '/'));
|
||||
if (mkdir(dir, 0750) != 0)
|
||||
return NULL;
|
||||
talloc_set_destructor(dir, destroy_path);
|
||||
}
|
||||
|
||||
perms = get_perms(get_parent(dir), &num);
|
||||
assert(perms);
|
||||
/* Domains own what they create. */
|
||||
if (conn->id)
|
||||
perms->id = conn->id;
|
||||
|
||||
permstr = perms_to_strings(dir, perms, num, &len);
|
||||
fd = talloc_open(node_permfile(conn->transaction, node),
|
||||
O_WRONLY|O_CREAT|O_EXCL, 0640);
|
||||
fd = talloc_open(permfile(dir), O_WRONLY|O_CREAT|O_EXCL, 0640);
|
||||
if (!fd || !xs_write_all(*fd, permstr, len))
|
||||
return false;
|
||||
return NULL;
|
||||
|
||||
if (data) {
|
||||
char *datapath = node_datafile(conn->transaction, node);
|
||||
char *datapath = datafile(dir);
|
||||
|
||||
fd = talloc_open(datapath, O_WRONLY|O_CREAT|O_EXCL, 0640);
|
||||
if (!fd || !xs_write_all(*fd, data, datalen))
|
||||
return false;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Finished! */
|
||||
talloc_set_destructor(dir, NULL);
|
||||
return true;
|
||||
return dir;
|
||||
}
|
||||
|
||||
/* path, flags, data... */
|
||||
@@ -959,6 +995,8 @@ static void do_write(struct connection *conn, struct buffered_data *in)
|
||||
}
|
||||
|
||||
if (lstat(node_dir(conn->transaction, node), &st) != 0) {
|
||||
char *dir;
|
||||
|
||||
/* Does not exist... */
|
||||
if (errno != ENOENT) {
|
||||
send_error(conn, errno);
|
||||
@@ -971,10 +1009,12 @@ static void do_write(struct connection *conn, struct buffered_data *in)
|
||||
return;
|
||||
}
|
||||
|
||||
if (!new_directory(conn, node, in->buffer + offset, datalen)) {
|
||||
dir = tempdir(conn, node, in->buffer + offset, datalen);
|
||||
if (!dir || !commit_dir(dir)) {
|
||||
send_error(conn, errno);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Exists... */
|
||||
if (streq(vec[1], XS_WRITE_CREATE_EXCL)) {
|
||||
@@ -999,6 +1039,9 @@ static void do_write(struct connection *conn, struct buffered_data *in)
|
||||
|
||||
static void do_mkdir(struct connection *conn, const char *node)
|
||||
{
|
||||
char *dir;
|
||||
struct stat st;
|
||||
|
||||
node = canonicalize(conn, node);
|
||||
if (!check_node_perms(conn, node, XS_PERM_WRITE|XS_PERM_ENOENT_OK)) {
|
||||
send_error(conn, errno);
|
||||
@@ -1013,7 +1056,14 @@ static void do_mkdir(struct connection *conn, const char *node)
|
||||
if (transaction_block(conn, node))
|
||||
return;
|
||||
|
||||
if (!new_directory(conn, node, NULL, 0)) {
|
||||
/* Must not already exist. */
|
||||
if (lstat(node_dir(conn->transaction, node), &st) == 0) {
|
||||
send_error(conn, EEXIST);
|
||||
return;
|
||||
}
|
||||
|
||||
dir = tempdir(conn, node, NULL, 0);
|
||||
if (!dir || !commit_dir(dir)) {
|
||||
send_error(conn, errno);
|
||||
return;
|
||||
}
|
||||
@@ -1073,7 +1123,7 @@ static void do_get_perms(struct connection *conn, const char *node)
|
||||
return;
|
||||
}
|
||||
|
||||
perms = get_perms(conn->transaction, node, &num);
|
||||
perms = get_perms(node_dir(conn->transaction, node), &num);
|
||||
if (!perms) {
|
||||
send_error(conn, errno);
|
||||
return;
|
||||
|
||||
@@ -303,6 +303,34 @@ static bool file_set_perms(struct file_ops_info *info,
|
||||
return true;
|
||||
}
|
||||
|
||||
static char *parent_filename(const char *name)
|
||||
{
|
||||
char *slash = strrchr(name + 1, '/');
|
||||
if (!slash)
|
||||
return talloc_strdup(name, "/");
|
||||
return talloc_asprintf(name, "%.*s", slash-name, name);
|
||||
}
|
||||
|
||||
static void make_dirs(const char *filename)
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
if (lstat(filename, &st) == 0 && S_ISREG(st.st_mode))
|
||||
convert_to_dir(filename);
|
||||
|
||||
if (mkdir(filename, 0700) == 0) {
|
||||
init_perms(filename);
|
||||
return;
|
||||
}
|
||||
if (errno == EEXIST)
|
||||
return;
|
||||
|
||||
make_dirs(parent_filename(filename));
|
||||
if (mkdir(filename, 0700) != 0)
|
||||
barf_perror("Failed to mkdir %s", filename);
|
||||
init_perms(filename);
|
||||
}
|
||||
|
||||
static bool file_write(struct file_ops_info *info,
|
||||
const char *path, const void *data,
|
||||
unsigned int len, int createflags)
|
||||
@@ -329,6 +357,9 @@ static bool file_write(struct file_ops_info *info,
|
||||
}
|
||||
}
|
||||
|
||||
if (createflags & O_CREAT)
|
||||
make_dirs(parent_filename(filename));
|
||||
|
||||
fd = open(filename, createflags|O_TRUNC|O_WRONLY, 0600);
|
||||
if (fd < 0) {
|
||||
/* FIXME: Another hack. */
|
||||
@@ -352,6 +383,7 @@ static bool file_mkdir(struct file_ops_info *info, const char *path)
|
||||
if (!write_ok(info, path))
|
||||
return false;
|
||||
|
||||
make_dirs(parent_filename(dirname));
|
||||
if (mkdir(dirname, 0700) != 0)
|
||||
return false;
|
||||
|
||||
@@ -420,7 +452,7 @@ static bool file_transaction_end(struct file_ops_info *info, bool abort)
|
||||
}
|
||||
|
||||
if (abort) {
|
||||
cmd = talloc_asprintf(NULL, "rm -r %s", info->transact_base);
|
||||
cmd = talloc_asprintf(NULL, "rm -rf %s", info->transact_base);
|
||||
do_command(cmd);
|
||||
goto success;
|
||||
}
|
||||
@@ -1004,8 +1036,8 @@ static void setup_xs_ops(void)
|
||||
} else {
|
||||
dup2(fds[1], STDOUT_FILENO);
|
||||
close(fds[0]);
|
||||
#if 0
|
||||
execlp("valgrind", "valgrind", "xenstored_test", "--output-pid",
|
||||
#if 1
|
||||
execlp("valgrind", "valgrind", "-q", "--suppressions=testsuite/vg-suppressions", "xenstored_test", "--output-pid",
|
||||
"--no-fork", NULL);
|
||||
#else
|
||||
execlp("./xenstored_test", "xenstored_test", "--output-pid",
|
||||
|
||||
@@ -9,6 +9,20 @@
|
||||
|
||||
#include "cpu.h"
|
||||
|
||||
/*
|
||||
* amd_flush_filter={on,off}. Forcibly Enable or disable the TLB flush
|
||||
* filter on AMD 64-bit processors.
|
||||
*/
|
||||
static int flush_filter_force;
|
||||
static void flush_filter(char *s)
|
||||
{
|
||||
if (!strcmp(s, "off"))
|
||||
flush_filter_force = -1;
|
||||
if (!strcmp(s, "on"))
|
||||
flush_filter_force = 1;
|
||||
}
|
||||
custom_param("amd_flush_filter", flush_filter);
|
||||
|
||||
#define num_physpages 0
|
||||
|
||||
/*
|
||||
@@ -192,6 +206,21 @@ static void __init init_amd(struct cpuinfo_x86 *c)
|
||||
break;
|
||||
}
|
||||
|
||||
if (c->x86 == 15) {
|
||||
rdmsr(MSR_K7_HWCR, l, h);
|
||||
printk(KERN_INFO "CPU%d: AMD Flush Filter %sabled",
|
||||
smp_processor_id(), (l & (1<<6)) ? "dis" : "en");
|
||||
if ((flush_filter_force > 0) && (l & (1<<6))) {
|
||||
l &= ~(1<<6);
|
||||
printk(" -> Forcibly enabled");
|
||||
} else if ((flush_filter_force < 0) && !(l & (1<<6))) {
|
||||
l |= 1<<6;
|
||||
printk(" -> Forcibly disabled");
|
||||
}
|
||||
wrmsr(MSR_K7_HWCR, l, h);
|
||||
printk("\n");
|
||||
}
|
||||
|
||||
display_cacheinfo(c);
|
||||
|
||||
if (cpuid_eax(0x80000000) >= 0x80000008) {
|
||||
|
||||
+4
-2
@@ -1449,8 +1449,10 @@ int get_page_type(struct pfn_info *page, unsigned long type)
|
||||
if ( ((x & PGT_type_mask) != PGT_l2_page_table) ||
|
||||
((type & PGT_type_mask) != PGT_l1_page_table) )
|
||||
MEM_LOG("Bad type (saw %" PRtype_info
|
||||
"!= exp %" PRtype_info ") for pfn %lx",
|
||||
x, type, page_to_pfn(page));
|
||||
"!= exp %" PRtype_info ") "
|
||||
"for mfn %lx (pfn %x)",
|
||||
x, type, page_to_pfn(page),
|
||||
machine_to_phys_mapping[page_to_pfn(page)]);
|
||||
return 0;
|
||||
}
|
||||
else if ( (x & PGT_va_mask) == PGT_va_mutable )
|
||||
|
||||