more kernel interface changes
authorMiklos Szeredi <miklos@szeredi.hu>
Fri, 20 Feb 2004 14:10:49 +0000 (14:10 +0000)
committerMiklos Szeredi <miklos@szeredi.hu>
Fri, 20 Feb 2004 14:10:49 +0000 (14:10 +0000)
ChangeLog
include/linux/fuse.h
kernel/dir.c
lib/fuse.c

index cdc25791795eaeb7399cb6e7adf63d4c374dbf65..cd1da1d2ce9756cb0436a43821773c30b2f8c730 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2004-02-20  Miklos Szeredi <mszeredi@inf.bme.hu>
+
+       * more kernel interface changes:
+
+       * added nanosecond precision to file times
+
 2004-02-19  Miklos Szeredi <mszeredi@inf.bme.hu>
 
        * statfs library API changed to match other methods.  Since this
index 9bca31c7a5ba717b1b05d75e2f522c84943a2d4a..10ef1864f3f91c34bd3dbf9257cf8f7467752b80 100644 (file)
@@ -66,11 +66,13 @@ struct fuse_attr {
        unsigned int        gid;
        unsigned int        rdev;
        unsigned long long  size;
-       unsigned long       _dummy;
        unsigned long       blocks;
        unsigned long       atime;
+       unsigned long       atimensec;
        unsigned long       mtime;
+       unsigned long       mtimensec;
        unsigned long       ctime;
+       unsigned long       ctimensec;
 };
 
 struct fuse_kstatfs {
@@ -87,7 +89,9 @@ struct fuse_kstatfs {
 #define FATTR_UID      (1 << 1)
 #define FATTR_GID      (1 << 2)
 #define FATTR_SIZE     (1 << 3)
-#define FATTR_UTIME    (1 << 4)
+#define FATTR_ATIME    (1 << 4)
+#define FATTR_MTIME    (1 << 5)
+#define FATTR_CTIME    (1 << 6)
 
 enum fuse_opcode {
        FUSE_LOOKUP     = 1,
index b9c26e60ebb84c38d597789ead3e8013557244b9..c5810e97aa2d624f8677f153336f355424cba804 100644 (file)
@@ -47,11 +47,11 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
        inode->i_blocks  = attr->blocks;
 #ifdef KERNEL_2_6
        inode->i_atime.tv_sec   = attr->atime;
-       inode->i_atime.tv_nsec  = 0;
+       inode->i_atime.tv_nsec  = attr->atimensec;
        inode->i_mtime.tv_sec   = attr->mtime;
-       inode->i_mtime.tv_nsec  = 0;
+       inode->i_mtime.tv_nsec  = attr->mtimensec;
        inode->i_ctime.tv_sec   = attr->ctime;
-       inode->i_ctime.tv_nsec  = 0;
+       inode->i_ctime.tv_nsec  = attr->ctimensec;
 #else
        inode->i_atime   = attr->atime;
        inode->i_mtime   = attr->mtime;
@@ -261,43 +261,46 @@ static int fuse_symlink(struct inode *dir, struct dentry *entry,
        return lookup_new_entry(dir, entry, &outarg, out.h.unique, S_IFLNK);
 }
 
-static int fuse_remove(struct inode *dir, struct dentry *entry, 
-                      enum fuse_opcode op)
+static int fuse_unlink(struct inode *dir, struct dentry *entry)
 {
        struct fuse_conn *fc = INO_FC(dir);
        struct fuse_in in = FUSE_IN_INIT;
        struct fuse_out out = FUSE_OUT_INIT;
 
-       in.h.opcode = op;
+       in.h.opcode = FUSE_UNLINK;
        in.h.ino = dir->i_ino;
        in.numargs = 1;
        in.args[0].size = entry->d_name.len + 1;
        in.args[0].value = entry->d_name.name;
        request_send(fc, &in, &out);
 
-       return out.h.error;
-}
-
-static int fuse_unlink(struct inode *dir, struct dentry *entry)
-{
-       int err = fuse_remove(dir, entry, FUSE_UNLINK);
-       if(!err) {
-               /* FIXME: the new i_nlink could be returned by the
-                   unlink operation */
-               err = fuse_do_getattr(entry->d_inode);
-               if(err == -ENOENT)
-                       entry->d_inode->i_nlink = 0;
-               return 0;
+       if(!out.h.error) {
+               /* Set nlink to zero so the inode can be cleared, if
+                   the inode does have more links this will be
+                   discovered at the next lookup/getattr */
+               /* FIXME: mark inode "not uptodate" */
+               entry->d_inode->i_nlink = 0;
        }
-       return err;
+
+       return out.h.error;
 }
 
 static int fuse_rmdir(struct inode *dir, struct dentry *entry)
 {
-       int err = fuse_remove(dir, entry, FUSE_RMDIR);
-       if(!err)
+       struct fuse_conn *fc = INO_FC(dir);
+       struct fuse_in in = FUSE_IN_INIT;
+       struct fuse_out out = FUSE_OUT_INIT;
+
+       in.h.opcode = FUSE_RMDIR;
+       in.h.ino = dir->i_ino;
+       in.numargs = 1;
+       in.args[0].size = entry->d_name.len + 1;
+       in.args[0].value = entry->d_name.name;
+       request_send(fc, &in, &out);
+       if(!out.h.error)
                entry->d_inode->i_nlink = 0;
-       return err;
+
+       return out.h.error;
 }
 
 static int fuse_rename(struct inode *olddir, struct dentry *oldent,
@@ -594,7 +597,7 @@ static unsigned int iattr_to_fattr(struct iattr *iattr,
                fvalid |= FATTR_SIZE,   fattr->size = iattr->ia_size;
        /* You can only _set_ these together (they may change by themselves) */
        if((ivalid & (ATTR_ATIME | ATTR_MTIME)) == (ATTR_ATIME | ATTR_MTIME)) {
-               fvalid |= FATTR_UTIME;
+               fvalid |= FATTR_ATIME | FATTR_MTIME;
 #ifdef KERNEL_2_6
                fattr->atime = iattr->ia_atime.tv_sec;
                fattr->mtime = iattr->ia_mtime.tv_sec;
index 079220a0eafa2837ffd2b623c7eb04d3ad488c8d..2e6950d7c1a98ca77cad53012d430e078751b959 100644 (file)
@@ -315,17 +315,19 @@ static void rename_node(struct fuse *f, fino_t olddir, const char *oldname,
 
 static void convert_stat(struct stat *stbuf, struct fuse_attr *attr)
 {
-    attr->mode    = stbuf->st_mode;
-    attr->nlink   = stbuf->st_nlink;
-    attr->uid     = stbuf->st_uid;
-    attr->gid     = stbuf->st_gid;
-    attr->rdev    = stbuf->st_rdev;
-    attr->size    = stbuf->st_size;
-    attr->blocks  = stbuf->st_blocks;
-    attr->atime   = stbuf->st_atime;
-    attr->mtime   = stbuf->st_mtime;
-    attr->ctime   = stbuf->st_ctime;
-    attr->_dummy  = 4096;
+    attr->mode      = stbuf->st_mode;
+    attr->nlink     = stbuf->st_nlink;
+    attr->uid       = stbuf->st_uid;
+    attr->gid       = stbuf->st_gid;
+    attr->rdev      = stbuf->st_rdev;
+    attr->size      = stbuf->st_size;
+    attr->blocks    = stbuf->st_blocks;
+    attr->atime     = stbuf->st_atime;
+    attr->atimensec = stbuf->st_atim.tv_nsec;
+    attr->mtime     = stbuf->st_mtime;
+    attr->mtimensec = stbuf->st_mtim.tv_nsec;
+    attr->ctime     = stbuf->st_ctime;
+    attr->ctimensec = stbuf->st_ctim.tv_nsec;
 }
 
 static int fill_dir(struct fuse_dirhandle *dh, char *name, int type)
@@ -553,7 +555,8 @@ static void do_setattr(struct fuse *f, struct fuse_in_header *in,
                 res = do_chown(f, path, attr, valid);
             if(!res && (valid & FATTR_SIZE))
                 res = do_truncate(f, path, attr);
-            if(!res && (valid & FATTR_UTIME))
+            if(!res && (valid & (FATTR_ATIME | FATTR_MTIME)) == 
+               (FATTR_ATIME | FATTR_MTIME))
                 res = do_utime(f, path, attr);
             if(!res) {
                 struct stat buf;
@@ -665,7 +668,7 @@ static void do_mkdir(struct fuse *f, struct fuse_in_header *in,
     send_reply(f, in, res, &outarg, sizeof(outarg));
 }
 
-static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
+static void do_unlink(struct fuse *f, struct fuse_in_header *in, char *name)
 {
     int res;
     char *path;
@@ -674,18 +677,32 @@ static void do_remove(struct fuse *f, struct fuse_in_header *in, char *name)
     path = get_path_name(f, in->ino, name);
     if(path != NULL) {
         res = -ENOSYS;
-        if(in->opcode == FUSE_UNLINK) {
-            if(f->op.unlink)
-                res = f->op.unlink(path);
+        if(f->op.unlink) {
+            res = f->op.unlink(path);
+            if(res == 0)
+                remove_node(f, in->ino, name);
         }
-        else {
-            if(f->op.rmdir)
-                res = f->op.rmdir(path);
+        free(path);
+    }
+    send_reply(f, in, res, NULL, 0);
+}
+
+static void do_rmdir(struct fuse *f, struct fuse_in_header *in, char *name)
+{
+    int res;
+    char *path;
+
+    res = -ENOENT;
+    path = get_path_name(f, in->ino, name);
+    if(path != NULL) {
+        res = -ENOSYS;
+        if(f->op.rmdir) {
+            res = f->op.rmdir(path);
+            if(res == 0)
+                remove_node(f, in->ino, name);
         }
         free(path);
     }
-    if(res == 0)
-        remove_node(f, in->ino, name);
     send_reply(f, in, res, NULL, 0);
 }
 
@@ -990,8 +1007,11 @@ void __fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
         break;
             
     case FUSE_UNLINK:
+        do_unlink(f, in, (char *) inarg);
+        break;
+
     case FUSE_RMDIR:
-        do_remove(f, in, (char *) inarg);
+        do_rmdir(f, in, (char *) inarg);
         break;
 
     case FUSE_SYMLINK: