Пример #1
0
def test_notify_store(testfs):
    (mnt_dir, fs_state) = testfs
    with open(os.path.join(mnt_dir, 'message'), 'r') as fh:
        llfuse.setxattr(mnt_dir, 'command', b'store')
        fs_state.read_called = False
        assert fh.read() == 'hello world\n'
        assert not fs_state.read_called
Пример #2
0
def main(args=None):
    '''Control a mounted S3QL File System.'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    path = options.mountpoint

    ctrlfile = assert_fs_owner(path, mountpoint=True)

    if options.action == 'flushcache':
        llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    elif options.action == 'dropcache':
        llfuse.setxattr(ctrlfile, 's3ql_dropcache!', b'dummy')

    elif options.action == 'upload-meta':
        llfuse.setxattr(ctrlfile, 'upload-meta', b'dummy')

    elif options.action == 'log':
        level = getattr(logging, options.level.upper())
        cmd = ('(%r, %r)' % (level, ','.join(options.modules))).encode()
        llfuse.setxattr(ctrlfile, 'logging', cmd)

    elif options.action == 'cachesize':
        llfuse.setxattr(ctrlfile, 'cachesize', ('%d' % (options.cachesize * 1024,)).encode())
Пример #3
0
 def check(_wait_time=[0.01]):
     llfuse.setxattr(mnt_dir, 'command', b'forget_entry')
     time.sleep(_wait_time[0])
     fs_state.lookup_called = False
     os.stat(path)
     _wait_time[0] += max(1, _wait_time[0])
     return fs_state.lookup_called
Пример #4
0
 def check(_wait_time=[0.01]):
     llfuse.setxattr(mnt_dir, 'command', b'forget_entry')
     time.sleep(_wait_time[0])
     fs_state.lookup_called = False
     os.stat(path)
     _wait_time[0] += max(1, _wait_time[0])
     return fs_state.lookup_called
Пример #5
0
def main(args=None):
    '''Recursively delete files and directories in an S3QL file system'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if not os.path.exists(name):
            raise QuietError('%r does not exist' % name)

        parent = os.path.dirname(os.path.abspath(name))
        fstat_p = os.stat(parent)
        fstat = os.stat(name)

        if fstat_p.st_dev != fstat.st_dev:
            raise QuietError('%s is a mount point itself.' % name)

        ctrlfile = os.path.join(parent, CTRL_NAME)
        if not (CTRL_NAME not in llfuse.listdir(parent) and os.path.exists(ctrlfile)):
            raise QuietError('%s is not on an S3QL file system' % name)

        if os.stat(ctrlfile).st_uid != os.geteuid():
            raise QuietError('Only root and the mounting user may run s3qlrm.')

        llfuse.setxattr(ctrlfile, 'rmtree', pickle.dumps((fstat_p.st_ino,
                                                          os.path.basename(name)),
                                                          pickle.HIGHEST_PROTOCOL))
Пример #6
0
def test_notify_store(testfs):
    (mnt_dir, fs_state) = testfs
    with open(os.path.join(mnt_dir, 'message'), 'r') as fh:
        llfuse.setxattr(mnt_dir, 'command', b'store')
        fs_state.read_called = False
        assert fh.read() == 'hello world\n'
        assert not fs_state.read_called
Пример #7
0
def blocking_umount(mountpoint):
    '''Invoke fusermount and wait for daemon to terminate.'''

    with open('/dev/null', 'wb') as devnull:
        if subprocess.call(['fuser', '-m', mountpoint], stdout=devnull,
                           stderr=devnull) == 0:
            raise MountInUseError(mountpoint)

    ctrlfile = os.path.join(mountpoint, CTRL_NAME)

    log.debug('Flushing cache...')
    llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    # Get pid
    log.debug('Trying to get pid')
    pid = parse_literal(llfuse.getxattr(ctrlfile, 's3ql_pid?'), int)
    log.debug('PID is %d', pid)

    # Get command line to make race conditions less-likely
    cmdline = get_cmdline(pid)

    # Unmount
    log.debug('Unmounting...')

    if os.getuid() == 0 or platform.system() == 'Darwin':
        # MacOS X always uses umount rather than fusermount
        umount_cmd = ['umount', mountpoint]
    else:
        umount_cmd = ['fusermount', '-u', mountpoint]

    if subprocess.call(umount_cmd) != 0:
        raise UmountSubError(mountpoint)

    # Wait for daemon
    log.debug('Uploading metadata...')
    step = 0.1
    while True:
        try:
            os.kill(pid, 0)
        except OSError:
            log.debug('Kill failed, assuming daemon has quit.')
            break

        # Check that the process did not terminate and the PID
        # was reused by a different process
        cmdline2 = get_cmdline(pid)
        if cmdline2 is None:
            log.debug('Reading cmdline failed, assuming daemon has quit.')
            break
        elif cmdline2 == cmdline:
            log.debug('PID still alive and commandline unchanged.')
        else:
            log.debug('PID still alive, but cmdline changed')
            break

        # Process still exists, we wait
        log.debug('Daemon seems to be alive, waiting...')
        time.sleep(step)
        if step < 1:
            step += 0.1
