svalen 2023-09-21 18:27 采纳率: 0%
浏览 7

奇怪的fcntl上锁Permission Denied问题

最近在做移植Samba服务到嵌入式设备中,在移植的过程中出现如下问题:

tdb(unnamed): tdb_brlock failed (fd=4) at offset 0 rw_type=1 lck_type=14 len=1
tdb(unnamed): tdb_open_ex: failed to get global lock on /usr/local/samba/var/locks/messages.tdb: Permission denied
ERROR: Failed to initialise messages database: Permission denied
messaging_tdb_init failed: NT_STATUS_ACCESS_DENIED
Could not init smbd messaging context.

经过各种权限设置都不能解决,之后通过排查发现是使用fcntl()设置F_SETLKW写入锁造成的,在网上搜索到以下程序进行测试,问题得以重现:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>

int lock_reg(int fd, int cmd, short lock_type, short lock_whence, off_t lock_start, off_t lock_len)
{
        struct flock lock;
        lock.l_type = lock_type;
        lock.l_whence = lock_whence;
        lock.l_start = lock_start;
        lock.l_len = lock_len;
        lock.l_pid = getpid();

        if (fcntl(fd, cmd, &lock) < 0) {
                if (errno == EACCES || errno == EAGAIN ) {
                        printf("file lock by other processes: %s\n", strerror(errno));
                        while(1);
                        return -1;
                }
                printf("lock file fail.\n");
                return -1;
        }
        if (lock_type == F_WRLCK) {
                printf("lock by %d.\n", getpid());
        } else if (lock_type == F_UNLCK) {
                printf("unlock by %d.\n", getpid());
        }
        return 0;
}


int reg_lock(int fd)
{
        return lock_reg(fd, F_SETLK, F_WRLCK, 0, SEEK_SET, 0);
}
int reg_unlock(int fd)
{
        return lock_reg(fd, F_SETLK, F_UNLCK, 0, SEEK_SET, 0);
}

int reg_lockw(int fd)
{
        return lock_reg(fd, F_SETLKW, F_WRLCK, 0, SEEK_SET, 0);
}
int reg_unlockw(int fd)
{
        return lock_reg(fd, F_SETLKW, F_UNLCK, 0, SEEK_SET, 0);
}


int main(int argv, char *argc[])
{
        char *buf;
        int i;
        int ret;
        int fd;

        if (argv < 2) {
                printf("argc error!\n");
                return -1;
        }
        fd = open("processes.txt", O_CREAT|O_RDWR|O_APPEND, 777);
        ret = reg_lockw(fd);
        if (ret !=0 ) {
                return -1;
        }
        sleep(5);
        buf = argc[1];
        i = 0;
        while (i < strlen(buf)) {
                if (write(fd, buf+i, sizeof(char)) < sizeof(char)) {
                        printf("printf out error!\n");
                        return -1;
                }
                        printf(" %c:out by pid %d.\n", buf[i], getpid());
                i++;
                sleep(1);
        }
        ret = reg_unlockw(fd);
        if (ret !=0 ) {
                return -1;
        }
        close(fd);
        return 0;
}

问题虽然找到了,但怎么解决却没有思路,猜想可能是文件系统或者内核设置造成的,如有人也遇到过同样的问题并解决成功,还望赐教。
Linux内核版本:4.19.91
文件系统:

Filesystem           1K-blocks      Used Available Use% Mounted on
tmpfs                   126908         0    126908   0% /dev
tmpfs                   126908      3012    123896   2% /tmp
tmpfs                   126908        12    126896   0% /var/run
/dev/ubi0_0              27980     19792      8188  71% /lib/modules
/dev/ubi0_0              27980     19792      8188  71% /usr/bin
/dev/ubi0_0              27980     19792      8188  71% /usr/lib
/dev/ubi1_0              40828     19472     21356  48% /mnt/app
/dev/mmcblk0p1        31166464  29193472   1972992  94% /mnt/sd

mount信息:

rootfs on / type rootfs (rw)
proc on /proc type proc (rw,relatime)
sysfs on /sys type sysfs (rw,relatime)
tmpfs on /dev type tmpfs (rw,relatime)
tmpfs on /tmp type tmpfs (rw,relatime)
tmpfs on /var/run type tmpfs (rw,relatime)
debugfs on /sys/kernel/debug type debugfs (rw,relatime)
devpts on /dev/pts type devpts (rw,relatime,mode=600,ptmxmode=000)
/dev/ubi0_0 on /lib/modules type ubifs (rw,relatime,assert=read-only,ubi=0,vol=0)
/dev/ubi0_0 on /usr/bin type ubifs (rw,relatime,assert=read-only,ubi=0,vol=0)
/dev/ubi0_0 on /usr/lib type ubifs (rw,relatime,assert=read-only,ubi=0,vol=0)
/dev/ubi1_0 on /mnt/app type ubifs (rw,relatime,assert=read-only,ubi=1,vol=0)
/dev/mmcblk0p1 on /mnt/sd type vfat (rw,dirsync,relatime,fmask=0000,dmask=0000,allow_utime=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,tz=UTC,errors=remount-ro)
  • 写回答

1条回答 默认 最新

  • 专家-赤兔[在线] 全栈领域优质创作者 2023-09-22 00:18
    关注

    引用 皆我百晓生 小程序回复内容作答:
    根据您提供的信息,问题可能是由于文件系统的权限设置或者文件系统类型导致的。以下是可能的解决方案:

    1. 检查文件系统权限:确保目录 /usr/local/samba/var/locks 可以被当前用户或者Samba服务访问和写入。您可以使用chmod命令更改权限,例如:sudo chmod 777 /usr/local/samba/var/locks。

    2. 检查文件系统类型:确认文件系统类型是否支持文件锁定。对于某些文件系统类型(如tmpfs),文件锁定可能不起作用。您可以尝试将Samba服务使用的文件目录更改为支持文件锁定的文件系统。

    3. 检查内核设置:查看内核配置中是否启用了文件锁定功能。您可以通过检查 /usr/src/linux/.config 文件中的相关设置来确认。

    4. 更新内核版本:如果可能的话,尝试更新到最新版本的内核,以解决可能存在的问题。

    5. 使用其他锁定方式:如果fcntl()函数仍然无法正常工作,您可以尝试使用其他的锁定方式,例如pthread_mutex_lock()或者System V信号量。

    请注意,在对系统进行更改之前,务必备份重要数据,并小心操作,以避免引起其他问题。如果您需要进一步的帮助,请提供更多关于您的环境和配置的详细信息。

    评论

报告相同问题?

问题事件

  • 创建了问题 9月21日

悬赏问题

  • ¥100 华为手机私有App后台保活
  • ¥15 sqlserver中加密的密码字段查询问题
  • ¥20 有谁能看看我coe文件到底哪儿有问题吗?
  • ¥20 我的这个coe文件到底哪儿出问题了
  • ¥15 matlab使用自定义函数时一直报错输入参数过多
  • ¥15 设计一个温度闭环控制系统
  • ¥100 rtmpose姿态评估
  • ¥15 通联支付网上收银统一下单接口
  • ¥15 angular有偿编写,
  • ¥15 centos7系统下abinit安装时make出错