]> git.apps.os.sepia.ceph.com Git - ceph-ci.git/commitdiff
fusetrace: s/Mutex/ceph::mutex/
authorKefu Chai <kchai@redhat.com>
Wed, 17 Jul 2019 09:02:31 +0000 (17:02 +0800)
committerKefu Chai <kchai@redhat.com>
Sat, 3 Aug 2019 03:27:20 +0000 (11:27 +0800)
Signed-off-by: Kefu Chai <kchai@redhat.com>
fusetrace/fusetrace_ll.cc

index 4c8eb0d2fd55b1bcaa8c849831cc52c5e4e488b7..b411a83fe20381b04ba5f012d01e73a02064f705 100644 (file)
@@ -54,9 +54,9 @@ CEPH_HASH_NAMESPACE_END
 #include <set>
 using namespace std;
 
-#include "common/Mutex.h"
+#include "common/ceph_mutex.h"
 
-Mutex trace_lock;
+ceph::mutex trace_lock;
 ofstream tracefile;
 
 #define traceout (tracefile.is_open() ? tracefile : cout)
@@ -67,7 +67,7 @@ bool do_timestamps = true;
 
 #define dout if (debug) cout
 
-Mutex lock;
+ceph::mutex lock;
 
 struct Inode {
     struct stat stbuf;
@@ -247,7 +247,7 @@ static void ft_ll_lookup(fuse_req_t req, fuse_ino_t pino, const char *name)
     struct fuse_entry_param fe;
     memset(&fe, 0, sizeof(fe));
 
-    lock.Lock();
+    lock.lock();
     Inode *parent = inode_map[pino];
     assert(parent);
 
@@ -294,12 +294,12 @@ static void ft_ll_lookup(fuse_req_t req, fuse_ino_t pino, const char *name)
            memcpy(&fe.attr, &in->stbuf, sizeof(in->stbuf));
        }
     }
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_lookup" << endl << pino << endl << name << endl << fe.attr.st_ino << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (in) 
        fuse_reply_entry(req, &fe);
@@ -310,7 +310,7 @@ static void ft_ll_lookup(fuse_req_t req, fuse_ino_t pino, const char *name)
 static void ft_ll_forget(fuse_req_t req, fuse_ino_t ino, long unsigned nlookup)
 {
     if (ino != 1) {
-       lock.Lock();
+       std::scoped_lock l{lock};
        Inode *in = inode_map[ino];
        if (in) {
            dout << "forget on " << ino << " ref " << in->ref << ", forget " << nlookup << endl;
@@ -323,13 +323,13 @@ static void ft_ll_forget(fuse_req_t req, fuse_ino_t ino, long unsigned nlookup)
        } else {
            dout << "**** BAD **** forget " << nlookup << " on nonexistent inode " << ino << endl;
        }
-       lock.Unlock();
     }
 
-    trace_lock.Lock();
-    print_time();
-    traceout << "ll_forget" << endl << ino << endl << nlookup << endl;
-    trace_lock.Unlock();
+    {
+       std::scoped_lock l{trace_lock};
+       print_time();
+       traceout << "ll_forget" << endl << ino << endl << nlookup << endl;
+    }
 
     fuse_reply_none(req);
 }
@@ -343,14 +343,14 @@ static void ft_ll_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
     Inode *in = 0;
     struct stat attr;
 
-    lock.Lock();
+    lock.lock();
     in = inode_map[ino];
     if (in->fds.empty()) {
        if (!make_inode_path(path, in))
            res = ENOENT;
     } else
        fd = *in->fds.begin();