Пример #8
0
 def check(_wait_time=[0.01]):
     llfuse.setxattr(mnt_dir, 'command', b'forget_inode')
     time.sleep(_wait_time[0])
     fs_state.read_called = False
     fh.seek(0)
     assert fh.read() == 'hello world\n'
     _wait_time[0] += max(1, _wait_time[0])
     return fs_state.read_called
Пример #9
0
 def check(_wait_time=[0.01]):
     llfuse.setxattr(mnt_dir, 'command', b'forget_inode')
     time.sleep(_wait_time[0])
     fs_state.read_called = False
     fh.seek(0)
     assert fh.read() == 'hello world\n'
     _wait_time[0] += max(1, _wait_time[0])
     return fs_state.read_called
Пример #10
0
 def tst_bug382(self):
     dirname = self.newname()
     fullname = self.mnt_dir + "/" + dirname
     os.mkdir(fullname)
     assert stat.S_ISDIR(os.stat(fullname).st_mode)
     assert dirname in llfuse.listdir(self.mnt_dir)
     cmd = ('(%d, %r)' % (llfuse.ROOT_INODE, path2bytes(dirname))).encode()
     llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME), 'rmtree', cmd)
     assert_raises(FileNotFoundError, os.stat, fullname)
     assert dirname not in llfuse.listdir(self.mnt_dir)
Пример #11
0
 def tst_bug382(self):
     dirname = self.newname()
     fullname = self.mnt_dir + "/" + dirname
     os.mkdir(fullname)
     assert stat.S_ISDIR(os.stat(fullname).st_mode)
     assert dirname in llfuse.listdir(self.mnt_dir)
     cmd = ('(%d, %r)' % (llfuse.ROOT_INODE, path2bytes(dirname))).encode()
     llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME), 'rmtree', cmd)
     assert_raises(FileNotFoundError, os.stat, fullname)
     assert dirname not in llfuse.listdir(self.mnt_dir)
Пример #12
0
 def tst_bug382(self):
     dirname = self.newname()
     fullname = self.mnt_dir + "/" + dirname
     os.mkdir(fullname)
     self.assertTrue(stat.S_ISDIR(os.stat(fullname).st_mode))
     self.assertTrue(dirname in llfuse.listdir(self.mnt_dir))
     llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME), 
                     'rmtree', pickle.dumps((llfuse.ROOT_INODE, path2bytes(dirname)),
                                            PICKLE_PROTOCOL))
     self.assertRaises(FileNotFoundError, os.stat, fullname)
     self.assertTrue(dirname not in llfuse.listdir(self.mnt_dir))
Пример #13
0
 def tst_bug382(self):
     dirname = self.newname()
     fullname = self.mnt_dir + "/" + dirname
     os.mkdir(fullname)
     assert stat.S_ISDIR(os.stat(fullname).st_mode)
     assert dirname in llfuse.listdir(self.mnt_dir)
     llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME),
                     'rmtree', pickle.dumps((llfuse.ROOT_INODE, path2bytes(dirname)),
                                            PICKLE_PROTOCOL))
     assert_raises(FileNotFoundError, os.stat, fullname)
     assert dirname not in llfuse.listdir(self.mnt_dir)
Пример #14
0
 def tst_bug382(self):
     dirname = self.newname()
     fullname = self.mnt_dir + "/" + dirname
     os.mkdir(fullname)
     self.assertTrue(stat.S_ISDIR(os.stat(fullname).st_mode))
     self.assertTrue(dirname in llfuse.listdir(self.mnt_dir))
     llfuse.setxattr('%s/%s' % (self.mnt_dir, CTRL_NAME), 
                     'rmtree', pickle.dumps((llfuse.ROOT_INODE, dirname),
                                            pickle.HIGHEST_PROTOCOL))                
     self.assertRaises(OSError, os.stat, fullname)
     self.assertTrue(dirname not in llfuse.listdir(self.mnt_dir))
Пример #15
0
def main(args=None):
    '''Control a mounted S3QL File System.'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    path = options.mountpoint

    ctrlfile = assert_fs_owner(path, mountpoint=True)

    if options.action == 'flushcache':
        llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    if options.action == 'upload-meta':
        llfuse.setxattr(ctrlfile, 'upload-meta', b'dummy')

    elif options.action == 'log':
        llfuse.setxattr(
            ctrlfile, 'logging',
            pickle.dumps((options.level, options.modules), PICKLE_PROTOCOL))

    elif options.action == 'cachesize':
        llfuse.setxattr(
            ctrlfile, 'cachesize',
            pickle.dumps(options.cachesize * 1024, PICKLE_PROTOCOL))
Пример #16
0
def main(args=None):
    '''Control a mounted S3QL File System.'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    path = options.mountpoint

    ctrlfile = assert_fs_owner(path, mountpoint=True)

    if options.action == 'flushcache':
        llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    if options.action == 'upload-meta':
        llfuse.setxattr(ctrlfile, 'upload-meta', b'dummy')

    elif options.action == 'log':
        cmd = ('(%r, %r)' % (options.level, ','.join(options.modules))).encode()
        llfuse.setxattr(ctrlfile, 'logging', cmd)

    elif options.action == 'cachesize':
        llfuse.setxattr(ctrlfile, 'cachesize', ('%d' % options.cachesize * 1024).encode())
Пример #17
0
def main(args=None):
    '''Control a mounted S3QL File System.'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    path = options.mountpoint
    
    if not os.path.exists(path):
        raise QuietError('Mountpoint %r does not exist' % path)
    
    ctrlfile = os.path.join(path, CTRL_NAME)
    if not (CTRL_NAME not in llfuse.listdir(path)
            and os.path.exists(ctrlfile)):
        raise QuietError('Mountpoint is not an S3QL file system')

    if os.stat(ctrlfile).st_uid != os.geteuid() and os.geteuid() != 0:
        raise QuietError('Only root and the mounting user may run s3qlctrl.')
    
    if options.action == 'flushcache':
        llfuse.setxattr(ctrlfile, 's3ql_flushcache!', 'dummy')

    if options.action == 'upload-meta':
        llfuse.setxattr(ctrlfile, 'upload-meta', 'dummy')
        
    elif options.action == 'log':
        llfuse.setxattr(ctrlfile, 'logging', 
                      pickle.dumps((options.level, options.modules),
                                   pickle.HIGHEST_PROTOCOL))

    elif options.action == 'cachesize':
        llfuse.setxattr(ctrlfile, 'cachesize', pickle.dumps(options.cachesize*1024))    
Пример #18
0
def main(args=None):
    '''Control a mounted S3QL File System.'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    path = options.mountpoint

    ctrlfile = assert_fs_owner(path, mountpoint=True)

    if options.action == 'flushcache':
        llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    if options.action == 'upload-meta':
        llfuse.setxattr(ctrlfile, 'upload-meta', b'dummy')

    elif options.action == 'log':
        llfuse.setxattr(ctrlfile, 'logging',
                      pickle.dumps((options.level, options.modules),
                                   PICKLE_PROTOCOL))

    elif options.action == 'cachesize':
        llfuse.setxattr(ctrlfile, 'cachesize', 
                        pickle.dumps(options.cachesize * 1024, PICKLE_PROTOCOL))
Пример #19
0
def main(args=None):
    '''Make directory tree immutable'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if os.path.ismount(name):
            raise QuietError('%s is a mount point.' % name)
        ctrlfile = assert_fs_owner(name)
        fstat = os.stat(name)
        llfuse.setxattr(ctrlfile, 'lock', pickle.dumps((fstat.st_ino,), PICKLE_PROTOCOL))
Пример #20
0
def main(args=None):
    '''Make directory tree immutable'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if os.path.ismount(name):
            raise QuietError('%s is a mount point.' % name)
        ctrlfile = assert_fs_owner(name)
        fstat = os.stat(name)
        llfuse.setxattr(ctrlfile, 'lock', ('%d' % fstat.st_ino).encode())
