1 /* $NetBSD: fs.c,v 1.3 2009/02/18 12:16:13 haad Exp $ */
4 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
5 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
7 * This file is part of LVM2.
9 * This copyrighted material is made available to anyone wishing to use,
10 * modify, copy, or redistribute it subject to the terms and conditions
11 * of the GNU Lesser General Public License v.2.1.
13 * You should have received a copy of the GNU Lesser General Public License
14 * along with this program; if not, write to the Free Software Foundation,
15 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include "toolcontext.h"
21 #include "lvm-string.h"
31 static int _mk_dir(const char *dev_dir
, const char *vg_name
)
33 char vg_path
[PATH_MAX
];
36 if (dm_snprintf(vg_path
, sizeof(vg_path
), "%s%s",
37 dev_dir
, vg_name
) == -1) {
38 log_error("Couldn't construct name of volume "
43 if (dir_exists(vg_path
))
46 log_very_verbose("Creating directory %s", vg_path
);
48 old_umask
= umask(DM_DEV_DIR_UMASK
);
49 if (mkdir(vg_path
, 0777)) {
50 log_sys_error("mkdir", vg_path
);
59 static int _rm_dir(const char *dev_dir
, const char *vg_name
)
61 char vg_path
[PATH_MAX
];
63 if (dm_snprintf(vg_path
, sizeof(vg_path
), "%s%s",
64 dev_dir
, vg_name
) == -1) {
65 log_error("Couldn't construct name of volume "
70 if (dir_exists(vg_path
) && is_empty_dir(vg_path
)) {
71 log_very_verbose("Removing directory %s", vg_path
);
78 static void _rm_blks(const char *dir
)
82 struct dirent
*dirent
;
86 if (!(d
= opendir(dir
))) {
87 log_sys_error("opendir", dir
);
91 while ((dirent
= readdir(d
))) {
92 name
= dirent
->d_name
;
94 if (!strcmp(name
, ".") || !strcmp(name
, ".."))
97 if (dm_snprintf(path
, sizeof(path
), "%s/%s", dir
, name
) == -1) {
98 log_error("Couldn't create path for %s", name
);
102 if (!lstat(path
, &buf
)) {
103 if (!S_ISBLK(buf
.st_mode
))
105 log_very_verbose("Removing %s", path
);
106 if (unlink(path
) < 0)
107 log_sys_error("unlink", path
);
110 if (dm_snprintf(path
, sizeof(path
), "%s/r%s", dir
, name
) == -1) {
111 log_error("Couldn't create path for r%s", name
);
115 if (!lstat(path
, &buf
)) {
116 if (!S_ISCHR(buf
.st_mode
))
118 log_very_verbose("Removing %s", path
);
119 if (unlink(path
) < 0)
120 log_sys_error("unlink", path
);
126 static int _mk_link(const char *dev_dir
, const char *vg_name
,
127 const char *lv_name
, const char *dev
)
129 char lv_path
[PATH_MAX
], link_path
[PATH_MAX
], lvm1_group_path
[PATH_MAX
];
130 char vg_path
[PATH_MAX
];
131 struct stat buf
, buf_lp
;
134 /* Add support for creating links to BSD raw devices */
135 char raw_lv_path
[PATH_MAX
], raw_link_path
[PATH_MAX
];
138 if (dm_snprintf(vg_path
, sizeof(vg_path
), "%s%s",
139 dev_dir
, vg_name
) == -1) {
140 log_error("Couldn't create path for volume group dir %s",
146 if (dm_snprintf(raw_lv_path
, sizeof(raw_lv_path
), "%s/r%s", vg_path
,
148 log_error("Couldn't create source pathname for "
149 "logical volume link r%s", lv_name
);
153 if (dm_snprintf(raw_link_path
, sizeof(raw_link_path
), "%s/r%s",
154 dm_dir(), dev
) == -1) {
155 log_error("Couldn't create destination pathname for "
156 "logical volume link for %s", lv_name
);
160 if (!lstat(raw_lv_path
, &buf
)) {
161 if (!S_ISLNK(buf
.st_mode
) && !S_ISCHR(buf
.st_mode
)) {
162 log_error("Symbolic link %s not created: file exists",
167 log_very_verbose("Removing %s", raw_lv_path
);
168 if (unlink(raw_lv_path
) < 0) {
169 log_sys_error("unlink", raw_lv_path
);
174 log_very_verbose("Linking %s -> %s", raw_lv_path
, raw_link_path
);
175 if (symlink(raw_link_path
, raw_lv_path
) < 0) {
176 log_sys_error("symlink", raw_lv_path
);
181 if (dm_snprintf(lv_path
, sizeof(lv_path
), "%s/%s", vg_path
,
183 log_error("Couldn't create source pathname for "
184 "logical volume link %s", lv_name
);
188 if (dm_snprintf(link_path
, sizeof(link_path
), "%s/%s",
189 dm_dir(), dev
) == -1) {
190 log_error("Couldn't create destination pathname for "
191 "logical volume link for %s", lv_name
);
195 if (dm_snprintf(lvm1_group_path
, sizeof(lvm1_group_path
), "%s/group",
197 log_error("Couldn't create pathname for LVM1 group file for %s",
202 /* To reach this point, the VG must have been locked.
203 * As locking fails if the VG is active under LVM1, it's
204 * now safe to remove any LVM1 devices we find here
205 * (as well as any existing LVM2 symlink). */
206 if (!lstat(lvm1_group_path
, &buf
)) {
207 if (!S_ISCHR(buf
.st_mode
)) {
208 log_error("Non-LVM1 character device found at %s",
213 log_very_verbose("Removing %s", lvm1_group_path
);
214 if (unlink(lvm1_group_path
) < 0)
215 log_sys_error("unlink", lvm1_group_path
);
219 if (!lstat(lv_path
, &buf
)) {
220 if (!S_ISLNK(buf
.st_mode
) && !S_ISBLK(buf
.st_mode
)) {
221 log_error("Symbolic link %s not created: file exists",
226 if (dm_udev_get_sync_support()) {
227 /* Check udev created the correct link. */
228 if (!stat(link_path
, &buf_lp
) &&
229 !stat(lv_path
, &buf
)) {
230 if (buf_lp
.st_rdev
== buf
.st_rdev
)
233 log_warn("Symlink %s that should have been "
234 "created by udev does not have "
235 "correct target. Falling back to "
236 "direct link creation", lv_path
);
238 log_warn("Symlink %s that should have been "
239 "created by udev could not be checked "
240 "for its correctness. Falling back to "
241 "direct link creation.", lv_path
);
245 log_very_verbose("Removing %s", lv_path
);
246 if (unlink(lv_path
) < 0) {
247 log_sys_error("unlink", lv_path
);
250 } else if (dm_udev_get_sync_support())
251 log_warn("The link %s should had been created by udev "
252 "but it was not found. Falling back to "
253 "direct link creation.", lv_path
);
255 log_very_verbose("Linking %s -> %s", lv_path
, link_path
);
256 if (symlink(link_path
, lv_path
) < 0) {
257 log_sys_error("symlink", lv_path
);
261 if (!dm_set_selinux_context(lv_path
, S_IFLNK
))
267 static int _rm_link(const char *dev_dir
, const char *vg_name
,
271 char lv_path
[PATH_MAX
];
274 /* Add support for removing links to BSD raw devices */
275 char raw_lv_path
[PATH_MAX
];
277 if (dm_snprintf(raw_lv_path
, sizeof(raw_lv_path
), "%s%s/r%s",
278 dev_dir
, vg_name
, lv_name
) == -1) {
279 log_error("Couldn't determine link pathname.");
283 if (lstat(raw_lv_path
, &buf
) || !S_ISLNK(buf
.st_mode
)) {
286 log_error("%s not symbolic link - not removing", raw_lv_path
);
290 log_very_verbose("Removing link %s", raw_lv_path
);
291 if (unlink(raw_lv_path
) < 0) {
292 log_sys_error("unlink", raw_lv_path
);
296 if (dm_snprintf(lv_path
, sizeof(lv_path
), "%s%s/%s",
297 dev_dir
, vg_name
, lv_name
) == -1) {
298 log_error("Couldn't determine link pathname.");
302 if (lstat(lv_path
, &buf
) && errno
== ENOENT
)
304 else if (dm_udev_get_sync_support())
305 log_warn("The link %s should have been removed by udev "
306 "but it is still present. Falling back to "
307 "direct link removal.", lv_path
);
309 if (!S_ISLNK(buf
.st_mode
)) {
310 log_error("%s not symbolic link - not removing", lv_path
);
314 log_very_verbose("Removing link %s", lv_path
);
315 if (unlink(lv_path
) < 0) {
316 log_sys_error("unlink", lv_path
);
329 static int _do_fs_op(fs_op_t type
, const char *dev_dir
, const char *vg_name
,
330 const char *lv_name
, const char *dev
,
331 const char *old_lv_name
)
335 if (!_mk_dir(dev_dir
, vg_name
) ||
336 !_mk_link(dev_dir
, vg_name
, lv_name
, dev
))
340 if (!_rm_link(dev_dir
, vg_name
, lv_name
) ||
341 !_rm_dir(dev_dir
, vg_name
))
344 /* FIXME Use rename() */
346 if (old_lv_name
&& !_rm_link(dev_dir
, vg_name
, old_lv_name
))
349 if (!_mk_link(dev_dir
, vg_name
, lv_name
, dev
))
356 static DM_LIST_INIT(_fs_ops
);
369 static void _store_str(char **pos
, char **ptr
, const char *str
)
373 *pos
+= strlen(*ptr
) + 1;
376 static int _stack_fs_op(fs_op_t type
, const char *dev_dir
, const char *vg_name
,
377 const char *lv_name
, const char *dev
,
378 const char *old_lv_name
)
380 struct fs_op_parms
*fsp
;
381 size_t len
= strlen(dev_dir
) + strlen(vg_name
) + strlen(lv_name
) +
382 strlen(dev
) + strlen(old_lv_name
) + 5;
385 if (!(fsp
= dm_malloc(sizeof(*fsp
) + len
))) {
386 log_error("No space to stack fs operation");
393 _store_str(&pos
, &fsp
->dev_dir
, dev_dir
);
394 _store_str(&pos
, &fsp
->vg_name
, vg_name
);
395 _store_str(&pos
, &fsp
->lv_name
, lv_name
);
396 _store_str(&pos
, &fsp
->dev
, dev
);
397 _store_str(&pos
, &fsp
->old_lv_name
, old_lv_name
);
399 dm_list_add(&_fs_ops
, &fsp
->list
);
404 static void _pop_fs_ops(void)
406 struct dm_list
*fsph
, *fspht
;
407 struct fs_op_parms
*fsp
;
409 dm_list_iterate_safe(fsph
, fspht
, &_fs_ops
) {
410 fsp
= dm_list_item(fsph
, struct fs_op_parms
);
411 _do_fs_op(fsp
->type
, fsp
->dev_dir
, fsp
->vg_name
, fsp
->lv_name
,
412 fsp
->dev
, fsp
->old_lv_name
);
413 dm_list_del(&fsp
->list
);
418 static int _fs_op(fs_op_t type
, const char *dev_dir
, const char *vg_name
,
419 const char *lv_name
, const char *dev
, const char *old_lv_name
)
422 if (!_stack_fs_op(type
, dev_dir
, vg_name
, lv_name
, dev
,
428 return _do_fs_op(type
, dev_dir
, vg_name
, lv_name
, dev
, old_lv_name
);
431 int fs_add_lv(const struct logical_volume
*lv
, const char *dev
)
433 return _fs_op(FS_ADD
, lv
->vg
->cmd
->dev_dir
, lv
->vg
->name
, lv
->name
,
437 int fs_del_lv(const struct logical_volume
*lv
)
439 return _fs_op(FS_DEL
, lv
->vg
->cmd
->dev_dir
, lv
->vg
->name
, lv
->name
,
443 int fs_del_lv_byname(const char *dev_dir
, const char *vg_name
, const char *lv_name
)
445 return _fs_op(FS_DEL
, dev_dir
, vg_name
, lv_name
, "", "");
448 int fs_rename_lv(struct logical_volume
*lv
, const char *dev
,
449 const char *old_vgname
, const char *old_lvname
)
451 if (strcmp(old_vgname
, lv
->vg
->name
)) {
453 (_fs_op(FS_DEL
, lv
->vg
->cmd
->dev_dir
, old_vgname
, old_lvname
, "", "") &&
454 _fs_op(FS_ADD
, lv
->vg
->cmd
->dev_dir
, lv
->vg
->name
, lv
->name
, dev
, ""));
457 return _fs_op(FS_RENAME
, lv
->vg
->cmd
->dev_dir
, lv
->vg
->name
, lv
->name
,