aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/dir.c
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2001-11-06 12:03:23 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2001-11-06 12:03:23 +0000
commita181e61ca0119b8c3fd2daa4b8d23add2cda3ed0 (patch)
tree57176d5ca8f96008180eac92518791ef22add726 /kernel/dir.c
parent5e183482b09cec20f54ccb44e767a7fab51833e9 (diff)
downloadlibfuse-a181e61ca0119b8c3fd2daa4b8d23add2cda3ed0.tar.gz
bugfixes
Diffstat (limited to 'kernel/dir.c')
-rw-r--r--kernel/dir.c79
1 files changed, 48 insertions, 31 deletions
diff --git a/kernel/dir.c b/kernel/dir.c
index 1dac0c8..f506816 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -16,7 +16,6 @@
static struct inode_operations fuse_dir_inode_operations;
static struct inode_operations fuse_file_inode_operations;
static struct inode_operations fuse_symlink_inode_operations;
-static struct inode_operations fuse_special_inode_operations;
static struct file_operations fuse_dir_operations;
@@ -24,6 +23,9 @@ static struct dentry_operations fuse_dentry_opertations;
static void change_attributes(struct inode *inode, struct fuse_attr *attr)
{
+ if(S_ISREG(inode->i_mode) && inode->i_size != attr->size)
+ invalidate_inode_pages(inode);
+
inode->i_mode = (inode->i_mode & S_IFMT) + (attr->mode & 07777);
inode->i_nlink = attr->nlink;
inode->i_uid = attr->uid;
@@ -36,9 +38,10 @@ static void change_attributes(struct inode *inode, struct fuse_attr *attr)
inode->i_ctime = attr->ctime;
}
-static void fuse_init_inode(struct inode *inode, int mode, int rdev)
+static void fuse_init_inode(struct inode *inode, struct fuse_attr *attr)
{
- inode->i_mode = mode & S_IFMT;
+ inode->i_mode = attr->mode & S_IFMT;
+ inode->i_size = attr->size;
if(S_ISREG(inode->i_mode)) {
inode->i_op = &fuse_file_inode_operations;
fuse_init_file_inode(inode);
@@ -51,23 +54,24 @@ static void fuse_init_inode(struct inode *inode, int mode, int rdev)
inode->i_op = &fuse_symlink_inode_operations;
}
else {
- inode->i_op = &fuse_special_inode_operations;
- init_special_inode(inode, inode->i_mode, rdev);
+ inode->i_op = &fuse_file_inode_operations;
+ init_special_inode(inode, inode->i_mode, attr->rdev);
}
inode->u.generic_ip = inode;
}
struct inode *fuse_iget(struct super_block *sb, ino_t ino,
- struct fuse_attr *attr)
+ struct fuse_attr *attr, int version)
{
struct inode *inode;
inode = iget(sb, ino);
if(inode) {
if(!inode->u.generic_ip)
- fuse_init_inode(inode, attr->mode, attr->rdev);
+ fuse_init_inode(inode, attr);
change_attributes(inode, attr);
+ inode->i_version = version;
}
return inode;
@@ -75,12 +79,13 @@ struct inode *fuse_iget(struct super_block *sb, ino_t ino,
static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
{
+ int ret;
struct fuse_conn *fc = INO_FC(dir);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
struct fuse_lookup_out arg;
struct inode *inode;
-
+
in.h.opcode = FUSE_LOOKUP;
in.h.ino = dir->i_ino;
in.argsize = entry->d_name.len + 1;
@@ -91,16 +96,24 @@ static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry)
inode = NULL;
if(!out.h.error) {
- inode = fuse_iget(dir->i_sb, arg.ino, &arg.attr);
+ ret = -ENOMEM;
+ inode = fuse_iget(dir->i_sb, arg.ino, &arg.attr, out.h.unique);
if(!inode)
- return ERR_PTR(-ENOMEM);
+ goto err;
+ }
+ else if(out.h.error != -ENOENT) {
+ ret = out.h.error;
+ goto err;
}
- else if(out.h.error != -ENOENT)
- return ERR_PTR(out.h.error);
+ entry->d_time = jiffies;
entry->d_op = &fuse_dentry_opertations;
d_add(entry, inode);
+
return NULL;
+
+ err:
+ return ERR_PTR(ret);
}
/* create needs to return a positive entry, so this also does a lookup */
@@ -136,12 +149,11 @@ static int fuse_mknod(struct inode *dir, struct dentry *entry, int mode,
if(out.h.error)
return out.h.error;
- inode = fuse_iget(dir->i_sb, outarg.ino, &outarg.attr);
+ inode = fuse_iget(dir->i_sb, outarg.ino, &outarg.attr, out.h.unique);
if(!inode)
return -ENOMEM;
d_instantiate(entry, inode);
-
return 0;
}
@@ -293,17 +305,16 @@ static int fuse_permission(struct inode *inode, int mask)
return 0;
}
-/* Only revalidate the root inode, since lookup is always redone on
- the last path segment, and lookup refreshes the attributes */
-static int fuse_revalidate(struct dentry *dentry)
+static int fuse_revalidate(struct dentry *entry)
{
- struct inode *inode = dentry->d_inode;
+ struct inode *inode = entry->d_inode;
struct fuse_conn *fc = INO_FC(inode);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
struct fuse_getattr_out arg;
- if(inode->i_ino != FUSE_ROOT_INO)
+ if(inode->i_ino != FUSE_ROOT_INO &&
+ time_before_eq(jiffies, entry->d_time + HZ / 100))
return 0;
in.h.opcode = FUSE_GETATTR;
@@ -435,7 +446,7 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
struct fuse_getdir_out outarg;
if(!(file->f_flags & O_DIRECTORY))
- return -EISDIR;
+ return 0;
in.h.opcode = FUSE_GETDIR;
in.h.ino = inode->i_ino;
@@ -465,7 +476,9 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
static int fuse_dir_release(struct inode *inode, struct file *file)
{
struct file *cfile = file->private_data;
- fput(cfile);
+
+ if(cfile)
+ fput(cfile);
return 0;
}
@@ -502,16 +515,26 @@ static int fuse_setattr(struct dentry *entry, struct iattr *attr)
struct fuse_conn *fc = INO_FC(inode);
struct fuse_in in = FUSE_IN_INIT;
struct fuse_out out = FUSE_OUT_INIT;
- struct fuse_setattr_in arg;
+ struct fuse_setattr_in inarg;
+ struct fuse_setattr_out outarg;
- arg.valid = iattr_to_fattr(attr, &arg.attr);
+ inarg.valid = iattr_to_fattr(attr, &inarg.attr);
in.h.opcode = FUSE_SETATTR;
in.h.ino = inode->i_ino;
- in.argsize = sizeof(arg);
- in.arg = &arg;
+ in.argsize = sizeof(inarg);
+ in.arg = &inarg;
+ out.argsize = sizeof(outarg);
+ out.arg = &outarg;
request_send(fc, &in, &out);
+ if(!out.h.error && (attr->ia_valid & ATTR_SIZE)) {
+ if(outarg.newsize > attr->ia_size)
+ outarg.newsize = attr->ia_size;
+
+ vmtruncate(inode, outarg.newsize);
+ }
+
return out.h.error;
}
@@ -552,12 +575,6 @@ static struct inode_operations fuse_file_inode_operations = {
revalidate: fuse_revalidate,
};
-static struct inode_operations fuse_special_inode_operations = {
- setattr: fuse_setattr,
- permission: fuse_permission,
- revalidate: fuse_revalidate,
-};
-
static struct inode_operations fuse_symlink_inode_operations =
{
setattr: fuse_setattr,