Пример #21
0
def main(args=None):
    '''Efficiently copy a directory tree'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    if not os.path.exists(options.source):
        raise QuietError('Source directory %r does not exist' % options.source)

    if os.path.exists(options.target):
        raise QuietError('Target directory %r must not yet exist.' % options.target)

    parent = os.path.dirname(os.path.abspath(options.target))
    if not os.path.exists(parent):
        raise QuietError('Target parent %r does not exist' % parent)

    fstat_s = os.stat(options.source)
    fstat_p = os.stat(parent)
    if not stat.S_ISDIR(fstat_s.st_mode):
        raise QuietError('Source %r is not a directory' % options.source)

    if not stat.S_ISDIR(fstat_p.st_mode):
        raise QuietError('Target parent %r is not a directory' % parent)

    if fstat_p.st_dev != fstat_s.st_dev:
        raise QuietError('Source and target are not on the same file system.')

    ctrlfile = os.path.join(parent, CTRL_NAME)
    if not (CTRL_NAME not in llfuse.listdir(parent) and os.path.exists(ctrlfile)):
        raise QuietError('Source and target are not on an S3QL file system')

    if os.stat(ctrlfile).st_uid != os.geteuid() and os.geteuid() != 0:
        raise QuietError('Only root and the mounting user may run s3qlcp.')

    try:
        os.mkdir(options.target)
    except OSError as exc:
        if exc.errno == errno.EACCES:
            raise QuietError('No permission to create target directory')
        else:
            raise

    fstat_t = os.stat(options.target)
    llfuse.setxattr(ctrlfile, 'copy', pickle.dumps((fstat_s.st_ino, fstat_t.st_ino),
                                                    pickle.HIGHEST_PROTOCOL))
Пример #22
0
def main(args=None):
    """Recursively delete files and directories in an S3QL file system"""

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if os.path.ismount(name):
            raise QuietError("%s is a mount point." % name)

        ctrlfile = assert_fs_owner(name)
        fstat_p = os.stat(os.path.dirname(os.path.abspath(name)))
        cmd = ("(%d, %r)" % (fstat_p.st_ino, path2bytes(os.path.basename(name)))).encode()
        llfuse.setxattr(ctrlfile, "rmtree", cmd)
Пример #23
0
def main(args=None):
    '''Recursively delete files and directories in an S3QL file system'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if os.path.ismount(name):
            raise QuietError('%s is a mount point.' % name)

        ctrlfile = assert_fs_owner(name)
        fstat_p = os.stat(os.path.dirname(os.path.abspath(name)))
        llfuse.setxattr(ctrlfile, 'rmtree', pickle.dumps((fstat_p.st_ino,
                                                          path2bytes(os.path.basename(name))),
                                                          PICKLE_PROTOCOL))
Пример #24
0
def main(args=None):
    '''Recursively delete files and directories in an S3QL file system'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    for name in options.path:
        if os.path.ismount(name):
            raise QuietError('%s is a mount point.' % name)

        ctrlfile = assert_fs_owner(name)
        fstat_p = os.stat(os.path.dirname(os.path.abspath(name)))
        cmd = ('(%d, %r)' %
               (fstat_p.st_ino, path2bytes(os.path.basename(name)))).encode()
        llfuse.setxattr(ctrlfile, 'rmtree', cmd)
Пример #25
0
def main(args=None):
    '''Efficiently copy a directory tree'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    if not os.path.exists(options.source):
        raise QuietError('Source directory %r does not exist' % options.source)

    if os.path.exists(options.target):
        raise QuietError('Target directory %r must not yet exist.' %
                         options.target)

    parent = os.path.dirname(os.path.abspath(options.target))
    if not os.path.exists(parent):
        raise QuietError('Target parent %r does not exist' % parent)

    fstat_s = os.stat(options.source)
    fstat_p = os.stat(parent)
    if not stat.S_ISDIR(fstat_s.st_mode):
        raise QuietError('Source %r is not a directory' % options.source)

    if not stat.S_ISDIR(fstat_p.st_mode):
        raise QuietError('Target parent %r is not a directory' % parent)

    if fstat_p.st_dev != fstat_s.st_dev:
        raise QuietError('Source and target are not on the same file system.')

    if os.path.ismount(options.source):
        raise QuietError('%s is a mount point.' % options.source)

    ctrlfile = assert_fs_owner(options.source)
    try:
        os.mkdir(options.target)
    except PermissionError:
        raise QuietError('No permission to create target directory')

    fstat_t = os.stat(options.target)
    llfuse.setxattr(
        ctrlfile, 'copy',
        pickle.dumps((fstat_s.st_ino, fstat_t.st_ino), PICKLE_PROTOCOL))
