Skip to content

Commit dc0da55

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) (cherry picked from commit cc2523a)
1 parent 7ac6ac2 commit dc0da55

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
@@ -385,6 +385,87 @@ static int stack_directory_get_name(const char *slink, char **ret) {
385385
return 0;
386386
}
387387

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

477+
r = link_update_diskseq(dev, slink, add);
478+
if (r != 0)
479+
return r;
480+
396481
r = stack_directory_get_name(slink, &dirname);
397482
if (r < 0)
398483
return log_device_debug_errno(dev, r, "Failed to build stack directory name for '%s': %m", slink);

0 commit comments

Comments
 (0)