133 lines · c
1// SPDX-License-Identifier: GPL-2.02 3#define _GNU_SOURCE4#include <fcntl.h>5#include <assert.h>6#include <stdio.h>7#include <unistd.h>8#include <string.h>9#include "../kselftest.h"10 11static int lock_set(int fd, struct flock *fl)12{13 int ret;14 15 fl->l_pid = 0; // needed for OFD locks16 fl->l_whence = SEEK_SET;17 ret = fcntl(fd, F_OFD_SETLK, fl);18 if (ret)19 perror("fcntl()");20 return ret;21}22 23static int lock_get(int fd, struct flock *fl)24{25 int ret;26 27 fl->l_pid = 0; // needed for OFD locks28 fl->l_whence = SEEK_SET;29 ret = fcntl(fd, F_OFD_GETLK, fl);30 if (ret)31 perror("fcntl()");32 return ret;33}34 35int main(void)36{37 int rc;38 struct flock fl, fl2;39 int fd = open("/tmp/aa", O_RDWR | O_CREAT | O_EXCL, 0600);40 int fd2 = open("/tmp/aa", O_RDONLY);41 42 unlink("/tmp/aa");43 assert(fd != -1);44 assert(fd2 != -1);45 ksft_print_msg("[INFO] opened fds %i %i\n", fd, fd2);46 47 /* Set some read lock */48 fl.l_type = F_RDLCK;49 fl.l_start = 5;50 fl.l_len = 3;51 rc = lock_set(fd, &fl);52 if (rc == 0) {53 ksft_print_msg54 ("[SUCCESS] set OFD read lock on first fd\n");55 } else {56 ksft_print_msg("[FAIL] to set OFD read lock on first fd\n");57 return -1;58 }59 /* Make sure read locks do not conflict on different fds. */60 fl.l_type = F_RDLCK;61 fl.l_start = 5;62 fl.l_len = 1;63 rc = lock_get(fd2, &fl);64 if (rc != 0)65 return -1;66 if (fl.l_type != F_UNLCK) {67 ksft_print_msg("[FAIL] read locks conflicted\n");68 return -1;69 }70 /* Make sure read/write locks do conflict on different fds. */71 fl.l_type = F_WRLCK;72 fl.l_start = 5;73 fl.l_len = 1;74 rc = lock_get(fd2, &fl);75 if (rc != 0)76 return -1;77 if (fl.l_type != F_UNLCK) {78 ksft_print_msg79 ("[SUCCESS] read and write locks conflicted\n");80 } else {81 ksft_print_msg82 ("[SUCCESS] read and write locks not conflicted\n");83 return -1;84 }85 /* Get info about the lock on first fd. */86 fl.l_type = F_UNLCK;87 fl.l_start = 5;88 fl.l_len = 1;89 rc = lock_get(fd, &fl);90 if (rc != 0) {91 ksft_print_msg92 ("[FAIL] F_OFD_GETLK with F_UNLCK not supported\n");93 return -1;94 }95 if (fl.l_type != F_UNLCK) {96 ksft_print_msg97 ("[SUCCESS] F_UNLCK test returns: locked, type %i pid %i len %zi\n",98 fl.l_type, fl.l_pid, fl.l_len);99 } else {100 ksft_print_msg101 ("[FAIL] F_OFD_GETLK with F_UNLCK did not return lock info\n");102 return -1;103 }104 /* Try the same but by locking everything by len==0. */105 fl2.l_type = F_UNLCK;106 fl2.l_start = 0;107 fl2.l_len = 0;108 rc = lock_get(fd, &fl2);109 if (rc != 0) {110 ksft_print_msg111 ("[FAIL] F_OFD_GETLK with F_UNLCK not supported\n");112 return -1;113 }114 if (memcmp(&fl, &fl2, sizeof(fl))) {115 ksft_print_msg116 ("[FAIL] F_UNLCK test returns: locked, type %i pid %i len %zi\n",117 fl.l_type, fl.l_pid, fl.l_len);118 return -1;119 }120 ksft_print_msg("[SUCCESS] F_UNLCK with len==0 returned the same\n");121 /* Get info about the lock on second fd - no locks on it. */122 fl.l_type = F_UNLCK;123 fl.l_start = 0;124 fl.l_len = 0;125 lock_get(fd2, &fl);126 if (fl.l_type != F_UNLCK) {127 ksft_print_msg128 ("[FAIL] F_OFD_GETLK with F_UNLCK return lock info from another fd\n");129 return -1;130 }131 return 0;132}133