Пример #26
0
def main(args=None):
    '''Efficiently copy a directory tree'''

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    if not os.path.exists(options.source):
        raise QuietError('Source directory %r does not exist' % options.source)

    if os.path.exists(options.target):
        raise QuietError('Target directory %r must not yet exist.' % options.target)

    parent = os.path.dirname(os.path.abspath(options.target))
    if not os.path.exists(parent):
        raise QuietError('Target parent %r does not exist' % parent)

    fstat_s = os.stat(options.source)
    fstat_p = os.stat(parent)
    if not stat.S_ISDIR(fstat_s.st_mode):
        raise QuietError('Source %r is not a directory' % options.source)

    if not stat.S_ISDIR(fstat_p.st_mode):
        raise QuietError('Target parent %r is not a directory' % parent)

    if fstat_p.st_dev != fstat_s.st_dev:
        raise QuietError('Source and target are not on the same file system.')

    if os.path.ismount(options.source):
        raise QuietError('%s is a mount point.' % options.source)

    ctrlfile = assert_fs_owner(options.source)
    try:
        os.mkdir(options.target)
    except PermissionError:
        raise QuietError('No permission to create target directory')

    fstat_t = os.stat(options.target)
    llfuse.setxattr(ctrlfile, 'copy',
                    ('(%d, %d)' % (fstat_s.st_ino, fstat_t.st_ino)).encode())
Пример #27
0
def main(args=None):
    """Efficiently copy a directory tree"""

    if args is None:
        args = sys.argv[1:]

    options = parse_args(args)
    setup_logging(options)

    if not os.path.exists(options.source):
        raise QuietError("Source directory %r does not exist" % options.source)

    if os.path.exists(options.target):
        raise QuietError("Target directory %r must not yet exist." % options.target)

    parent = os.path.dirname(os.path.abspath(options.target))
    if not os.path.exists(parent):
        raise QuietError("Target parent %r does not exist" % parent)

    fstat_s = os.stat(options.source)
    fstat_p = os.stat(parent)
    if not stat.S_ISDIR(fstat_s.st_mode):
        raise QuietError("Source %r is not a directory" % options.source)

    if not stat.S_ISDIR(fstat_p.st_mode):
        raise QuietError("Target parent %r is not a directory" % parent)

    if fstat_p.st_dev != fstat_s.st_dev:
        raise QuietError("Source and target are not on the same file system.")

    if os.path.ismount(options.source):
        raise QuietError("%s is a mount point." % options.source)

    ctrlfile = assert_fs_owner(options.source)
    try:
        os.mkdir(options.target)
    except PermissionError:
        raise QuietError("No permission to create target directory")

    fstat_t = os.stat(options.target)
    llfuse.setxattr(ctrlfile, "copy", pickle.dumps((fstat_s.st_ino, fstat_t.st_ino), PICKLE_PROTOCOL))
Пример #28
0
def test_xattr():
    with tempfile.NamedTemporaryFile() as fh:
        key = 'user.new_attribute'
        assert _getxattr_helper(fh.name, key) is None
        value = b'a nice little bytestring'

        try:
            llfuse.setxattr(fh.name, key, value)
        except OSError as exc:
            if exc.errno == errno.ENOTSUP:
                pytest.skip('ACLs not supported for %s' % fh.name)
            raise
        assert _getxattr_helper(fh.name, key) == value

        if not hasattr(os, 'setxattr'):
            return

        key = 'user.another_new_attribute'
        assert _getxattr_helper(fh.name, key) is None
        value = b'a nice little bytestring, but slightly modified'
        os.setxattr(fh.name, key, value)
        assert _getxattr_helper(fh.name, key) == value
Пример #29
0
def test_xattr():
    with tempfile.NamedTemporaryFile() as fh:
        key = 'user.new_attribute'
        assert _getxattr_helper(fh.name, key) is None
        value = b'a nice little bytestring'

        try:
            llfuse.setxattr(fh.name, key, value)
        except OSError as exc:
            if exc.errno == errno.ENOTSUP:
                pytest.skip('ACLs not supported for %s' % fh.name)
            raise
        assert _getxattr_helper(fh.name, key) == value

        if not hasattr(os, 'setxattr'):
            return

        key = 'user.another_new_attribute'
        assert _getxattr_helper(fh.name, key) is None
        value = b'a nice little bytestring, but slightly modified'
        os.setxattr(fh.name, key, value)
        assert _getxattr_helper(fh.name, key) == value
