2 * Copyright (C) 2001-2004 Sistina Software, Inc. All rights reserved.
3 * Copyright (C) 2004-2007 Red Hat, Inc. All rights reserved.
5 * This file is part of LVM2.
7 * This copyrighted material is made available to anyone wishing to use,
8 * modify, copy, or redistribute it subject to the terms and conditions
9 * of the GNU Lesser General Public License v.2.1.
11 * You should have received a copy of the GNU Lesser General Public License
12 * along with this program; if not, write to the Free Software Foundation,
13 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 #include "toolcontext.h"
19 #include "lvm-string.h"
29 static int _mk_dir(const char *dev_dir, const char *vg_name)
31 char vg_path[PATH_MAX];
34 if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
35 dev_dir, vg_name) == -1) {
36 log_error("Couldn't construct name of volume "
41 if (dir_exists(vg_path))
44 log_very_verbose("Creating directory %s", vg_path);
46 (void) dm_prepare_selinux_context(vg_path, S_IFDIR);
47 old_umask = umask(DM_DEV_DIR_UMASK);
48 if (mkdir(vg_path, 0777)) {
49 log_sys_error("mkdir", vg_path);
51 (void) dm_prepare_selinux_context(NULL, 0);
55 (void) dm_prepare_selinux_context(NULL, 0);
60 static int _rm_dir(const char *dev_dir, const char *vg_name)
62 char vg_path[PATH_MAX];
64 if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
65 dev_dir, vg_name) == -1) {
66 log_error("Couldn't construct name of volume "
71 if (dir_exists(vg_path) && is_empty_dir(vg_path)) {
72 log_very_verbose("Removing directory %s", vg_path);
79 static void _rm_blks(const char *dir)
83 struct dirent *dirent;
87 if (!(d = opendir(dir))) {
88 log_sys_error("opendir", dir);
92 while ((dirent = readdir(d))) {
93 name = dirent->d_name;
95 if (!strcmp(name, ".") || !strcmp(name, ".."))
98 if (dm_snprintf(path, sizeof(path), "%s/%s", dir, name) == -1) {
99 log_error("Couldn't create path for %s", name);
103 if (!lstat(path, &buf)) {
104 if (!S_ISBLK(buf.st_mode))
106 log_very_verbose("Removing %s", path);
107 if (unlink(path) < 0)
108 log_sys_error("unlink", path);
113 log_sys_error("closedir", dir);
116 static int _mk_link(const char *dev_dir, const char *vg_name,
117 const char *lv_name, const char *dev, int check_udev)
119 char lv_path[PATH_MAX], link_path[PATH_MAX], lvm1_group_path[PATH_MAX];
120 char vg_path[PATH_MAX];
121 struct stat buf, buf_lp;
123 if (dm_snprintf(vg_path, sizeof(vg_path), "%s%s",
124 dev_dir, vg_name) == -1) {
125 log_error("Couldn't create path for volume group dir %s",
130 if (dm_snprintf(lv_path, sizeof(lv_path), "%s/%s", vg_path,
132 log_error("Couldn't create source pathname for "
133 "logical volume link %s", lv_name);
137 if (dm_snprintf(link_path, sizeof(link_path), "%s/%s",
138 dm_dir(), dev) == -1) {
139 log_error("Couldn't create destination pathname for "
140 "logical volume link for %s", lv_name);
144 if (dm_snprintf(lvm1_group_path, sizeof(lvm1_group_path), "%s/group",
146 log_error("Couldn't create pathname for LVM1 group file for %s",
151 /* To reach this point, the VG must have been locked.
152 * As locking fails if the VG is active under LVM1, it's
153 * now safe to remove any LVM1 devices we find here
154 * (as well as any existing LVM2 symlink). */
155 if (!lstat(lvm1_group_path, &buf)) {
156 if (!S_ISCHR(buf.st_mode)) {
157 log_error("Non-LVM1 character device found at %s",
162 log_very_verbose("Removing %s", lvm1_group_path);
163 if (unlink(lvm1_group_path) < 0)
164 log_sys_error("unlink", lvm1_group_path);
168 if (!lstat(lv_path, &buf)) {
169 if (!S_ISLNK(buf.st_mode) && !S_ISBLK(buf.st_mode)) {
170 log_error("Symbolic link %s not created: file exists",
175 if (dm_udev_get_sync_support() && udev_checking() && check_udev) {
176 /* Check udev created the correct link. */
177 if (!stat(link_path, &buf_lp) &&
178 !stat(lv_path, &buf)) {
179 if (buf_lp.st_rdev == buf.st_rdev)
182 log_warn("Symlink %s that should have been "
183 "created by udev does not have "
184 "correct target. Falling back to "
185 "direct link creation", lv_path);
187 log_warn("Symlink %s that should have been "
188 "created by udev could not be checked "
189 "for its correctness. Falling back to "
190 "direct link creation.", lv_path);
194 log_very_verbose("Removing %s", lv_path);
195 if (unlink(lv_path) < 0) {
196 log_sys_error("unlink", lv_path);
199 } else if (dm_udev_get_sync_support() && udev_checking() && check_udev)
200 log_warn("The link %s should had been created by udev "
201 "but it was not found. Falling back to "
202 "direct link creation.", lv_path);
204 log_very_verbose("Linking %s -> %s", lv_path, link_path);
206 (void) dm_prepare_selinux_context(lv_path, S_IFLNK);
207 if (symlink(link_path, lv_path) < 0) {
208 log_sys_error("symlink", lv_path);
209 (void) dm_prepare_selinux_context(NULL, 0);
212 (void) dm_prepare_selinux_context(NULL, 0);
217 static int _rm_link(const char *dev_dir, const char *vg_name,
218 const char *lv_name, int check_udev)
221 char lv_path[PATH_MAX];
223 if (dm_snprintf(lv_path, sizeof(lv_path), "%s%s/%s",
224 dev_dir, vg_name, lv_name) == -1) {
225 log_error("Couldn't determine link pathname.");
229 if (lstat(lv_path, &buf) && errno == ENOENT)
231 else if (dm_udev_get_sync_support() && udev_checking() && check_udev)
232 log_warn("The link %s should have been removed by udev "
233 "but it is still present. Falling back to "
234 "direct link removal.", lv_path);
236 if (!S_ISLNK(buf.st_mode)) {
237 log_error("%s not symbolic link - not removing", lv_path);
241 log_very_verbose("Removing link %s", lv_path);
242 if (unlink(lv_path) < 0) {
243 log_sys_error("unlink", lv_path);
256 static int _do_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
257 const char *lv_name, const char *dev,
258 const char *old_lv_name, int check_udev)
262 if (!_mk_dir(dev_dir, vg_name) ||
263 !_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
267 if (!_rm_link(dev_dir, vg_name, lv_name, check_udev) ||
268 !_rm_dir(dev_dir, vg_name))
271 /* FIXME Use rename() */
273 if (old_lv_name && !_rm_link(dev_dir, vg_name, old_lv_name,
277 if (!_mk_link(dev_dir, vg_name, lv_name, dev, check_udev))
284 static DM_LIST_INIT(_fs_ops);
298 static void _store_str(char **pos, char **ptr, const char *str)
302 *pos += strlen(*ptr) + 1;
305 static int _stack_fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
306 const char *lv_name, const char *dev,
307 const char *old_lv_name, int check_udev)
309 struct fs_op_parms *fsp;
310 size_t len = strlen(dev_dir) + strlen(vg_name) + strlen(lv_name) +
311 strlen(dev) + strlen(old_lv_name) + 5;
314 if (!(fsp = dm_malloc(sizeof(*fsp) + len))) {
315 log_error("No space to stack fs operation");
321 fsp->check_udev = check_udev;
323 _store_str(&pos, &fsp->dev_dir, dev_dir);
324 _store_str(&pos, &fsp->vg_name, vg_name);
325 _store_str(&pos, &fsp->lv_name, lv_name);
326 _store_str(&pos, &fsp->dev, dev);
327 _store_str(&pos, &fsp->old_lv_name, old_lv_name);
329 dm_list_add(&_fs_ops, &fsp->list);
334 static void _pop_fs_ops(void)
336 struct dm_list *fsph, *fspht;
337 struct fs_op_parms *fsp;
339 dm_list_iterate_safe(fsph, fspht, &_fs_ops) {
340 fsp = dm_list_item(fsph, struct fs_op_parms);
341 _do_fs_op(fsp->type, fsp->dev_dir, fsp->vg_name, fsp->lv_name,
342 fsp->dev, fsp->old_lv_name, fsp->check_udev);
343 dm_list_del(&fsp->list);
348 static int _fs_op(fs_op_t type, const char *dev_dir, const char *vg_name,
349 const char *lv_name, const char *dev, const char *old_lv_name,
353 if (!_stack_fs_op(type, dev_dir, vg_name, lv_name, dev,
354 old_lv_name, check_udev))
359 return _do_fs_op(type, dev_dir, vg_name, lv_name, dev,
360 old_lv_name, check_udev);
363 int fs_add_lv(const struct logical_volume *lv, const char *dev)
365 return _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
366 dev, "", lv->vg->cmd->current_settings.udev_rules);
369 int fs_del_lv(const struct logical_volume *lv)
371 return _fs_op(FS_DEL, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
372 "", "", lv->vg->cmd->current_settings.udev_rules);
375 int fs_del_lv_byname(const char *dev_dir, const char *vg_name,
376 const char *lv_name, int check_udev)
378 return _fs_op(FS_DEL, dev_dir, vg_name, lv_name, "", "", check_udev);
381 int fs_rename_lv(struct logical_volume *lv, const char *dev,
382 const char *old_vgname, const char *old_lvname)
384 if (strcmp(old_vgname, lv->vg->name)) {
386 (_fs_op(FS_DEL, lv->vg->cmd->dev_dir, old_vgname,
387 old_lvname, "", "", lv->vg->cmd->current_settings.udev_rules) &&
388 _fs_op(FS_ADD, lv->vg->cmd->dev_dir, lv->vg->name,
389 lv->name, dev, "", lv->vg->cmd->current_settings.udev_rules));
392 return _fs_op(FS_RENAME, lv->vg->cmd->dev_dir, lv->vg->name, lv->name,
393 dev, old_lvname, lv->vg->cmd->current_settings.udev_rules);