Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
openeuler
libvirt
提交
55ae53d9
L
libvirt
项目概览
openeuler
/
libvirt
通知
3
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
L
libvirt
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
55ae53d9
编写于
4月 01, 2009
作者:
D
Daniel P. Berrange
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
SCSI HBA storage pool implementation (Dave Allan)
上级
ecedb9ce
变更
10
隐藏空白更改
内联
并排
Showing
10 changed file
with
633 addition
and
325 deletion
+633
-325
ChangeLog
ChangeLog
+15
-0
configure.in
configure.in
+11
-0
po/POTFILES.in
po/POTFILES.in
+1
-0
src/Makefile.am
src/Makefile.am
+8
-0
src/storage_backend.c
src/storage_backend.c
+6
-0
src/storage_backend_iscsi.c
src/storage_backend_iscsi.c
+14
-325
src/storage_backend_scsi.c
src/storage_backend_scsi.c
+510
-0
src/storage_backend_scsi.h
src/storage_backend_scsi.h
+43
-0
src/storage_conf.c
src/storage_conf.c
+18
-0
src/storage_conf.h
src/storage_conf.h
+7
-0
未找到文件。
ChangeLog
浏览文件 @
55ae53d9
Wed Apr 1 16:50:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
SCSI HBA storage pool implementation (Dave Allan)
* configure.in: Add flag for SCSI storage pool support
* po/POTFILES.in: Add storage_backend_scsi.c
* src/Makefile.am: Add new SCSI storage backend
* src/storage_backend.c: Support for SCSI pool type
* src/storage_backend_iscsi.c: Refactor to re-use logic from
SCSI pool backend
* src/storage_backend_scsi.c, src/storage_backend_scsi.h:
Generic pool for Linux SCSI HBAs (or things which look
like SCSI HBAs)
* src/storage_conf.c, src/storage_conf.h: Add logic for
SCSI storage pool XML parsing options
Wed Apr 1 11:40:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
Wed Apr 1 11:40:22 BST 2009 Daniel P. Berrange <berrange@redhat.com>
* configure.in: Check for libsasl.so as well as libsasl2.so
* configure.in: Check for libsasl.so as well as libsasl2.so
...
...
configure.in
浏览文件 @
55ae53d9
...
@@ -792,6 +792,8 @@ AC_ARG_WITH([storage-lvm],
...
@@ -792,6 +792,8 @@ AC_ARG_WITH([storage-lvm],
[ --with-storage-lvm with LVM backend for the storage driver (on)],[],[with_storage_lvm=check])
[ --with-storage-lvm with LVM backend for the storage driver (on)],[],[with_storage_lvm=check])
AC_ARG_WITH([storage-iscsi],
AC_ARG_WITH([storage-iscsi],
[ --with-storage-iscsi with iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check])
[ --with-storage-iscsi with iSCSI backend for the storage driver (on)],[],[with_storage_iscsi=check])
AC_ARG_WITH([storage-scsi],
[ --with-storage-scsi with SCSI backend for the storage driver (on)],[],[with_storage_scsi=check])
AC_ARG_WITH([storage-disk],
AC_ARG_WITH([storage-disk],
[ --with-storage-disk with GPartd Disk backend for the storage driver (on)],[],[with_storage_disk=check])
[ --with-storage-disk with GPartd Disk backend for the storage driver (on)],[],[with_storage_disk=check])
...
@@ -801,6 +803,7 @@ if test "$with_libvirtd" = "no"; then
...
@@ -801,6 +803,7 @@ if test "$with_libvirtd" = "no"; then
with_storage_fs=no
with_storage_fs=no
with_storage_lvm=no
with_storage_lvm=no
with_storage_iscsi=no
with_storage_iscsi=no
with_storage_scsi=no
with_storage_disk=no
with_storage_disk=no
fi
fi
if test "$with_storage_dir" = "yes" ; then
if test "$with_storage_dir" = "yes" ; then
...
@@ -929,6 +932,13 @@ if test "$with_storage_iscsi" = "yes" -o "$with_storage_iscsi" = "check"; then
...
@@ -929,6 +932,13 @@ if test "$with_storage_iscsi" = "yes" -o "$with_storage_iscsi" = "check"; then
fi
fi
AM_CONDITIONAL([WITH_STORAGE_ISCSI], [test "$with_storage_iscsi" = "yes"])
AM_CONDITIONAL([WITH_STORAGE_ISCSI], [test "$with_storage_iscsi" = "yes"])
if test "$with_storage_scsi" = "check"; then
with_storage_scsi=yes
AC_DEFINE_UNQUOTED([WITH_STORAGE_SCSI], 1,
[whether SCSI backend for storage driver is enabled])
AM_CONDITIONAL([WITH_STORAGE_SCSI], [test "$with_storage_scsi" = "yes"])
fi
LIBPARTED_CFLAGS=
LIBPARTED_CFLAGS=
...
@@ -1365,6 +1375,7 @@ AC_MSG_NOTICE([ FS: $with_storage_fs])
...
@@ -1365,6 +1375,7 @@ AC_MSG_NOTICE([ FS: $with_storage_fs])
AC_MSG_NOTICE([ NetFS: $with_storage_fs])
AC_MSG_NOTICE([ NetFS: $with_storage_fs])
AC_MSG_NOTICE([ LVM: $with_storage_lvm])
AC_MSG_NOTICE([ LVM: $with_storage_lvm])
AC_MSG_NOTICE([ iSCSI: $with_storage_iscsi])
AC_MSG_NOTICE([ iSCSI: $with_storage_iscsi])
AC_MSG_NOTICE([ SCSI: $with_storage_scsi])
AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([ Disk: $with_storage_disk])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([])
AC_MSG_NOTICE([Security Drivers])
AC_MSG_NOTICE([Security Drivers])
...
...
po/POTFILES.in
浏览文件 @
55ae53d9
...
@@ -30,6 +30,7 @@ src/storage_backend_disk.c
...
@@ -30,6 +30,7 @@ src/storage_backend_disk.c
src/storage_backend_fs.c
src/storage_backend_fs.c
src/storage_backend_iscsi.c
src/storage_backend_iscsi.c
src/storage_backend_logical.c
src/storage_backend_logical.c
src/storage_backend_scsi.c
src/storage_conf.c
src/storage_conf.c
src/storage_driver.c
src/storage_driver.c
src/test.c
src/test.c
...
...
src/Makefile.am
浏览文件 @
55ae53d9
...
@@ -159,6 +159,9 @@ STORAGE_DRIVER_LVM_SOURCES = \
...
@@ -159,6 +159,9 @@ STORAGE_DRIVER_LVM_SOURCES = \
STORAGE_DRIVER_ISCSI_SOURCES
=
\
STORAGE_DRIVER_ISCSI_SOURCES
=
\
storage_backend_iscsi.h storage_backend_iscsi.c
storage_backend_iscsi.h storage_backend_iscsi.c
STORAGE_DRIVER_SCSI_SOURCES
=
\
storage_backend_scsi.h storage_backend_scsi.c
STORAGE_DRIVER_DISK_SOURCES
=
\
STORAGE_DRIVER_DISK_SOURCES
=
\
storage_backend_disk.h storage_backend_disk.c
storage_backend_disk.h storage_backend_disk.c
...
@@ -353,6 +356,10 @@ if WITH_STORAGE_ISCSI
...
@@ -353,6 +356,10 @@ if WITH_STORAGE_ISCSI
libvirt_driver_storage_la_SOURCES
+=
$(STORAGE_DRIVER_ISCSI_SOURCES)
libvirt_driver_storage_la_SOURCES
+=
$(STORAGE_DRIVER_ISCSI_SOURCES)
endif
endif
if
WITH_STORAGE_SCSI
libvirt_driver_storage_la_SOURCES
+=
$(STORAGE_DRIVER_SCSI_SOURCES)
endif
if
WITH_STORAGE_DISK
if
WITH_STORAGE_DISK
libvirt_driver_storage_la_SOURCES
+=
$(STORAGE_DRIVER_DISK_SOURCES)
libvirt_driver_storage_la_SOURCES
+=
$(STORAGE_DRIVER_DISK_SOURCES)
endif
endif
...
@@ -408,6 +415,7 @@ EXTRA_DIST += \
...
@@ -408,6 +415,7 @@ EXTRA_DIST += \
$(STORAGE_DRIVER_FS_SOURCES)
\
$(STORAGE_DRIVER_FS_SOURCES)
\
$(STORAGE_DRIVER_LVM_SOURCES)
\
$(STORAGE_DRIVER_LVM_SOURCES)
\
$(STORAGE_DRIVER_ISCSI_SOURCES)
\
$(STORAGE_DRIVER_ISCSI_SOURCES)
\
$(STORAGE_DRIVER_SCSI_SOURCES)
\
$(STORAGE_DRIVER_DISK_SOURCES)
\
$(STORAGE_DRIVER_DISK_SOURCES)
\
$(NODE_DEVICE_DRIVER_SOURCES)
\
$(NODE_DEVICE_DRIVER_SOURCES)
\
$(NODE_DEVICE_DRIVER_HAL_SOURCES)
\
$(NODE_DEVICE_DRIVER_HAL_SOURCES)
\
...
...
src/storage_backend.c
浏览文件 @
55ae53d9
...
@@ -54,6 +54,9 @@
...
@@ -54,6 +54,9 @@
#if WITH_STORAGE_ISCSI
#if WITH_STORAGE_ISCSI
#include "storage_backend_iscsi.h"
#include "storage_backend_iscsi.h"
#endif
#endif
#if WITH_STORAGE_SCSI
#include "storage_backend_scsi.h"
#endif
#if WITH_STORAGE_DISK
#if WITH_STORAGE_DISK
#include "storage_backend_disk.h"
#include "storage_backend_disk.h"
#endif
#endif
...
@@ -78,6 +81,9 @@ static virStorageBackendPtr backends[] = {
...
@@ -78,6 +81,9 @@ static virStorageBackendPtr backends[] = {
#if WITH_STORAGE_ISCSI
#if WITH_STORAGE_ISCSI
&
virStorageBackendISCSI
,
&
virStorageBackendISCSI
,
#endif
#endif
#if WITH_STORAGE_SCSI
&
virStorageBackendSCSI
,
#endif
#if WITH_STORAGE_DISK
#if WITH_STORAGE_DISK
&
virStorageBackendDisk
,
&
virStorageBackendDisk
,
#endif
#endif
...
...
src/storage_backend_iscsi.c
浏览文件 @
55ae53d9
...
@@ -35,6 +35,7 @@
...
@@ -35,6 +35,7 @@
#include <dirent.h>
#include <dirent.h>
#include "virterror_internal.h"
#include "virterror_internal.h"
#include "storage_backend_scsi.h"
#include "storage_backend_iscsi.h"
#include "storage_backend_iscsi.h"
#include "util.h"
#include "util.h"
#include "memory.h"
#include "memory.h"
...
@@ -169,343 +170,33 @@ virStorageBackendISCSIConnection(virConnectPtr conn,
...
@@ -169,343 +170,33 @@ virStorageBackendISCSIConnection(virConnectPtr conn,
return
0
;
return
0
;
}
}
static
int
virStorageBackendISCSINewLun
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
unsigned
int
lun
,
const
char
*
dev
)
{
virStorageVolDefPtr
vol
;
int
fd
=
-
1
;
char
*
devpath
=
NULL
;
int
opentries
=
0
;
if
(
VIR_ALLOC
(
vol
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
vol
->
type
=
VIR_STORAGE_VOL_BLOCK
;
if
(
virAsprintf
(
&
(
vol
->
name
),
"lun-%d"
,
lun
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
if
(
virAsprintf
(
&
devpath
,
"/dev/%s"
,
dev
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
/* It can take a little while between logging into the ISCSI
* server and udev creating the /dev nodes, so if we get ENOENT
* we must retry a few times - they should eventually appear.
* We currently wait for upto 5 seconds. Is this good enough ?
* Perhaps not on a very heavily loaded system Any other
* options... ?
*/
reopen:
if
((
fd
=
open
(
devpath
,
O_RDONLY
))
<
0
)
{
opentries
++
;
if
(
errno
==
ENOENT
&&
opentries
<
50
)
{
usleep
(
100
*
1000
);
goto
reopen
;
}
virReportSystemError
(
conn
,
errno
,
_
(
"cannot open '%s'"
),
devpath
);
goto
cleanup
;
}
/* Now figure out the stable path
*
* XXX this method is O(N) because it scans the pool target
* dir every time its run. Should figure out a more efficient
* way of doing this...
*/
if
((
vol
->
target
.
path
=
virStorageBackendStablePath
(
conn
,
pool
,
devpath
))
==
NULL
)
goto
cleanup
;
VIR_FREE
(
devpath
);
if
(
virStorageBackendUpdateVolTargetInfoFD
(
conn
,
&
vol
->
target
,
fd
,
&
vol
->
allocation
,
&
vol
->
capacity
)
<
0
)
goto
cleanup
;
/* XXX use unique iSCSI id instead */
vol
->
key
=
strdup
(
vol
->
target
.
path
);
if
(
vol
->
key
==
NULL
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
pool
->
def
->
capacity
+=
vol
->
capacity
;
pool
->
def
->
allocation
+=
vol
->
allocation
;
if
(
VIR_REALLOC_N
(
pool
->
volumes
.
objs
,
pool
->
volumes
.
count
+
1
)
<
0
)
{
virReportOOMError
(
conn
);
goto
cleanup
;
}
pool
->
volumes
.
objs
[
pool
->
volumes
.
count
++
]
=
vol
;
close
(
fd
);
return
0
;
cleanup:
if
(
fd
!=
-
1
)
close
(
fd
);
VIR_FREE
(
devpath
);
virStorageVolDefFree
(
vol
);
return
-
1
;
}
static
int
notdotdir
(
const
struct
dirent
*
dir
)
{
return
!
(
STREQLEN
(
dir
->
d_name
,
"."
,
1
)
||
STREQLEN
(
dir
->
d_name
,
".."
,
2
));
}
/* Function to check if the type file in the given sysfs_path is a
* Direct-Access device (i.e. type 0). Return -1 on failure, 0 if not
* a Direct-Access device, and 1 if a Direct-Access device
*/
static
int
directAccessDevice
(
const
char
*
sysfs_path
)
{
char
typestr
[
3
];
char
*
gottype
,
*
p
;
FILE
*
typefile
;
int
type
;
typefile
=
fopen
(
sysfs_path
,
"r"
);
if
(
typefile
==
NULL
)
{
/* there was no type file; that doesn't seem right */
return
-
1
;
}
gottype
=
fgets
(
typestr
,
3
,
typefile
);
fclose
(
typefile
);
if
(
gottype
==
NULL
)
{
/* we couldn't read the type file; have to give up */
return
-
1
;
}
/* we don't actually care about p, but if you pass NULL and the last
* character is not \0, virStrToLong_i complains
*/
if
(
virStrToLong_i
(
typestr
,
&
p
,
10
,
&
type
)
<
0
)
{
/* Hm, type wasn't an integer; seems strange */
return
-
1
;
}
if
(
type
!=
0
)
{
/* saw a device other than Direct-Access */
return
0
;
}
return
1
;
}
static
int
static
int
virStorageBackendISCSIFindLU
N
s
(
virConnectPtr
conn
,
virStorageBackendISCSIFindLUs
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
virStoragePoolObjPtr
pool
,
const
char
*
session
)
const
char
*
session
)
{
{
char
sysfs_path
[
PATH_MAX
];
char
sysfs_path
[
PATH_MAX
];
uint32_t
host
,
bus
,
target
,
lun
;
int
retval
=
0
;
DIR
*
sysdir
;
uint32_t
host
;
struct
dirent
*
sys_dirent
;
struct
dirent
**
namelist
;
int
i
,
n
,
tries
,
retval
,
directaccess
;
char
*
block
,
*
scsidev
,
*
block2
;
retval
=
0
;
block
=
NULL
;
scsidev
=
NULL
;
snprintf
(
sysfs_path
,
PATH_MAX
,
snprintf
(
sysfs_path
,
PATH_MAX
,
"/sys/class/iscsi_session/session%s/device"
,
session
);
"/sys/class/iscsi_session/session%s/device"
,
session
);
sysdir
=
opendir
(
sysfs_path
);
if
(
virStorageBackendSCSIGetHostNumber
(
conn
,
sysfs_path
,
&
host
)
<
0
)
{
if
(
sysdir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir sysfs path '%s'"
),
_
(
"Failed to get host number for iSCSI session "
"with path '%s'"
),
sysfs_path
);
sysfs_path
);
ret
urn
-
1
;
ret
val
=
-
1
;
}
}
while
((
sys_dirent
=
readdir
(
sysdir
)))
{
/* double-negative, so we can use the same function for scandir below */
if
(
!
notdotdir
(
sys_dirent
))
continue
;
if
(
STREQLEN
(
sys_dirent
->
d_name
,
"target"
,
6
))
{
if
(
sscanf
(
sys_dirent
->
d_name
,
"target%u:%u:%u"
,
&
host
,
&
bus
,
&
target
)
!=
3
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to parse target from sysfs path %s/%s"
),
sysfs_path
,
sys_dirent
->
d_name
);
closedir
(
sysdir
);
return
-
1
;
}
break
;
}
}
closedir
(
sysdir
);
/* we now have the host, bus, and target; let's scan for LUNs */
snprintf
(
sysfs_path
,
PATH_MAX
,
"/sys/class/iscsi_session/session%s/device/target%u:%u:%u"
,
session
,
host
,
bus
,
target
);
n
=
scandir
(
sysfs_path
,
&
namelist
,
notdotdir
,
versionsort
);
if
(
virStorageBackendSCSIFindLUs
(
conn
,
pool
,
host
)
<
0
)
{
if
(
n
<=
0
)
{
/* we didn't find any reasonable entries; return failure */
virReportSystemError
(
conn
,
errno
,
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to find any LUNs for session '%s'"
),
_
(
"Failed to find LUs on host %u"
),
host
);
session
);
retval
=
-
1
;
return
-
1
;
}
for
(
i
=
0
;
i
<
n
;
i
++
)
{
block
=
NULL
;
scsidev
=
NULL
;
if
(
sscanf
(
namelist
[
i
]
->
d_name
,
"%u:%u:%u:%u
\n
"
,
&
host
,
&
bus
,
&
target
,
&
lun
)
!=
4
)
continue
;
/* we found a LUN */
/* Note, however, that just finding a LUN doesn't mean it is
* actually useful to us. There are a few different types of
* LUNs, enumerated in the linux kernel in
* drivers/scsi/scsi.c:scsi_device_types[]. Luckily, these device
* types form part of the ABI between the kernel and userland, so
* are unlikely to change. For now, we ignore everything that isn't
* type 0; that is, a Direct-Access device
*/
snprintf
(
sysfs_path
,
PATH_MAX
,
"/sys/bus/scsi/devices/%u:%u:%u:%u/type"
,
host
,
bus
,
target
,
lun
);
directaccess
=
directAccessDevice
(
sysfs_path
);
if
(
directaccess
<
0
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"
),
host
,
bus
,
target
,
lun
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
else
if
(
directaccess
==
0
)
{
/* not a direct-access device; skip */
continue
;
}
/* implicit else if (access == 1); Direct-Access device */
/* It might take some time for the
* /sys/bus/scsi/devices/host:bus:target:lun/block{:sda,/sda}
* link to show up; wait up to 5 seconds for it, then give up
*/
tries
=
0
;
while
(
block
==
NULL
&&
tries
<
50
)
{
snprintf
(
sysfs_path
,
PATH_MAX
,
"/sys/bus/scsi/devices/%u:%u:%u:%u"
,
host
,
bus
,
target
,
lun
);
sysdir
=
opendir
(
sysfs_path
);
if
(
sysdir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir sysfs path '%s'"
),
sysfs_path
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
while
((
sys_dirent
=
readdir
(
sysdir
)))
{
if
(
!
notdotdir
(
sys_dirent
))
continue
;
if
(
STREQLEN
(
sys_dirent
->
d_name
,
"block"
,
5
))
{
block
=
strdup
(
sys_dirent
->
d_name
);
break
;
}
}
closedir
(
sysdir
);
tries
++
;
if
(
block
==
NULL
)
usleep
(
100
*
1000
);
}
if
(
block
==
NULL
)
{
/* we couldn't find the device link for this device; fail */
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to find device link for lun %d"
),
lun
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
if
(
strlen
(
block
)
==
5
)
{
/* OK, this is exactly "block"; must be new-style */
snprintf
(
sysfs_path
,
PATH_MAX
,
"/sys/bus/scsi/devices/%u:%u:%u:%u/block"
,
host
,
bus
,
target
,
lun
);
sysdir
=
opendir
(
sysfs_path
);
if
(
sysdir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir sysfs path '%s'"
),
sysfs_path
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
while
((
sys_dirent
=
readdir
(
sysdir
)))
{
if
(
!
notdotdir
(
sys_dirent
))
continue
;
scsidev
=
strdup
(
sys_dirent
->
d_name
);
break
;
}
closedir
(
sysdir
);
}
else
{
/* old-style; just parse out the sd */
block2
=
strrchr
(
block
,
':'
);
if
(
block2
==
NULL
)
{
/* Hm, wasn't what we were expecting; have to give up */
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to parse block path %s"
),
block
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
block2
++
;
scsidev
=
strdup
(
block2
);
}
if
(
scsidev
==
NULL
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
namelist_cleanup
;
}
retval
=
virStorageBackendISCSINewLun
(
conn
,
pool
,
lun
,
scsidev
);
if
(
retval
<
0
)
break
;
VIR_FREE
(
scsidev
);
VIR_FREE
(
block
);
}
}
namelist_cleanup:
/* we call these VIR_FREE here to make sure we don't leak memory on
* error cases; in the success case, these are already freed but NULL,
* which should be fine
*/
VIR_FREE
(
scsidev
);
VIR_FREE
(
block
);
for
(
i
=
0
;
i
<
n
;
i
++
)
VIR_FREE
(
namelist
[
i
]);
VIR_FREE
(
namelist
);
return
retval
;
return
retval
;
}
}
...
@@ -615,13 +306,11 @@ virStorageBackendISCSIRefreshPool(virConnectPtr conn,
...
@@ -615,13 +306,11 @@ virStorageBackendISCSIRefreshPool(virConnectPtr conn,
pool
->
def
->
allocation
=
pool
->
def
->
capacity
=
pool
->
def
->
available
=
0
;
pool
->
def
->
allocation
=
pool
->
def
->
capacity
=
pool
->
def
->
available
=
0
;
virStorageBackendWaitForDevices
(
conn
);
if
((
session
=
virStorageBackendISCSISession
(
conn
,
pool
,
0
))
==
NULL
)
if
((
session
=
virStorageBackendISCSISession
(
conn
,
pool
,
0
))
==
NULL
)
goto
cleanup
;
goto
cleanup
;
if
(
virStorageBackendISCSIRescanLUNs
(
conn
,
pool
,
session
)
<
0
)
if
(
virStorageBackendISCSIRescanLUNs
(
conn
,
pool
,
session
)
<
0
)
goto
cleanup
;
goto
cleanup
;
if
(
virStorageBackendISCSIFindLU
N
s
(
conn
,
pool
,
session
)
<
0
)
if
(
virStorageBackendISCSIFindLUs
(
conn
,
pool
,
session
)
<
0
)
goto
cleanup
;
goto
cleanup
;
VIR_FREE
(
session
);
VIR_FREE
(
session
);
...
...
src/storage_backend_scsi.c
0 → 100644
浏览文件 @
55ae53d9
/*
* storage_backend_scsi.c: storage backend for SCSI handling
*
* Copyright (C) 2007-2008 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange redhat com>
*/
#include <config.h>
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <fcntl.h>
#include "virterror_internal.h"
#include "storage_backend_scsi.h"
#include "memory.h"
#include "logging.h"
#define VIR_FROM_THIS VIR_FROM_STORAGE
/* Function to check if the type file in the given sysfs_path is a
* Direct-Access device (i.e. type 0). Return -1 on failure, type of
* the device otherwise.
*/
static
int
getDeviceType
(
virConnectPtr
conn
,
uint32_t
host
,
uint32_t
bus
,
uint32_t
target
,
uint32_t
lun
,
int
*
type
)
{
char
*
type_path
=
NULL
;
char
typestr
[
3
];
char
*
gottype
,
*
p
;
FILE
*
typefile
;
int
retval
=
0
;
if
(
virAsprintf
(
&
type_path
,
"/sys/bus/scsi/devices/%u:%u:%u:%u/type"
,
host
,
bus
,
target
,
lun
)
<
0
)
{
virReportOOMError
(
conn
);
goto
out
;
}
typefile
=
fopen
(
type_path
,
"r"
);
if
(
typefile
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Could not find typefile '%s'"
),
type_path
);
/* there was no type file; that doesn't seem right */
retval
=
-
1
;
goto
out
;
}
gottype
=
fgets
(
typestr
,
3
,
typefile
);
fclose
(
typefile
);
if
(
gottype
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Could not read typefile '%s'"
),
type_path
);
/* we couldn't read the type file; have to give up */
retval
=
-
1
;
goto
out
;
}
/* we don't actually care about p, but if you pass NULL and the last
* character is not \0, virStrToLong_i complains
*/
if
(
virStrToLong_i
(
typestr
,
&
p
,
10
,
type
)
<
0
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Device type '%s' is not an integer"
),
typestr
);
/* Hm, type wasn't an integer; seems strange */
retval
=
-
1
;
goto
out
;
}
VIR_DEBUG
(
_
(
"Device type is %d"
),
*
type
);
out:
VIR_FREE
(
type_path
);
return
retval
;
}
static
int
virStorageBackendSCSINewLun
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
uint32_t
host
,
uint32_t
bus
,
uint32_t
target
,
uint32_t
lun
,
const
char
*
dev
)
{
virStorageVolDefPtr
vol
;
char
*
devpath
=
NULL
;
int
retval
=
0
;
if
(
VIR_ALLOC
(
vol
)
<
0
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
out
;
}
vol
->
type
=
VIR_STORAGE_VOL_BLOCK
;
if
(
virAsprintf
(
&
(
vol
->
name
),
"%u.%u.%u.%u"
,
host
,
bus
,
target
,
lun
)
<
0
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
free_vol
;
}
if
(
virAsprintf
(
&
devpath
,
"/dev/%s"
,
dev
)
<
0
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
free_vol
;
}
VIR_DEBUG
(
_
(
"Trying to create volume for '%s'"
),
devpath
);
/* Now figure out the stable path
*
* XXX this method is O(N) because it scans the pool target
* dir every time its run. Should figure out a more efficient
* way of doing this...
*/
if
((
vol
->
target
.
path
=
virStorageBackendStablePath
(
conn
,
pool
,
devpath
))
==
NULL
)
{
retval
=
-
1
;
goto
free_vol
;
}
if
(
STREQLEN
(
devpath
,
vol
->
target
.
path
,
PATH_MAX
)
&&
!
(
STREQ
(
pool
->
def
->
target
.
path
,
"/dev"
)
||
STREQ
(
pool
->
def
->
target
.
path
,
"/dev/"
)))
{
VIR_DEBUG
(
_
(
"No stable path found for '%s' in '%s'"
),
devpath
,
pool
->
def
->
target
.
path
);
retval
=
-
1
;
goto
free_vol
;
}
if
(
virStorageBackendUpdateVolTargetInfo
(
conn
,
&
vol
->
target
,
&
vol
->
allocation
,
&
vol
->
capacity
)
<
0
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to update volume for '%s'"
),
devpath
);
retval
=
-
1
;
goto
free_vol
;
}
/* XXX should use logical unit's UUID instead */
vol
->
key
=
strdup
(
vol
->
target
.
path
);
if
(
vol
->
key
==
NULL
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
free_vol
;
}
pool
->
def
->
capacity
+=
vol
->
capacity
;
pool
->
def
->
allocation
+=
vol
->
allocation
;
if
(
VIR_REALLOC_N
(
pool
->
volumes
.
objs
,
pool
->
volumes
.
count
+
1
)
<
0
)
{
virReportOOMError
(
conn
);
retval
=
-
1
;
goto
free_vol
;
}
pool
->
volumes
.
objs
[
pool
->
volumes
.
count
++
]
=
vol
;
goto
out
;
free_vol:
virStorageVolDefFree
(
vol
);
out:
VIR_FREE
(
devpath
);
return
retval
;
}
static
int
getNewStyleBlockDevice
(
virConnectPtr
conn
,
const
char
*
lun_path
,
const
char
*
block_name
ATTRIBUTE_UNUSED
,
char
**
block_device
)
{
char
*
block_path
=
NULL
;
DIR
*
block_dir
=
NULL
;
struct
dirent
*
block_dirent
=
NULL
;
int
retval
=
0
;
if
(
virAsprintf
(
&
block_path
,
"%s/block"
,
lun_path
)
<
0
)
{
virReportOOMError
(
conn
);
goto
out
;
}
VIR_DEBUG
(
_
(
"Looking for block device in '%s'"
),
block_path
);
block_dir
=
opendir
(
block_path
);
if
(
block_dir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir sysfs path '%s'"
),
block_path
);
retval
=
-
1
;
goto
out
;
}
while
((
block_dirent
=
readdir
(
block_dir
)))
{
if
(
STREQLEN
(
block_dirent
->
d_name
,
"."
,
1
))
{
continue
;
}
*
block_device
=
strdup
(
block_dirent
->
d_name
);
VIR_DEBUG
(
_
(
"Block device is '%s'"
),
*
block_device
);
break
;
}
closedir
(
block_dir
);
out:
VIR_FREE
(
block_path
);
return
retval
;
}
static
int
getOldStyleBlockDevice
(
virConnectPtr
conn
,
const
char
*
lun_path
ATTRIBUTE_UNUSED
,
const
char
*
block_name
,
char
**
block_device
)
{
char
*
blockp
=
NULL
;
int
retval
=
0
;
/* old-style; just parse out the sd */
blockp
=
strrchr
(
block_name
,
':'
);
if
(
blockp
==
NULL
)
{
/* Hm, wasn't what we were expecting; have to give up */
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to parse block name %s"
),
block_name
);
retval
=
-
1
;
}
else
{
blockp
++
;
*
block_device
=
strdup
(
blockp
);
VIR_DEBUG
(
_
(
"Block device is '%s'"
),
*
block_device
);
}
return
retval
;
}
static
int
getBlockDevice
(
virConnectPtr
conn
,
uint32_t
host
,
uint32_t
bus
,
uint32_t
target
,
uint32_t
lun
,
char
**
block_device
)
{
char
*
lun_path
=
NULL
;
DIR
*
lun_dir
=
NULL
;
struct
dirent
*
lun_dirent
=
NULL
;
int
retval
=
0
;
if
(
virAsprintf
(
&
lun_path
,
"/sys/bus/scsi/devices/%u:%u:%u:%u"
,
host
,
bus
,
target
,
lun
)
<
0
)
{
virReportOOMError
(
conn
);
goto
out
;
}
lun_dir
=
opendir
(
lun_path
);
if
(
lun_dir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir sysfs path '%s'"
),
lun_path
);
retval
=
-
1
;
goto
out
;
}
while
((
lun_dirent
=
readdir
(
lun_dir
)))
{
if
(
STREQLEN
(
lun_dirent
->
d_name
,
"block"
,
5
))
{
if
(
strlen
(
lun_dirent
->
d_name
)
==
5
)
{
retval
=
getNewStyleBlockDevice
(
conn
,
lun_path
,
lun_dirent
->
d_name
,
block_device
);
}
else
{
retval
=
getOldStyleBlockDevice
(
conn
,
lun_path
,
lun_dirent
->
d_name
,
block_device
);
}
break
;
}
}
closedir
(
lun_dir
);
out:
VIR_FREE
(
lun_path
);
return
retval
;
}
static
int
processLU
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
uint32_t
host
,
uint32_t
bus
,
uint32_t
target
,
uint32_t
lun
)
{
char
*
type_path
=
NULL
;
int
retval
=
0
;
int
device_type
;
char
*
block_device
=
NULL
;
VIR_DEBUG
(
_
(
"Processing LU %u:%u:%u:%u"
),
host
,
bus
,
target
,
lun
);
if
(
getDeviceType
(
conn
,
host
,
bus
,
target
,
lun
,
&
device_type
)
<
0
)
{
virStorageReportError
(
conn
,
VIR_ERR_INTERNAL_ERROR
,
_
(
"Failed to determine if %u:%u:%u:%u is a Direct-Access LUN"
),
host
,
bus
,
target
,
lun
);
retval
=
-
1
;
goto
out
;
}
/* We don't create volumes for devices other than disk and cdrom
* devices, but finding a device that isn't one of those types
* isn't an error, either. */
if
(
!
(
device_type
==
VIR_STORAGE_DEVICE_TYPE_DISK
||
device_type
==
VIR_STORAGE_DEVICE_TYPE_ROM
))
{
retval
=
0
;
goto
out
;
}
VIR_DEBUG
(
_
(
"%u:%u:%u:%u is a Direct-Access LUN"
),
host
,
bus
,
target
,
lun
);
if
(
getBlockDevice
(
conn
,
host
,
bus
,
target
,
lun
,
&
block_device
)
<
0
)
{
goto
out
;
}
if
(
virStorageBackendSCSINewLun
(
conn
,
pool
,
host
,
bus
,
target
,
lun
,
block_device
)
<
0
)
{
VIR_DEBUG
(
_
(
"Failed to create new storage volume for %u:%u:%u:%u"
),
host
,
bus
,
target
,
lun
);
retval
=
-
1
;
goto
out
;
}
VIR_DEBUG
(
_
(
"Created new storage volume for %u:%u:%u:%u successfully"
),
host
,
bus
,
target
,
lun
);
VIR_FREE
(
type_path
);
out:
return
retval
;
}
int
virStorageBackendSCSIFindLUs
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
uint32_t
scanhost
)
{
int
retval
=
0
;
uint32_t
bus
,
target
,
lun
;
char
*
device_path
=
NULL
;
DIR
*
devicedir
=
NULL
;
struct
dirent
*
lun_dirent
=
NULL
;
char
devicepattern
[
64
];
VIR_DEBUG
(
_
(
"Discovering LUs on host %u"
),
scanhost
);
virStorageBackendWaitForDevices
(
conn
);
if
(
virAsprintf
(
&
device_path
,
"/sys/bus/scsi/devices"
)
<
0
)
{
virReportOOMError
(
conn
);
goto
out
;
}
devicedir
=
opendir
(
device_path
);
if
(
devicedir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir path '%s'"
),
device_path
);
retval
=
-
1
;
goto
out
;
}
snprintf
(
devicepattern
,
sizeof
(
devicepattern
),
"%u:%%u:%%u:%%u
\n
"
,
scanhost
);
while
((
lun_dirent
=
readdir
(
devicedir
)))
{
if
(
sscanf
(
lun_dirent
->
d_name
,
devicepattern
,
&
bus
,
&
target
,
&
lun
)
!=
3
)
{
continue
;
}
VIR_DEBUG
(
_
(
"Found LU '%s'"
),
lun_dirent
->
d_name
);
processLU
(
conn
,
pool
,
scanhost
,
bus
,
target
,
lun
);
}
closedir
(
devicedir
);
out:
VIR_FREE
(
device_path
);
return
retval
;
}
int
virStorageBackendSCSIGetHostNumber
(
virConnectPtr
conn
,
const
char
*
sysfs_path
,
uint32_t
*
host
)
{
int
retval
=
0
;
DIR
*
sysdir
=
NULL
;
struct
dirent
*
dirent
=
NULL
;
VIR_DEBUG
(
_
(
"Finding host number from '%s'"
),
sysfs_path
);
virStorageBackendWaitForDevices
(
conn
);
sysdir
=
opendir
(
sysfs_path
);
if
(
sysdir
==
NULL
)
{
virReportSystemError
(
conn
,
errno
,
_
(
"Failed to opendir path '%s'"
),
sysfs_path
);
retval
=
-
1
;
goto
out
;
}
while
((
dirent
=
readdir
(
sysdir
)))
{
if
(
STREQLEN
(
dirent
->
d_name
,
"target"
,
strlen
(
"target"
)))
{
if
(
sscanf
(
dirent
->
d_name
,
"target%u:"
,
host
)
!=
1
)
{
VIR_DEBUG
(
_
(
"Failed to parse target '%s'"
),
dirent
->
d_name
);
retval
=
-
1
;
break
;
}
}
}
closedir
(
sysdir
);
out:
return
retval
;
}
static
int
virStorageBackendSCSIRefreshPool
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
)
{
int
retval
=
0
;
uint32_t
host
;
pool
->
def
->
allocation
=
pool
->
def
->
capacity
=
pool
->
def
->
available
=
0
;
if
(
sscanf
(
pool
->
def
->
source
.
adapter
,
"host%u"
,
&
host
)
!=
1
)
{
VIR_DEBUG
(
_
(
"Failed to get host number from '%s'"
),
pool
->
def
->
source
.
adapter
);
retval
=
-
1
;
goto
out
;
}
VIR_DEBUG
(
_
(
"Scanning host%u"
),
host
);
virStorageBackendSCSIFindLUs
(
conn
,
pool
,
host
);
out:
return
retval
;
}
virStorageBackend
virStorageBackendSCSI
=
{
.
type
=
VIR_STORAGE_POOL_SCSI
,
.
refreshPool
=
virStorageBackendSCSIRefreshPool
,
};
src/storage_backend_scsi.h
0 → 100644
浏览文件 @
55ae53d9
/*
* storage_backend_scsi.h: storage backend for SCSI handling
*
* Copyright (C) 2007-2008 Red Hat, Inc.
* Copyright (C) 2007-2008 Daniel P. Berrange
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* Author: Daniel P. Berrange <berrange redhat com>
*/
#ifndef __VIR_STORAGE_BACKEND_SCSI_H__
#define __VIR_STORAGE_BACKEND_SCSI_H__
#include "storage_backend.h"
#define LINUX_SYSFS_SCSI_HOST_PREFIX "/sys/class/scsi_host"
#define LINUX_SYSFS_SCSI_HOST_POSTFIX "device"
extern
virStorageBackend
virStorageBackendSCSI
;
int
virStorageBackendSCSIGetHostNumber
(
virConnectPtr
conn
,
const
char
*
sysfs_path
,
uint32_t
*
host
);
int
virStorageBackendSCSIFindLUs
(
virConnectPtr
conn
,
virStoragePoolObjPtr
pool
,
uint32_t
scanhost
);
#endif
/* __VIR_STORAGE_BACKEND_SCSI_H__ */
src/storage_conf.c
浏览文件 @
55ae53d9
...
@@ -187,6 +187,14 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
...
@@ -187,6 +187,14 @@ static virStoragePoolTypeInfo poolTypeInfo[] = {
.
formatToString
=
virStoragePoolFormatDiskTypeToString
,
.
formatToString
=
virStoragePoolFormatDiskTypeToString
,
}
}
},
},
{
.
poolType
=
VIR_STORAGE_POOL_SCSI
,
.
poolOptions
=
{
.
flags
=
(
VIR_STORAGE_POOL_SOURCE_ADAPTER
),
},
.
volOptions
=
{
.
formatToString
=
virStoragePoolFormatDiskTypeToString
,
}
},
{
.
poolType
=
VIR_STORAGE_POOL_DISK
,
{
.
poolType
=
VIR_STORAGE_POOL_DISK
,
.
poolOptions
=
{
.
poolOptions
=
{
.
flags
=
(
VIR_STORAGE_POOL_SOURCE_DEVICE
),
.
flags
=
(
VIR_STORAGE_POOL_SOURCE_DEVICE
),
...
@@ -269,6 +277,7 @@ virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
...
@@ -269,6 +277,7 @@ virStoragePoolSourceFree(virStoragePoolSourcePtr source) {
VIR_FREE
(
source
->
devices
);
VIR_FREE
(
source
->
devices
);
VIR_FREE
(
source
->
dir
);
VIR_FREE
(
source
->
dir
);
VIR_FREE
(
source
->
name
);
VIR_FREE
(
source
->
name
);
VIR_FREE
(
source
->
adapter
);
if
(
source
->
authType
==
VIR_STORAGE_POOL_AUTH_CHAP
)
{
if
(
source
->
authType
==
VIR_STORAGE_POOL_AUTH_CHAP
)
{
VIR_FREE
(
source
->
auth
.
chap
.
login
);
VIR_FREE
(
source
->
auth
.
chap
.
login
);
...
@@ -573,6 +582,15 @@ virStoragePoolDefParseDoc(virConnectPtr conn,
...
@@ -573,6 +582,15 @@ virStoragePoolDefParseDoc(virConnectPtr conn,
}
}
}
}
if
(
options
->
flags
&
VIR_STORAGE_POOL_SOURCE_ADAPTER
)
{
if
((
ret
->
source
.
adapter
=
virXPathString
(
conn
,
"string(/pool/source/adapter/@name)"
,
ctxt
))
==
NULL
)
{
virStorageReportError
(
conn
,
VIR_ERR_XML_ERROR
,
"%s"
,
_
(
"missing storage pool source adapter name"
));
goto
cleanup
;
}
}
authType
=
virXPathString
(
conn
,
"string(/pool/source/auth/@type)"
,
ctxt
);
authType
=
virXPathString
(
conn
,
"string(/pool/source/auth/@type)"
,
ctxt
);
if
(
authType
==
NULL
)
{
if
(
authType
==
NULL
)
{
...
...
src/storage_conf.h
浏览文件 @
55ae53d9
...
@@ -117,6 +117,13 @@ enum virStoragePoolType {
...
@@ -117,6 +117,13 @@ enum virStoragePoolType {
VIR_ENUM_DECL
(
virStoragePool
)
VIR_ENUM_DECL
(
virStoragePool
)
enum
virStoragePoolDeviceType
{
VIR_STORAGE_DEVICE_TYPE_DISK
=
0x00
,
VIR_STORAGE_DEVICE_TYPE_ROM
=
0x05
,
VIR_STORAGE_DEVICE_TYPE_LAST
,
};
enum
virStoragePoolAuthType
{
enum
virStoragePoolAuthType
{
VIR_STORAGE_POOL_AUTH_NONE
,
VIR_STORAGE_POOL_AUTH_NONE
,
...
...
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录