* [PATCH 0/7] fuse updates
@ 2005-11-28 19:41 Miklos Szeredi
2005-11-28 19:43 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:41 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Hi Andrew!
Patches 1 and 2 are bugfixes, and should go into 2.6.15.
The others are cleanups and new features, which can wait for 2.6.16.
Thanks,
Miklos
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/7] fuse: check directory aliasing in mkdir
2005-11-28 19:41 [PATCH 0/7] fuse updates Miklos Szeredi
@ 2005-11-28 19:43 ` Miklos Szeredi
2005-11-28 19:45 ` [PATCH 2/7] fuse: check for invalid node ID in fuse_create_open() Miklos Szeredi
2005-11-28 19:57 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Trond Myklebust
0 siblings, 2 replies; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:43 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Check the created directory inode for aliases in the mkdir() method.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2005-11-28 14:01:08.000000000 +0100
+++ linux/fs/fuse/dir.c 2005-11-28 14:01:52.000000000 +0100
@@ -74,6 +74,19 @@ static int fuse_dentry_revalidate(struct
return 1;
}
+static int dir_alias(struct inode *inode)
+{
+ if (S_ISDIR(inode->i_mode)) {
+ /* Don't allow creating an alias to a directory */
+ struct dentry *alias = d_find_alias(inode);
+ if (alias) {
+ dput(alias);
+ return 1;
+ }
+ }
+ return 0;
+}
+
static struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
@@ -263,7 +276,7 @@ static int create_new_entry(struct fuse_
fuse_put_request(fc, req);
/* Don't allow userspace to do really stupid things... */
- if ((inode->i_mode ^ mode) & S_IFMT) {
+ if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) {
iput(inode);
return -EIO;
}
@@ -874,14 +887,9 @@ static struct dentry *fuse_lookup(struct
err = fuse_lookup_iget(dir, entry, &inode);
if (err)
return ERR_PTR(err);
- if (inode && S_ISDIR(inode->i_mode)) {
- /* Don't allow creating an alias to a directory */
- struct dentry *alias = d_find_alias(inode);
- if (alias) {
- dput(alias);
- iput(inode);
- return ERR_PTR(-EIO);
- }
+ if (inode && dir_alias(inode)) {
+ iput(inode);
+ return ERR_PTR(-EIO);
}
d_add(entry, inode);
return NULL;
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 2/7] fuse: check for invalid node ID in fuse_create_open()
2005-11-28 19:43 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Miklos Szeredi
@ 2005-11-28 19:45 ` Miklos Szeredi
2005-11-28 19:46 ` [PATCH 3/7] fuse: clean up fuse_lookup() Miklos Szeredi
2005-11-28 19:57 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Trond Myklebust
1 sibling, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:45 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Check for invalid node ID values in the new atomic create+open method.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2005-11-28 17:24:22.000000000 +0100
+++ linux/fs/fuse/dir.c 2005-11-28 17:24:26.000000000 +0100
@@ -87,6 +87,11 @@ static int dir_alias(struct inode *inode
return 0;
}
+static inline int invalid_nodeid(u64 nodeid)
+{
+ return !nodeid || nodeid == FUSE_ROOT_ID;
+}
+
static struct dentry_operations fuse_dentry_operations = {
.d_revalidate = fuse_dentry_revalidate,
};
@@ -110,7 +115,7 @@ static int fuse_lookup_iget(struct inode
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
err = req->out.h.error;
- if (!err && (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID))
+ if (!err && invalid_nodeid(outarg.nodeid))
err = -EIO;
if (!err) {
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
@@ -206,7 +211,7 @@ static int fuse_create_open(struct inode
}
err = -EIO;
- if (!S_ISREG(outentry.attr.mode))
+ if (!S_ISREG(outentry.attr.mode) || invalid_nodeid(outentry.nodeid))
goto out_free_ff;
inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
@@ -263,7 +268,7 @@ static int create_new_entry(struct fuse_
fuse_put_request(fc, req);
return err;
}
- if (!outarg.nodeid || outarg.nodeid == FUSE_ROOT_ID) {
+ if (invalid_nodeid(outarg.nodeid)) {
fuse_put_request(fc, req);
return -EIO;
}
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 3/7] fuse: clean up fuse_lookup()
2005-11-28 19:45 ` [PATCH 2/7] fuse: check for invalid node ID in fuse_create_open() Miklos Szeredi
@ 2005-11-28 19:46 ` Miklos Szeredi
2005-11-28 19:47 ` [PATCH 4/7] fuse: clean up page offset calculation Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:46 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Simplify fuse_lookup() and related functions.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2005-11-28 17:24:26.000000000 +0100
+++ linux/fs/fuse/dir.c 2005-11-28 17:26:51.000000000 +0100
@@ -13,7 +13,6 @@
#include <linux/gfp.h>
#include <linux/sched.h>
#include <linux/namei.h>
-#include <linux/mount.h>
static inline unsigned long time_to_jiffies(unsigned long sec,
unsigned long nsec)
@@ -22,6 +21,13 @@ static inline unsigned long time_to_jiff
return jiffies + timespec_to_jiffies(&ts);
}
+static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
+{
+ struct fuse_inode *fi = get_fuse_inode(entry->d_inode);
+ entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
+ fi->i_time = time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+}
+
static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
struct dentry *entry,
struct fuse_entry_out *outarg)
@@ -66,10 +72,7 @@ static int fuse_dentry_revalidate(struct
return 0;
fuse_change_attributes(inode, &outarg.attr);
- entry->d_time = time_to_jiffies(outarg.entry_valid,
- outarg.entry_valid_nsec);
- fi->i_time = time_to_jiffies(outarg.attr_valid,
- outarg.attr_valid_nsec);
+ fuse_change_timeout(entry, &outarg);
}
return 1;
}
@@ -96,8 +99,8 @@ static struct dentry_operations fuse_den
.d_revalidate = fuse_dentry_revalidate,
};
-static int fuse_lookup_iget(struct inode *dir, struct dentry *entry,
- struct inode **inodep)
+static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
+ struct nameidata *nd)
{
int err;
struct fuse_entry_out outarg;
@@ -106,11 +109,11 @@ static int fuse_lookup_iget(struct inode
struct fuse_req *req;
if (entry->d_name.len > FUSE_NAME_MAX)
- return -ENAMETOOLONG;
+ return ERR_PTR(-ENAMETOOLONG);
req = fuse_get_request(fc);
if (!req)
- return -EINTR;
+ return ERR_PTR(-EINTR);
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
@@ -122,24 +125,22 @@ static int fuse_lookup_iget(struct inode
&outarg.attr);
if (!inode) {
fuse_send_forget(fc, req, outarg.nodeid, 1);
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
}
}
fuse_put_request(fc, req);
if (err && err != -ENOENT)
- return err;
+ return ERR_PTR(err);
- if (inode) {
- struct fuse_inode *fi = get_fuse_inode(inode);
- entry->d_time = time_to_jiffies(outarg.entry_valid,
- outarg.entry_valid_nsec);
- fi->i_time = time_to_jiffies(outarg.attr_valid,
- outarg.attr_valid_nsec);
+ if (inode && dir_alias(inode)) {
+ iput(inode);
+ return ERR_PTR(-EIO);
}
-
+ d_add(entry, inode);
entry->d_op = &fuse_dentry_operations;
- *inodep = inode;
- return 0;
+ if (inode)
+ fuse_change_timeout(entry, &outarg);
+ return NULL;
}
void fuse_invalidate_attr(struct inode *inode)
@@ -163,7 +164,6 @@ static int fuse_create_open(struct inode
struct fuse_open_in inarg;
struct fuse_open_out outopen;
struct fuse_entry_out outentry;
- struct fuse_inode *fi;
struct fuse_file *ff;
struct file *file;
int flags = nd->intent.open.flags - 1;
@@ -224,13 +224,8 @@ static int fuse_create_open(struct inode
goto out_put_request;
}
fuse_put_request(fc, req);
- entry->d_time = time_to_jiffies(outentry.entry_valid,
- outentry.entry_valid_nsec);
- fi = get_fuse_inode(inode);
- fi->i_time = time_to_jiffies(outentry.attr_valid,
- outentry.attr_valid_nsec);
-
d_instantiate(entry, inode);
+ fuse_change_timeout(entry, &outentry);
file = lookup_instantiate_filp(nd, entry, generic_file_open);
if (IS_ERR(file)) {
ff->fh = outopen.fh;
@@ -254,7 +249,6 @@ static int create_new_entry(struct fuse_
{
struct fuse_entry_out outarg;
struct inode *inode;
- struct fuse_inode *fi;
int err;
req->in.h.nodeid = get_node_id(dir);
@@ -286,14 +280,8 @@ static int create_new_entry(struct fuse_
return -EIO;
}
- entry->d_time = time_to_jiffies(outarg.entry_valid,
- outarg.entry_valid_nsec);
-
- fi = get_fuse_inode(inode);
- fi->i_time = time_to_jiffies(outarg.attr_valid,
- outarg.attr_valid_nsec);
-
d_instantiate(entry, inode);
+ fuse_change_timeout(entry, &outarg);
fuse_invalidate_attr(dir);
return 0;
}
@@ -883,23 +871,6 @@ static int fuse_getattr(struct vfsmount
return err;
}
-static struct dentry *fuse_lookup(struct inode *dir, struct dentry *entry,
- struct nameidata *nd)
-{
- struct inode *inode;
- int err;
-
- err = fuse_lookup_iget(dir, entry, &inode);
- if (err)
- return ERR_PTR(err);
- if (inode && dir_alias(inode)) {
- iput(inode);
- return ERR_PTR(-EIO);
- }
- d_add(entry, inode);
- return NULL;
-}
-
static int fuse_setxattr(struct dentry *entry, const char *name,
const void *value, size_t size, int flags)
{
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 4/7] fuse: clean up page offset calculation
2005-11-28 19:46 ` [PATCH 3/7] fuse: clean up fuse_lookup() Miklos Szeredi
@ 2005-11-28 19:47 ` Miklos Szeredi
2005-11-28 19:49 ` [PATCH 5/7] fuse: bump interface version Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:47 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Use page_offset() instead of doing page offset calculation by hand.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/file.c
===================================================================
--- linux.orig/fs/fuse/file.c 2005-11-28 14:01:07.000000000 +0100
+++ linux/fs/fuse/file.c 2005-11-28 14:02:07.000000000 +0100
@@ -272,7 +272,6 @@ static int fuse_readpage(struct file *fi
{
struct inode *inode = page->mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
- loff_t pos = (loff_t) page->index << PAGE_CACHE_SHIFT;
struct fuse_req *req = fuse_get_request(fc);
int err = -EINTR;
if (!req)
@@ -281,7 +280,7 @@ static int fuse_readpage(struct file *fi
req->out.page_zeroing = 1;
req->num_pages = 1;
req->pages[0] = page;
- fuse_send_read(req, file, inode, pos, PAGE_CACHE_SIZE);
+ fuse_send_read(req, file, inode, page_offset(page), PAGE_CACHE_SIZE);
err = req->out.h.error;
fuse_put_request(fc, req);
if (!err)
@@ -295,7 +294,7 @@ static int fuse_readpage(struct file *fi
static int fuse_send_readpages(struct fuse_req *req, struct file *file,
struct inode *inode)
{
- loff_t pos = (loff_t) req->pages[0]->index << PAGE_CACHE_SHIFT;
+ loff_t pos = page_offset(req->pages[0]);
size_t count = req->num_pages << PAGE_CACHE_SHIFT;
unsigned i;
req->out.page_zeroing = 1;
@@ -402,7 +401,7 @@ static int fuse_commit_write(struct file
unsigned count = to - offset;
struct inode *inode = page->mapping->host;
struct fuse_conn *fc = get_fuse_conn(inode);
- loff_t pos = ((loff_t) page->index << PAGE_CACHE_SHIFT) + offset;
+ loff_t pos = page_offset(page) + offset;
struct fuse_req *req = fuse_get_request(fc);
if (!req)
return -EINTR;
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 5/7] fuse: bump interface version
2005-11-28 19:47 ` [PATCH 4/7] fuse: clean up page offset calculation Miklos Szeredi
@ 2005-11-28 19:49 ` Miklos Szeredi
2005-11-28 19:50 ` [PATCH 6/7] fuse: add frsize to statfs reply Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:49 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Change interface version to 7.4.
Following changes will need backward compatibility support, so store
the minor version returned by userspace.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/dev.c
===================================================================
--- linux.orig/fs/fuse/dev.c 2005-11-22 14:45:54.000000000 +0100
+++ linux/fs/fuse/dev.c 2005-11-28 12:02:10.000000000 +0100
@@ -178,6 +178,8 @@ static void request_end(struct fuse_conn
if (req->misc.init_in_out.major != FUSE_KERNEL_VERSION)
fc->conn_error = 1;
+ fc->minor = req->misc.init_in_out.minor;
+
/* After INIT reply is received other requests can go
out. So do (FUSE_MAX_OUTSTANDING - 1) number of
up()s on outstanding_sem. The last up() is done in
Index: linux/include/linux/fuse.h
===================================================================
--- linux.orig/include/linux/fuse.h 2005-11-22 14:45:58.000000000 +0100
+++ linux/include/linux/fuse.h 2005-11-28 11:59:01.000000000 +0100
@@ -14,7 +14,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 3
+#define FUSE_KERNEL_MINOR_VERSION 4
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
Index: linux/fs/fuse/fuse_i.h
===================================================================
--- linux.orig/fs/fuse/fuse_i.h 2005-11-22 14:45:54.000000000 +0100
+++ linux/fs/fuse/fuse_i.h 2005-11-28 12:02:36.000000000 +0100
@@ -272,6 +272,9 @@ struct fuse_conn {
/** Is create not implemented by fs? */
unsigned no_create : 1;
+ /** Negotiated minor version */
+ unsigned minor;
+
/** Backing dev info */
struct backing_dev_info bdi;
};
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 6/7] fuse: add frsize to statfs reply
2005-11-28 19:49 ` [PATCH 5/7] fuse: bump interface version Miklos Szeredi
@ 2005-11-28 19:50 ` Miklos Szeredi
2005-11-28 19:51 ` [PATCH 7/7] fuse: support caching negative dentries Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:50 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Add 'frsize' member to the statfs reply.
I'm not sure if sending f_fsid will ever be needed, but just in case
leave some space at the end of the structure, so less compatibility
mess would be required.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/inode.c
===================================================================
--- linux.orig/fs/fuse/inode.c 2005-11-28 14:01:07.000000000 +0100
+++ linux/fs/fuse/inode.c 2005-11-28 16:45:12.000000000 +0100
@@ -218,6 +218,7 @@ static void convert_fuse_statfs(struct k
{
stbuf->f_type = FUSE_SUPER_MAGIC;
stbuf->f_bsize = attr->bsize;
+ stbuf->f_frsize = attr->frsize;
stbuf->f_blocks = attr->blocks;
stbuf->f_bfree = attr->bfree;
stbuf->f_bavail = attr->bavail;
@@ -238,10 +239,12 @@ static int fuse_statfs(struct super_bloc
if (!req)
return -EINTR;
+ memset(&outarg, 0, sizeof(outarg));
req->in.numargs = 0;
req->in.h.opcode = FUSE_STATFS;
req->out.numargs = 1;
- req->out.args[0].size = sizeof(outarg);
+ req->out.args[0].size =
+ fc->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(outarg);
req->out.args[0].value = &outarg;
request_send(fc, req);
err = req->out.h.error;
Index: linux/include/linux/fuse.h
===================================================================
--- linux.orig/include/linux/fuse.h 2005-11-28 14:02:09.000000000 +0100
+++ linux/include/linux/fuse.h 2005-11-28 15:25:14.000000000 +0100
@@ -53,6 +53,9 @@ struct fuse_kstatfs {
__u64 ffree;
__u32 bsize;
__u32 namelen;
+ __u32 frsize;
+ __u32 padding;
+ __u32 spare[6];
};
#define FATTR_MODE (1 << 0)
@@ -213,6 +216,8 @@ struct fuse_write_out {
__u32 padding;
};
+#define FUSE_COMPAT_STATFS_SIZE 48
+
struct fuse_statfs_out {
struct fuse_kstatfs st;
};
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 7/7] fuse: support caching negative dentries
2005-11-28 19:50 ` [PATCH 6/7] fuse: add frsize to statfs reply Miklos Szeredi
@ 2005-11-28 19:51 ` Miklos Szeredi
2005-11-28 20:40 ` Andrew Morton
0 siblings, 1 reply; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 19:51 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
Add support for caching negative dentries.
Up till now, ->d_revalidate() always forced a new lookup on these.
Now let the lookup method return a zero node ID (not used for anything
else) meaning a negative entry, but with a positive cache timeout.
The old way of signaling negative entry (replying ENOENT) still works.
Userspace should check the ABI minor version to see whether sending a
zero ID is allowed by the kernel or not.
Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
---
Index: linux/fs/fuse/dir.c
===================================================================
--- linux.orig/fs/fuse/dir.c 2005-11-28 17:55:27.000000000 +0100
+++ linux/fs/fuse/dir.c 2005-11-28 18:07:23.000000000 +0100
@@ -23,9 +23,26 @@ static inline unsigned long time_to_jiff
static void fuse_change_timeout(struct dentry *entry, struct fuse_entry_out *o)
{
- struct fuse_inode *fi = get_fuse_inode(entry->d_inode);
entry->d_time = time_to_jiffies(o->entry_valid, o->entry_valid_nsec);
- fi->i_time = time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+ if (entry->d_inode)
+ get_fuse_inode(entry->d_inode)->i_time =
+ time_to_jiffies(o->attr_valid, o->attr_valid_nsec);
+}
+
+void fuse_invalidate_attr(struct inode *inode)
+{
+ get_fuse_inode(inode)->i_time = jiffies - 1;
+}
+
+static void fuse_invalidate_entry_cache(struct dentry *entry)
+{
+ entry->d_time = jiffies - 1;
+}
+
+static void fuse_invalidate_entry(struct dentry *entry)
+{
+ d_invalidate(entry);
+ fuse_invalidate_entry_cache(entry);
}
static void fuse_lookup_init(struct fuse_req *req, struct inode *dir,
@@ -45,15 +62,22 @@ static void fuse_lookup_init(struct fuse
static int fuse_dentry_revalidate(struct dentry *entry, struct nameidata *nd)
{
- if (!entry->d_inode || is_bad_inode(entry->d_inode))
+ struct inode *inode = entry->d_inode;
+
+ if (inode && is_bad_inode(inode))
return 0;
else if (time_after(jiffies, entry->d_time)) {
int err;
struct fuse_entry_out outarg;
- struct inode *inode = entry->d_inode;
- struct fuse_inode *fi = get_fuse_inode(inode);
- struct fuse_conn *fc = get_fuse_conn(inode);
- struct fuse_req *req = fuse_get_request(fc);
+ struct fuse_conn *fc;
+ struct fuse_req *req;
+
+ fuse_invalidate_entry_cache(entry);
+ if (!inode)
+ return 0;
+
+ fc = get_fuse_conn(inode);
+ req = fuse_get_request(fc);
if (!req)
return 0;
@@ -61,6 +85,7 @@ static int fuse_dentry_revalidate(struct
request_send(fc, req);
err = req->out.h.error;
if (!err) {
+ struct fuse_inode *fi = get_fuse_inode(inode);
if (outarg.nodeid != get_node_id(inode)) {
fuse_send_forget(fc, req, outarg.nodeid, 1);
return 0;
@@ -118,9 +143,9 @@ static struct dentry *fuse_lookup(struct
fuse_lookup_init(req, dir, entry, &outarg);
request_send(fc, req);
err = req->out.h.error;
- if (!err && invalid_nodeid(outarg.nodeid))
+ if (!err && outarg.nodeid && invalid_nodeid(outarg.nodeid))
err = -EIO;
- if (!err) {
+ if (!err && outarg.nodeid) {
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
&outarg.attr);
if (!inode) {
@@ -138,22 +163,13 @@ static struct dentry *fuse_lookup(struct
}
d_add(entry, inode);
entry->d_op = &fuse_dentry_operations;
- if (inode)
+ if (!err)
fuse_change_timeout(entry, &outarg);
+ else
+ fuse_invalidate_entry_cache(entry);
return NULL;
}
-void fuse_invalidate_attr(struct inode *inode)
-{
- get_fuse_inode(inode)->i_time = jiffies - 1;
-}
-
-static void fuse_invalidate_entry(struct dentry *entry)
-{
- d_invalidate(entry);
- entry->d_time = jiffies - 1;
-}
-
static int fuse_create_open(struct inode *dir, struct dentry *entry, int mode,
struct nameidata *nd)
{
@@ -387,6 +403,7 @@ static int fuse_unlink(struct inode *dir
inode->i_nlink = 0;
fuse_invalidate_attr(inode);
fuse_invalidate_attr(dir);
+ fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR)
fuse_invalidate_entry(entry);
return err;
@@ -412,6 +429,7 @@ static int fuse_rmdir(struct inode *dir,
if (!err) {
entry->d_inode->i_nlink = 0;
fuse_invalidate_attr(dir);
+ fuse_invalidate_entry_cache(entry);
} else if (err == -EINTR)
fuse_invalidate_entry(entry);
return err;
@@ -447,6 +465,10 @@ static int fuse_rename(struct inode *old
fuse_invalidate_attr(olddir);
if (olddir != newdir)
fuse_invalidate_attr(newdir);
+
+ /* newent will end up negative */
+ if (newent->d_inode)
+ fuse_invalidate_entry_cache(newent);
} else if (err == -EINTR) {
/* If request was interrupted, DEITY only knows if the
rename actually took place. If the invalidation
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/7] fuse: check directory aliasing in mkdir
2005-11-28 19:43 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Miklos Szeredi
2005-11-28 19:45 ` [PATCH 2/7] fuse: check for invalid node ID in fuse_create_open() Miklos Szeredi
@ 2005-11-28 19:57 ` Trond Myklebust
2005-11-28 20:09 ` Miklos Szeredi
1 sibling, 1 reply; 12+ messages in thread
From: Trond Myklebust @ 2005-11-28 19:57 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: akpm, linux-kernel
On Mon, 2005-11-28 at 20:43 +0100, Miklos Szeredi wrote:
> Check the created directory inode for aliases in the mkdir() method.
Can't you use d_add_unique() here?
Cheers,
Trond
> Signed-off-by: Miklos Szeredi <miklos@szeredi.hu>
>
> ---
> Index: linux/fs/fuse/dir.c
> ===================================================================
> --- linux.orig/fs/fuse/dir.c 2005-11-28 14:01:08.000000000 +0100
> +++ linux/fs/fuse/dir.c 2005-11-28 14:01:52.000000000 +0100
> @@ -74,6 +74,19 @@ static int fuse_dentry_revalidate(struct
> return 1;
> }
>
> +static int dir_alias(struct inode *inode)
> +{
> + if (S_ISDIR(inode->i_mode)) {
> + /* Don't allow creating an alias to a directory */
> + struct dentry *alias = d_find_alias(inode);
> + if (alias) {
> + dput(alias);
> + return 1;
> + }
> + }
> + return 0;
> +}
> +
> static struct dentry_operations fuse_dentry_operations = {
> .d_revalidate = fuse_dentry_revalidate,
> };
> @@ -263,7 +276,7 @@ static int create_new_entry(struct fuse_
> fuse_put_request(fc, req);
>
> /* Don't allow userspace to do really stupid things... */
> - if ((inode->i_mode ^ mode) & S_IFMT) {
> + if (((inode->i_mode ^ mode) & S_IFMT) || dir_alias(inode)) {
> iput(inode);
> return -EIO;
> }
> @@ -874,14 +887,9 @@ static struct dentry *fuse_lookup(struct
> err = fuse_lookup_iget(dir, entry, &inode);
> if (err)
> return ERR_PTR(err);
> - if (inode && S_ISDIR(inode->i_mode)) {
> - /* Don't allow creating an alias to a directory */
> - struct dentry *alias = d_find_alias(inode);
> - if (alias) {
> - dput(alias);
> - iput(inode);
> - return ERR_PTR(-EIO);
> - }
> + if (inode && dir_alias(inode)) {
> + iput(inode);
> + return ERR_PTR(-EIO);
> }
> d_add(entry, inode);
> return NULL;
> -
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 1/7] fuse: check directory aliasing in mkdir
2005-11-28 19:57 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Trond Myklebust
@ 2005-11-28 20:09 ` Miklos Szeredi
0 siblings, 0 replies; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 20:09 UTC (permalink / raw)
To: trond.myklebust; +Cc: akpm, linux-kernel
> > Check the created directory inode for aliases in the mkdir() method.
>
>
> Can't you use d_add_unique() here?
The patch is checking for hashed aliases of an inode. E.g. if /foo is
a directory and has a ID of 28, and mkdir /bar returns the same ID,
then the mkdir should fail.
It's an illegal for the filesystem to create two directories refering
to the same inode.
OTOH d_add_unique() is looking for unhashed aliases to resurrect,
which may or may not make sense in fuse. I'll think about it a bit
more.
Thanks,
Miklos
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 7/7] fuse: support caching negative dentries
2005-11-28 19:51 ` [PATCH 7/7] fuse: support caching negative dentries Miklos Szeredi
@ 2005-11-28 20:40 ` Andrew Morton
2005-11-28 21:06 ` Miklos Szeredi
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Morton @ 2005-11-28 20:40 UTC (permalink / raw)
To: Miklos Szeredi; +Cc: linux-kernel
Miklos Szeredi <miklos@szeredi.hu> wrote:
>
> +void fuse_invalidate_attr(struct inode *inode)
> +{
> + get_fuse_inode(inode)->i_time = jiffies - 1;
> +}
> +
> +static void fuse_invalidate_entry_cache(struct dentry *entry)
> +{
> + entry->d_time = jiffies - 1;
> +}
> +
I'd normally have a little whine about lack of comments here - pity the
poor programmer who is trying to work out why on earth that code is doing
that.
But fuse is pretty much a comment-free zone anyway. Please don't go near
any buses.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH 7/7] fuse: support caching negative dentries
2005-11-28 20:40 ` Andrew Morton
@ 2005-11-28 21:06 ` Miklos Szeredi
0 siblings, 0 replies; 12+ messages in thread
From: Miklos Szeredi @ 2005-11-28 21:06 UTC (permalink / raw)
To: akpm; +Cc: linux-kernel
> >
> > +void fuse_invalidate_attr(struct inode *inode)
> > +{
> > + get_fuse_inode(inode)->i_time = jiffies - 1;
> > +}
> > +
> > +static void fuse_invalidate_entry_cache(struct dentry *entry)
> > +{
> > + entry->d_time = jiffies - 1;
> > +}
> > +
>
> I'd normally have a little whine about lack of comments here - pity the
> poor programmer who is trying to work out why on earth that code is doing
> that.
Well, I thought it was evident, but it seems not. I'll add some
comments.
> But fuse is pretty much a comment-free zone anyway.
I think most of FUSE is really-really obvious. The most complex parts
are in the device handling, which is now quite well commented (thanks
to your earlier whining :).
> Please don't go near any buses.
Don't worry, I usually go by tram.
Miklos
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2005-11-28 21:07 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2005-11-28 19:41 [PATCH 0/7] fuse updates Miklos Szeredi
2005-11-28 19:43 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Miklos Szeredi
2005-11-28 19:45 ` [PATCH 2/7] fuse: check for invalid node ID in fuse_create_open() Miklos Szeredi
2005-11-28 19:46 ` [PATCH 3/7] fuse: clean up fuse_lookup() Miklos Szeredi
2005-11-28 19:47 ` [PATCH 4/7] fuse: clean up page offset calculation Miklos Szeredi
2005-11-28 19:49 ` [PATCH 5/7] fuse: bump interface version Miklos Szeredi
2005-11-28 19:50 ` [PATCH 6/7] fuse: add frsize to statfs reply Miklos Szeredi
2005-11-28 19:51 ` [PATCH 7/7] fuse: support caching negative dentries Miklos Szeredi
2005-11-28 20:40 ` Andrew Morton
2005-11-28 21:06 ` Miklos Szeredi
2005-11-28 19:57 ` [PATCH 1/7] fuse: check directory aliasing in mkdir Trond Myklebust
2005-11-28 20:09 ` Miklos Szeredi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®