def __search_checkpoints(self, n, x): for p in glob( os.path.join(kutil.fsget(x.dev), ".inodes", str(x.ino)) + "*"): dbg.info("found inodes: %s" % p) info = p.split(".") tic = (int(info[-2]) * 10**9 + int(info[-1]), 0) n.checkpoints.add(fsmgr.FileCheckpoint(tic, tic, x.dev, x.ino, p))
def get_file_dev_ino(self): """Get the (dev, ino) that this directory entry currently points to. Should be the same (dev, ino) pair that os.stat() would return when called on the pathname of this file.""" dev_pn = kutil.fsget(self.dev) dir_pn = kutil.iget(dev_pn, self.ino) cur_ino = self._get_inode(dir_pn, self.name_in_dir) return (self.dev, cur_ino)
def __init__(self, tic, tac, dev, ino): fs = kutil.fsget(dev) src = kutil.iget(fs, ino) dst = os.path.join(fs, ".inodes", str(ino) + "-" + str(tic[0])) shutil.copy(src, dst) self.name = ('File', dev, ino, dst) self.dev = dev self.ino = ino self.snap = dst super(FileContentCheckpoint, self).__init__(tic, tac)
def rollback(self, c): assert (isinstance(c, FileCheckpoint)) # XXX. hack to ignore /proc and /dev entries if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]): return None cpn = c.pn() try: dev_pn = kutil.fsget(self.dev) ino_pn = kutil.iget(dev_pn, self.ino) except kutil.MissingInode: if cpn is None: return dbg.infom("!", "#R<rollback#> %s(%s) -> %s" % (self.ino, ino_pn, cpn)) dbg.infom("readers %s" % str(self.readers)) dbg.infom("writers %s" % str(self.writers)) if runopts.dryrun: return cstat = os.lstat(cpn) if cpn else None istat = os.lstat(ino_pn) if (cstat and stat.S_IFMT(istat.st_mode) != stat.S_IFMT(cstat.st_mode)): raise Exception('inode changed types', cpn, ino_pn, cstat, istat) if stat.S_ISREG(istat.st_mode): if cpn: with open(cpn, 'r') as f1: f1data = f1.read() else: f1data = '' with open(ino_pn, 'r') as f2: f2data = f2.read() if f1data != f2data: with open(ino_pn, 'w') as f2: f2.write(f1data) elif stat.S_ISLNK(istat.st_mode): pass ## no way to change existing symlink elif stat.S_ISDIR(istat.st_mode): # XXX. pass else: raise Exception('cannot handle inode type', stat.S_IFMT(istat.st_mode))
def syscall_open(self, arg, ret): r = arg.data assert r.nr == syscall.NR_open assert ((r.args["path"].inode is None) or (r.args["path"].inode == r.ret.inode)) inode = r.ret.inode dbg.syscallm("!", "#R<open#>: %s" % (str(r))) if runopts.dryrun: return ret.origdata pn = r.args['path'].path # pathname to file # if not absolute pathname, retrieve with iget if not pn.startswith('/'): dentry = r.args['path'].entries[0] assert type(dentry) == sysarg.dentry pn = os.path.join("%s/%s" % (kutil.get(dentry.parent), dentry.name)) # flag == os.O_CREAT and only the case we really created an empty file if (r.args["path"].inode is None): src_pn = os.path.join(kutil.fsget(inode.dev), ".inodes", str(inode.ino)) # to keep the inode os.rename(src_pn, pn) # make it empty when newly created with open(pn, "w") as f: pass dbg.syscallm("!", "#R<rename#>: %s -> %s" % (src_pn, pn)) # if explicit truncate request if (r.args['flags'] & os.O_TRUNC): with open(pn, "w") as f: pass # If the syscall opened a _different_ inode than the file # points to now. path = r.args['path'] arg_name = path.path dir_dev = path.entries[0].parent.dev dir_ino = path.entries[0].parent.ino dirent = fsmgr.DirentDataNode.get(dir_dev, dir_ino, arg_name) (cur_dev, cur_ino) = dirent.get_file_dev_ino() ret.data = deepcopy(ret.origdata) ret.data.ret.inode.ino, ret.data.ret.inode.dev = (cur_ino, cur_dev) return ret.data
def search_snap(dev, ino): ## XXX hack to find snapshots fs = kutil.fsget(dev) if fs in ['/'] or any(fs.startswith(d) for d in ['/proc', '/dev']): yield (mgrapi.MinusInfinity(), mgrapi.MinusInfinity(), fs) return if not fs.endswith('trunk'): return root = os.path.dirname(fs) for s in os.listdir(root): if s.startswith("snap"): t = (int(s.split("-")[-1]) * (10**9), ) yield (t, t, os.path.join(root, s)) mi = mgrapi.MinusInfinity() if os.path.exists(os.path.join(root, 'fresh')): yield (mi, mi, os.path.join(root, 'fresh'))
def rollback(self, c): assert (isinstance(c, FileCheckpoint)) # XXX. hack to ignore /proc entries if any(c.d_pn.startswith(d) for d in ["/proc", "/dev"]): return cp_ino = None # ino of the directory _entry_ cpn = c.pn() if cpn: cp_ino = self._get_inode(cpn, self.name_in_dir) dev_pn = kutil.fsget(self.dev) dir_pn = kutil.iget(dev_pn, self.ino) cur_ino = self._get_inode(dir_pn, self.name_in_dir) if cp_ino == cur_ino: return if cur_ino is not None: # backup src = os.path.join(dir_pn, self.name_in_dir) dst = os.path.join(dev_pn, ".inodes", str(cur_ino)) dbg.infom("!", "#R<rename#>: %s -> %s" % (src, dst)) dbg.infom("readers %s" % str(self.readers)) dbg.infom("writers %s" % str(self.writers)) if not runopts.dryrun: os.rename(src, dst) if cp_ino is not None: src = kutil.iget(dev_pn, cp_ino) dst = os.path.join(dir_pn, self.name_in_dir) dbg.infom("!", "#R<link#>: %s -> %s" % (src, dst)) if not runopts.dryrun: os.link(src, dst) kutil.dcache_flush()