-    lock.Unlock();
+    lock.unlock();
 
     if (fd > 0) {
        res = ::fstat(fd, &attr);
@@ -362,15 +362,15 @@ static void ft_ll_getattr(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
     if (res < 0) res = errno;
     if (ino == 1) attr.st_ino = 1;
     
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_getattr" << endl << ino << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0) {
-       lock.Lock();
+       lock.lock();
        memcpy(&in->stbuf, &attr, sizeof(attr));
-       lock.Unlock();
+       lock.unlock();
        fuse_reply_attr(req, &attr, 0);
     } else 
        fuse_reply_err(req, res);
@@ -384,16 +384,16 @@ static void ft_ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
     int fd = 0;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     in = inode_map[ino];
     if (in->fds.empty() || (to_set & FUSE_SET_ATTR_MTIME)) {
        if (!make_inode_path(path, in))
            res = ENOENT;
     } else
        fd = *in->fds.begin();
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_setattr" << endl << ino << endl;
     traceout << attr->st_mode << endl;
@@ -402,7 +402,7 @@ static void ft_ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
     traceout << attr->st_mtime << endl;
     traceout << attr->st_atime << endl;
     traceout << to_set << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0 && !has_perm(0010, in, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) {
        res = EPERM;
@@ -435,11 +435,11 @@ static void ft_ll_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
     }
 
     if (res == 0) {
-       lock.Lock();
+       lock.lock();
        ::lstat(path.c_str(), &in->stbuf);
        if (ino == 1) in->stbuf.st_ino = 1;
        memcpy(attr, &in->stbuf, sizeof(*attr));
-       lock.Unlock();
+       lock.unlock();
        fuse_reply_attr(req, attr, 0);
     } else
        fuse_reply_err(req, res);    
@@ -451,15 +451,15 @@ static void ft_ll_readlink(fuse_req_t req, fuse_ino_t ino)
     string path;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     if (!make_ino_path(path, ino))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_readlink" << endl << ino << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     char buf[256];
     if (res == 0) res = readlink(path.c_str(), buf, 255);
@@ -478,11 +478,11 @@ static void ft_ll_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
 {
     string path;
     int res = 0;
-    lock.Lock();
+    lock.lock();
     Inode *in = inode_map[ino];
     if (!make_inode_path(path, in))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
     DIR *dir = 0;
     if (res == 0 && !has_perm(0100, in, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
@@ -490,10 +490,10 @@ static void ft_ll_opendir(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
     else if (res == 0) dir = opendir(path.c_str());
     if (res < 0) res = errno;
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_opendir" << endl << ino << endl << (unsigned long)dir << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
     
     if (dir) {
        fi->fh = (long)dir;
@@ -541,10 +541,10 @@ static void ft_ll_releasedir(fuse_req_t req, fuse_ino_t ino,
 {
     DIR *dir = (DIR*)fi->fh;
     
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_releasedir" << endl << (unsigned long)dir << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
     
     closedir(dir);
     fuse_reply_err(req, 0);
@@ -558,11 +558,11 @@ static void ft_ll_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
     string path;
     Inode *pin = 0;
     int res = 0;
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
     dout << "mknod " << path << endl;
     if (res == 0 && !has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
@@ -578,17 +578,17 @@ static void ft_ll_mknod(fuse_req_t req, fuse_ino_t parent, const char *name,
        memset(&fe, 0, sizeof(fe));
        ::lstat(path.c_str(), &fe.attr);
        fe.ino = fe.attr.st_ino;
-       lock.Lock();
+       lock.lock();
        Inode *in = add_inode(pin, name, &fe.attr);
        in->ref++;
-       lock.Unlock();
+       lock.unlock();
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_mknod" << endl << parent << endl << name << endl << mode << endl << rdev << endl;
     traceout << (res == 0 ? fe.ino:0) << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0)
        fuse_reply_entry(req, &fe);
@@ -602,11 +602,11 @@ static void ft_ll_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
     string path;
     Inode *pin = 0;
     int res = 0;
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
     if (res == 0 && !has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
        res = EPERM;
@@ -621,17 +621,17 @@ static void ft_ll_mkdir(fuse_req_t req, fuse_ino_t parent, const char *name,
        memset(&fe, 0, sizeof(fe));
        ::lstat(path.c_str(), &fe.attr);
        fe.ino = fe.attr.st_ino;
-       lock.Lock();
+       lock.lock();
        Inode *in = add_inode(pin, name, &fe.attr);
        in->ref++;
-       lock.Unlock();
+       lock.unlock();
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_mkdir" << endl << parent << endl << name << endl << mode << endl;
     traceout << (res == 0 ? fe.ino:0) << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0)
        fuse_reply_entry(req, &fe);
@@ -645,11 +645,11 @@ static void ft_ll_symlink(fuse_req_t req, const char *value, fuse_ino_t parent,
     Inode *pin = 0;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
     if (res == 0 && !has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
        res = EPERM;
@@ -664,17 +664,17 @@ static void ft_ll_symlink(fuse_req_t req, const char *value, fuse_ino_t parent,
        memset(&fe, 0, sizeof(fe));
        ::lstat(path.c_str(), &fe.attr);
        fe.ino = fe.attr.st_ino;
-       lock.Lock();
+       lock.lock();
        Inode *in = add_inode(pin, name, &fe.attr);
        in->ref++;
-       lock.Unlock();
+       lock.unlock();
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_symlink" << endl << parent << endl << name << endl << value << endl;
     traceout << (res == 0 ? fe.ino:0) << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0)
        fuse_reply_entry(req, &fe);
@@ -689,11 +689,11 @@ static void ft_ll_create(fuse_req_t req, fuse_ino_t parent, const char *name,
     Inode *pin = 0;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
     dout << "create " << path << endl;
     int fd = 0;
@@ -713,15 +713,15 @@ static void ft_ll_create(fuse_req_t req, fuse_ino_t parent, const char *name,
     if (res == 0) {
        ::lstat(path.c_str(), &fe.attr);
        fe.ino = fe.attr.st_ino;
-       lock.Lock();
+       lock.lock();
        Inode *in = add_inode(pin, name, &fe.attr);
        in->ref++;
        in->fds.insert(fd);
-       lock.Unlock();
+       lock.unlock();
        fi->fh = fd;
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_create" << endl
             << parent << endl
@@ -730,7 +730,7 @@ static void ft_ll_create(fuse_req_t req, fuse_ino_t parent, const char *name,
             << fi->flags << endl
             << (res == 0 ? fd:0) << endl
             << fe.ino << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0)
        fuse_reply_create(req, &fe, fi);
@@ -745,18 +745,18 @@ static void ft_ll_statfs(fuse_req_t req, fuse_ino_t ino)
     string path;
     int res = 0;
     if (ino) {
-       lock.Lock();
+       lock.lock();
        if (!make_ino_path(path, ino))
            res = ENOENT;
-       lock.Unlock();
+       lock.unlock();
     } else {
        path = basedir;
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_statfs" << endl << ino << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
     
     struct statvfs stbuf;
     if (res == 0) res = statvfs(path.c_str(), &stbuf);
@@ -775,17 +775,17 @@ static void ft_ll_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
     Inode *in = 0;
     string dname(name);
     int res = 0;
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     in = pin->lookup(dname);
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_unlink" << endl << parent << endl << name << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
     
     if (res == 0 && !has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
        res = EPERM;
@@ -802,11 +802,11 @@ static void ft_ll_unlink(fuse_req_t req, fuse_ino_t parent, const char *name)
 
     if (res == 0) {
        // remove from out cache
-       lock.Lock();
+       lock.lock();
        string dname(name);
        if (pin->lookup(dname))
            remove_dentry(pin, dname);
-       lock.Unlock();
+       lock.unlock();
        fuse_reply_err(req, 0);
     } else
        fuse_reply_err(req, res);
@@ -818,16 +818,16 @@ static void ft_ll_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
     Inode *pin = 0;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_rmdir" << endl << parent << endl << name << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0 && !has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)) 
        res = EPERM;
@@ -836,11 +836,11 @@ static void ft_ll_rmdir(fuse_req_t req, fuse_ino_t parent, const char *name)
 
     if (res == 0) {
        // remove from out cache
-       lock.Lock();
+       lock.lock();
        string dname(name);
        if (pin->lookup(dname))
            remove_dentry(pin, dname);
-       lock.Unlock();
+       lock.unlock();
        fuse_reply_err(req, 0);
     } else
        fuse_reply_err(req, res);
@@ -855,23 +855,23 @@ static void ft_ll_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
     Inode *pin = 0;
     Inode *newpin = 0;
     int res = 0;
-    lock.Lock();
+    lock.lock();
     pin = inode_map[parent];
     if (!make_inode_path(path, pin, name))
        res = ENOENT;
     newpin = inode_map[newparent];
     if (!make_inode_path(newpath, newpin, newname))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_rename" << endl
             << parent << endl 
             << name << endl
             << newparent << endl
             << newname << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0 && (!has_perm(0010, pin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid) ||
                     !has_perm(0010, newpin, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid)))
@@ -882,7 +882,7 @@ static void ft_ll_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
     if (res == 0) {
        string dname(name);
        string newdname(newname);
-       lock.Lock();
+       lock.lock();
        Inode *in = pin->lookup(dname);
        if (in) {
            add_dentry(newpin, newdname, in);
@@ -890,7 +890,7 @@ static void ft_ll_rename(fuse_req_t req, fuse_ino_t parent, const char *name,
        } else {
            dout << "hrm, rename didn't have renamed inode.. " << path << " to " << newpath << endl;
        }
-       lock.Unlock();
+       lock.unlock();
        fuse_reply_err(req, 0);
     } else 
        fuse_reply_err(req, res);
@@ -904,7 +904,7 @@ static void ft_ll_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
     Inode *in = 0;
     Inode *newpin = 0;
     int res = 0;
-    lock.Lock();
+    lock.lock();
     in = inode_map[ino];
     if (!make_inode_path(path, in))
        res = ENOENT;
@@ -912,15 +912,15 @@ static void ft_ll_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
     newpin = inode_map[newparent];
     if (!make_inode_path(newpath, newpin, newname))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_link" << endl
             << ino << endl
             << newparent << endl
             << newname << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
     
     //cout << "link " << path << " newpath " << newpath << endl;
     if (res == 0 && (!has_perm(0010, in, fuse_req_ctx(req)->uid, fuse_req_ctx(req)->gid) ||
@@ -934,12 +934,12 @@ static void ft_ll_link(fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
        memset(&fe, 0, sizeof(fe));
        ::lstat(newpath.c_str(), &fe.attr);
 
-       lock.Lock();
+       lock.lock();
        string newdname(newname);
        add_dentry(newpin, newdname, in);
        in->ref++;
        memcpy(&in->stbuf, &fe.attr, sizeof(fe.attr));   // re-read, bc we changed the link count
-       lock.Unlock();
+       lock.unlock();
 
        fe.ino = fe.attr.st_ino;
        fuse_reply_entry(req, &fe);
@@ -953,11 +953,11 @@ static void ft_ll_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi
     Inode *in = 0;
     int res = 0;
 
-    lock.Lock();
+    lock.lock();
     in = inode_map[ino];
     if (!make_inode_path(path, in))
        res = ENOENT;
-    lock.Unlock();
+    lock.unlock();
     
     int want = 0100;
     if (fi->flags & O_RDWR) want |= 0010;
@@ -971,18 +971,18 @@ static void ft_ll_open(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi
        if (fd <= 0) res = errno;
     }
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_open" << endl
             << ino << endl
             << fi->flags << endl
             << (fd > 0 ? fd:0) << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res == 0) {
-       lock.Lock();
+       lock.lock();
        in->fds.insert(fd);
-       lock.Unlock();
+       lock.unlock();
        fi->fh = fd;
        fuse_reply_open(req, fi);
     } else
@@ -997,13 +997,13 @@ static void ft_ll_read(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
     int res = ::pread(fi->fh, buf, size, off);
 
     //cout << "read " << path << " " << off << "~" << size << endl;
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_read" << endl 
             << fi->fh << endl
             << off << endl
             << size << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res >= 0) 
        fuse_reply_buf(req, buf, res);
@@ -1017,13 +1017,13 @@ static void ft_ll_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
 {
     int res = ::pwrite(fi->fh, buf, size, off);
 
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_write" << endl
             << fi->fh << endl
             << off << endl
             << size << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     if (res >= 0) 
        fuse_reply_write(req, res);
@@ -1033,10 +1033,10 @@ static void ft_ll_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
 
 static void ft_ll_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 {
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_flush" << endl << fi->fh << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     int res = ::fdatasync(fi->fh);
     //int res = ::close(dup(fi->fh));
@@ -1048,15 +1048,15 @@ static void ft_ll_flush(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *f
 
 static void ft_ll_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi)
 {
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_release" << endl << fi->fh << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
-    lock.Lock();
+    lock.lock();
     Inode *in = inode_map[ino];
     in->fds.erase(fi->fh);
-    lock.Unlock();
+    lock.unlock();
 
     int res = ::close(fi->fh);
     if (res >= 0)
@@ -1068,10 +1068,10 @@ static void ft_ll_release(fuse_req_t req, fuse_ino_t ino, struct fuse_file_info
 static void ft_ll_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
                          struct fuse_file_info *fi)
 {
-    trace_lock.Lock();
+    trace_lock.lock();
     print_time();
     traceout << "ll_fsync" << endl << fi->fh << endl;
-    trace_lock.Unlock();
+    trace_lock.unlock();
 
     int res = ::fsync(fi->fh);
     if (res >= 0)