Skip to content

Commit cc2523a

Browse files
yuwatabluca
authored andcommitted
udev-node: skip stack directory creation for diskseq
The disk/by-diskseq symlink should not be shared with multiple block devices. Hence, it is not necessary to create stack directory for the symlink that manages which device owns the symlink. This is not just a optimization. If a service unit tries to mount a disk image but the service fails, then the diskseq of the loop device for the image may be continuously increased during restart, and inodes in /run may increase rapidly, as the stack directories are cleaned up only when udev queue is empty. Fixes #34637. (cherry picked from commit 09373c1) (cherry picked from commit 02a5e5a) (cherry picked from commit 54bc0da) (cherry picked from commit 67216d2)
1 parent 2641b10 commit cc2523a

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed

src/udev/udev-node.c

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,87 @@ static int stack_directory_open(sd_device *dev, const char *slink, int *ret_dirf
383383
return 0;
384384
}
385385

386+
static int link_update_diskseq(sd_device *dev, const char *slink, bool add) {
387+
_cleanup_free_ char *buf = NULL;
388+
const char *fname, *diskseq, *subsystem = NULL, *devtype = NULL;
389+
int r;
390+
391+
assert(dev);
392+
assert(slink);
393+
394+
(void) sd_device_get_subsystem(dev, &subsystem);
395+
if (!streq_ptr(subsystem, "block"))
396+
return 0;
397+
398+
fname = path_startswith(slink, "/dev/disk/by-diskseq");
399+
if (isempty(fname))
400+
return 0;
401+
402+
(void) sd_device_get_devtype(dev, &devtype);
403+
if (streq_ptr(devtype, "partition")) {
404+
_cleanup_free_ char *suffix = NULL;
405+
const char *partn, *p;
406+
407+
/* Check if the symlink has an expected suffix "-part%n". See 60-persistent-storage.rules. */
408+
409+
r = sd_device_get_sysnum(dev, &partn);
410+
if (r < 0) {
411+
/* Cannot verify the symlink is owned by this device. Let's create the stack directory for the symlink. */
412+
log_device_debug_errno(dev, r, "Failed to get sysnum, but symlink '%s' is requested, ignoring: %m", slink);
413+
return 0;
414+
}
415+
416+
suffix = strjoin("-part", partn);
417+
if (!suffix)
418+
return -ENOMEM;
419+
420+
p = endswith(fname, suffix);
421+
if (!p) {
422+
log_device_debug(dev, "Unexpected by-diskseq symlink '%s' is requested, proceeding anyway.", slink);
423+
return 0;
424+
}
425+
426+
buf = strndup(fname, p - fname);
427+
if (!buf)
428+
return -ENOMEM;
429+
430+
fname = buf;
431+
}
432+
433+
/* Check if the diskseq part of the symlink is in digits. */
434+
if (!in_charset(fname, DIGITS)) {
435+
log_device_debug(dev, "Unexpected by-diskseq symlink '%s' is requested, proceeding anyway.", slink);
436+
return 0; /* unexpected by-diskseq symlink */
437+
}
438+
439+
/* On removal, we cannot verify the diskseq. Skipping further check below. */
440+
if (!add) {
441+
if (unlink(slink) < 0 && errno != ENOENT)
442+
return log_device_debug_errno(dev, errno, "Failed to remove '%s': %m", slink);
443+
444+
(void) rmdir_parents(slink, "/dev");
445+
return 1; /* done */
446+
}
447+
448+
/* Check if the diskseq matches with the DISKSEQ property. */
449+
r = sd_device_get_property_value(dev, "DISKSEQ", &diskseq);
450+
if (r < 0) {
451+
log_device_debug_errno(dev, r, "Failed to get DISKSEQ property, but symlink '%s' is requested, ignoring: %m", slink);
452+
return 0;
453+
}
454+
455+
if (!streq(fname, diskseq)) {
456+
log_device_debug(dev, "Unexpected by-diskseq symlink '%s' is requested (DISKSEQ=%s), proceeding anyway.", slink, diskseq);
457+
return 0;
458+
}
459+
460+
r = node_symlink(dev, /* devnode = */ NULL, slink);
461+
if (r < 0)
462+
return r;
463+
464+
return 1; /* done */
465+
}
466+
386467
static int link_update(sd_device *dev, const char *slink, bool add) {
387468
_cleanup_close_ int dirfd = -EBADF, lockfd = -EBADF;
388469
_cleanup_free_ char *devnode = NULL;
@@ -391,6 +472,10 @@ static int link_update(sd_device *dev, const char *slink, bool add) {
391472
assert(dev);
392473
assert(slink);
393474

475+
r = link_update_diskseq(dev, slink, add);
476+
if (r != 0)
477+
return r;
478+
394479
r = stack_directory_open(dev, slink, &dirfd, &lockfd);
395480
if (r < 0)
396481
return r;

0 commit comments

Comments
 (0)