Advisory locks for restoration 26/322626/3
authorMichal Bloch <m.bloch@samsung.com>
Fri, 11 Apr 2025 17:07:33 +0000 (19:07 +0200)
committerMichal Bloch <m.bloch@samsung.com>
Mon, 14 Apr 2025 14:13:50 +0000 (16:13 +0200)
Change-Id: Ic394369fa3ab017503deb329e6dfee0328736f7c

src/service/src/main_restore.cpp

index aee985214a1bc2842fa5f78ffa9b62f7a7845ae6..1761c294023b29e7e4e403143698fad31b28b426 100644 (file)
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  * THE SOFTWARE. */
 
+#define _GNU_SOURCE
+
 #include "main_restore.hpp"
 
 #include "fs_helpers.hpp"
 #include "main_context.hpp"
 #include "os_ops.hpp"
 
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
 #include <filesystem>
 #include <fstream>
+#include <string>
+#include <utility>
 
 #undef LOG_TAG
 #define LOG_TAG "SESSIOND"
 #include <dlog.h>
 
-/* TODO: without some sort of lock, restoration is racy, since in case the "real" sessiond
- * manages to start before the restore-only version is done, they could both be trying to
- * mount the same fixed-size subsession. */
+using namespace std::string_literals;
+
+std::string get_restoration_lock_filename(int uid)
+{
+       return "/run/sessiond-restore-"s + std::to_string(uid) + ".lock";
+}
+
 static int restoration_lock(int uid)
 {
-       return -1;
+       const auto filename = get_restoration_lock_filename(uid);
+       const int fd = open(filename.c_str(), O_CREAT | O_WRONLY, 0600);
+       if (fd == -1)
+               return -1;
+
+       struct flock f;
+       f.l_type   = F_WRLCK;
+       f.l_whence = SEEK_SET;
+       f.l_start  = 0;
+       f.l_len    = 0;
+       f.l_pid    = 0;
+
+       if (fcntl (fd, F_OFD_SETLKW, &f) < 0) {
+               close(fd);
+               return -1;
+       }
+
+       return fd;
 }
 
 static void restoration_unlock(int fd)
 {
+       /* OFD locks don't need F_UNLCK, it's enough to just close. */
+       close(fd);
 }
 
 static void restore_user_session(const fs::path& user_home_dir)