Пример #30
0
def blocking_umount(mountpoint):
    '''Invoke fusermount and wait for daemon to terminate.'''

    with open('/dev/null', 'wb') as devnull:
        if subprocess.call(['fuser', '-m', mountpoint],
                           stdout=devnull,
                           stderr=devnull) == 0:
            raise MountInUseError(mountpoint)

    ctrlfile = os.path.join(mountpoint, CTRL_NAME)

    log.debug('Flushing cache...')
    llfuse.setxattr(ctrlfile, 's3ql_flushcache!', b'dummy')

    # Get pid
    log.debug('Trying to get pid')
    pid = parse_literal(llfuse.getxattr(ctrlfile, 's3ql_pid?'), int)
    log.debug('PID is %d', pid)

    # Get command line to make race conditions less-likely
    cmdline = get_cmdline(pid)

    # Unmount
    log.debug('Unmounting...')

    if os.getuid() == 0 or platform.system() == 'Darwin':
        # MacOS X always uses umount rather than fusermount
        umount_cmd = ['umount', mountpoint]
    else:
        umount_cmd = ['fusermount', '-u', mountpoint]

    if subprocess.call(umount_cmd) != 0:
        raise UmountSubError(mountpoint)

    # Wait for daemon
    log.debug('Uploading metadata...')
    step = 0.1
    while True:
        try:
            os.kill(pid, 0)
        except OSError:
            log.debug('Kill failed, assuming daemon has quit.')
            break

        # Check that the process did not terminate and the PID
        # was reused by a different process
        cmdline2 = get_cmdline(pid)
        if cmdline2 is None:
            log.debug('Reading cmdline failed, assuming daemon has quit.')
            break
        elif cmdline2 == cmdline:
            log.debug('PID still alive and commandline unchanged.')
        else:
            log.debug('PID still alive, but cmdline changed')
            break

        # Process still exists, we wait
        log.debug('Daemon seems to be alive, waiting...')
        time.sleep(step)
        if step < 1:
            step += 0.1
Пример #31
0
def blocking_umount(mountpoint):
    '''Invoke fusermount and wait for daemon to terminate.'''

    devnull = open('/dev/null', 'wb')
    if subprocess.call(
        ['fuser', '-m', mountpoint], stdout=devnull, stderr=devnull
    ) == 0:
        raise MountInUseError(mountpoint)

    ctrlfile = os.path.join(mountpoint, CTRL_NAME)

    log.debug('Flushing cache...')
    llfuse.setxattr(ctrlfile, b's3ql_flushcache!', b'dummy')

    # Get pid
    log.debug('Trying to get pid')
    pid = int(llfuse.getxattr(ctrlfile, b's3ql_pid?'))
    log.debug('PID is %d', pid)

    # Get command line to make race conditions less-likely
    with open('/proc/%d/cmdline' % pid, 'r') as fh:
        cmdline = fh.readline()
    log.debug('cmdline is %r', cmdline)

    # Unmount
    log.debug('Unmounting...')
    # This seems to be necessary to prevent weird busy errors
    time.sleep(3)

    if os.getuid() == 0:
        umount_cmd = ['umount', mountpoint]
    else:
        umount_cmd = ['fusermount', '-u', mountpoint]

    if subprocess.call(umount_cmd) != 0:
        raise UmountError(mountpoint)

    # Wait for daemon
    log.debug('Uploading metadata...')
    step = 0.5
    while True:
        try:
            os.kill(pid, 0)
        except OSError:
            log.debug('Kill failed, assuming daemon has quit.')
            break

        # Check that the process did not terminate and the PID
        # was reused by a different process
        try:
            with open('/proc/%d/cmdline' % pid, 'r') as fh:
                if fh.readline() != cmdline:
                    log.debug('PID still alive, but cmdline changed')
                    # PID must have been reused, original process terminated
                    break
                else:
                    log.debug('PID still alive and commandline unchanged.')
        except OSError:
            # Process must have exited by now
            log.debug('Reading cmdline failed, assuming daemon has quit.')
            break

        # Process still exists, we wait
        log.debug('Daemon seems to be alive, waiting...')
        time.sleep(step)
        if step < 10:
            step *= 2