From 496ad9aa8ef448058e36ca7a787c61f2e63f0f54 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Wed, 23 Jan 2013 17:07:38 -0500 Subject: new helper: file_inode(file) Signed-off-by: Al Viro --- fs/9p/vfs_file.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/vfs_file.c b/fs/9p/vfs_file.c index c2483e97beee..3356e3ed5115 100644 --- a/fs/9p/vfs_file.c +++ b/fs/9p/vfs_file.c @@ -133,7 +133,7 @@ out_error: static int v9fs_file_lock(struct file *filp, int cmd, struct file_lock *fl) { int res = 0; - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); p9_debug(P9_DEBUG_VFS, "filp: %p lock: %p\n", filp, fl); @@ -302,7 +302,7 @@ static int v9fs_file_getlock(struct file *filp, struct file_lock *fl) static int v9fs_file_lock_dotl(struct file *filp, int cmd, struct file_lock *fl) { - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); int ret = -ENOLCK; p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", @@ -338,7 +338,7 @@ out_err: static int v9fs_file_flock_dotl(struct file *filp, int cmd, struct file_lock *fl) { - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); int ret = -ENOLCK; p9_debug(P9_DEBUG_VFS, "filp: %p cmd:%d lock: %p name: %s\n", @@ -529,7 +529,7 @@ v9fs_file_write(struct file *filp, const char __user * data, if (!count) goto out; - retval = v9fs_file_write_internal(filp->f_path.dentry->d_inode, + retval = v9fs_file_write_internal(file_inode(filp), filp->private_data, data, count, &origin, 1); /* update offset on successful write */ @@ -604,7 +604,7 @@ v9fs_vm_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf) struct v9fs_inode *v9inode; struct page *page = vmf->page; struct file *filp = vma->vm_file; - struct inode *inode = filp->f_path.dentry->d_inode; + struct inode *inode = file_inode(filp); p9_debug(P9_DEBUG_VFS, "page %p fid %lx\n", -- cgit v1.2.3 From 38baba9ea02780c2df35c7a02552fddeb8576e16 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 12:34:58 -0500 Subject: 9p: add fid-based variant of v9fs_xattr_set() ... making v9fs_xattr_set() a wrapper for it. Signed-off-by: Al Viro --- fs/9p/xattr.c | 33 ++++++++++++++++++--------------- fs/9p/xattr.h | 2 ++ 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/xattr.c b/fs/9p/xattr.c index 29653b70a9c3..c45e016b190f 100644 --- a/fs/9p/xattr.c +++ b/fs/9p/xattr.c @@ -110,20 +110,27 @@ ssize_t v9fs_xattr_get(struct dentry *dentry, const char *name, */ int v9fs_xattr_set(struct dentry *dentry, const char *name, const void *value, size_t value_len, int flags) +{ + struct p9_fid *fid = v9fs_fid_lookup(dentry); + if (IS_ERR(fid)) + return PTR_ERR(fid); + return v9fs_fid_xattr_set(fid, name, value, value_len, flags); +} + +int v9fs_fid_xattr_set(struct p9_fid *fid, const char *name, + const void *value, size_t value_len, int flags) { u64 offset = 0; int retval, msize, write_count; - struct p9_fid *fid = NULL; p9_debug(P9_DEBUG_VFS, "name = %s value_len = %zu flags = %d\n", name, value_len, flags); - fid = v9fs_fid_clone(dentry); - if (IS_ERR(fid)) { - retval = PTR_ERR(fid); - fid = NULL; - goto error; - } + /* Clone it */ + fid = p9_client_walk(fid, 0, NULL, 1); + if (IS_ERR(fid)) + return PTR_ERR(fid); + /* * On success fid points to xattr */ @@ -131,7 +138,8 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, if (retval < 0) { p9_debug(P9_DEBUG_VFS, "p9_client_xattrcreate failed %d\n", retval); - goto error; + p9_client_clunk(fid); + return retval; } msize = fid->clnt->msize; while (value_len) { @@ -144,17 +152,12 @@ int v9fs_xattr_set(struct dentry *dentry, const char *name, if (write_count < 0) { /* error in xattr write */ retval = write_count; - goto error; + break; } offset += write_count; value_len -= write_count; } - /* Total read xattr bytes */ - retval = offset; -error: - if (fid) - retval = p9_client_clunk(fid); - return retval; + return p9_client_clunk(fid); } ssize_t v9fs_listxattr(struct dentry *dentry, char *buffer, size_t buffer_size) diff --git a/fs/9p/xattr.h b/fs/9p/xattr.h index eaa837c53bd5..eec348a3df71 100644 --- a/fs/9p/xattr.h +++ b/fs/9p/xattr.h @@ -27,6 +27,8 @@ extern ssize_t v9fs_fid_xattr_get(struct p9_fid *, const char *, void *, size_t); extern ssize_t v9fs_xattr_get(struct dentry *, const char *, void *, size_t); +extern int v9fs_fid_xattr_set(struct p9_fid *, const char *, + const void *, size_t, int); extern int v9fs_xattr_set(struct dentry *, const char *, const void *, size_t, int); extern ssize_t v9fs_listxattr(struct dentry *, char *, size_t); -- cgit v1.2.3 From 7f165aaa7dc898472f3b3fbf2231bb3b5623a3df Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 12:46:55 -0500 Subject: 9p: lift the call of set_cached_acl() into the callers of v9fs_set_acl() Signed-off-by: Al Viro --- fs/9p/acl.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 15b679166201..c5d8cd638e6e 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -119,10 +119,6 @@ static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl) char *name; size_t size; void *buffer; - struct inode *inode = dentry->d_inode; - - set_cached_acl(inode, type, acl); - if (!acl) return 0; @@ -163,6 +159,7 @@ int v9fs_acl_chmod(struct dentry *dentry) retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); if (retval) return retval; + set_cached_acl(inode, ACL_TYPE_ACCESS, acl); retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, acl); posix_acl_release(acl); } @@ -173,7 +170,9 @@ int v9fs_set_create_acl(struct dentry *dentry, struct posix_acl **dpacl, struct posix_acl **pacl) { if (dentry) { + set_cached_acl(dentry->d_inode, ACL_TYPE_DEFAULT, *dpacl); v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, *dpacl); + set_cached_acl(dentry->d_inode, ACL_TYPE_ACCESS, *pacl); v9fs_set_acl(dentry, ACL_TYPE_ACCESS, *pacl); } posix_acl_release(*dpacl); -- cgit v1.2.3 From 0f235caeaed6bbde6d455e172a83fa693ca485a1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 12:54:47 -0500 Subject: 9p: switch v9fs_set_acl() from dentry to fid Signed-off-by: Al Viro --- fs/9p/acl.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index c5d8cd638e6e..506d8af26a1f 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -23,6 +23,7 @@ #include "acl.h" #include "v9fs.h" #include "v9fs_vfs.h" +#include "fid.h" static struct posix_acl *__v9fs_get_acl(struct p9_fid *fid, char *name) { @@ -113,7 +114,7 @@ struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type) } -static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl) +static int v9fs_set_acl(struct p9_fid *fid, int type, struct posix_acl *acl) { int retval; char *name; @@ -140,7 +141,7 @@ static int v9fs_set_acl(struct dentry *dentry, int type, struct posix_acl *acl) default: BUG(); } - retval = v9fs_xattr_set(dentry, name, buffer, size, 0); + retval = v9fs_fid_xattr_set(fid, name, buffer, size, 0); err_free_out: kfree(buffer); return retval; @@ -151,16 +152,19 @@ int v9fs_acl_chmod(struct dentry *dentry) int retval = 0; struct posix_acl *acl; struct inode *inode = dentry->d_inode; + struct p9_fid *fid = v9fs_fid_lookup(dentry); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; + if (IS_ERR(fid)) + return PTR_ERR(fid); acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); if (acl) { retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); if (retval) return retval; set_cached_acl(inode, ACL_TYPE_ACCESS, acl); - retval = v9fs_set_acl(dentry, ACL_TYPE_ACCESS, acl); + retval = v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); posix_acl_release(acl); } return retval; @@ -170,10 +174,13 @@ int v9fs_set_create_acl(struct dentry *dentry, struct posix_acl **dpacl, struct posix_acl **pacl) { if (dentry) { + struct p9_fid *fid = v9fs_fid_lookup(dentry); set_cached_acl(dentry->d_inode, ACL_TYPE_DEFAULT, *dpacl); - v9fs_set_acl(dentry, ACL_TYPE_DEFAULT, *dpacl); set_cached_acl(dentry->d_inode, ACL_TYPE_ACCESS, *pacl); - v9fs_set_acl(dentry, ACL_TYPE_ACCESS, *pacl); + if (!IS_ERR(fid)) { + v9fs_set_acl(fid, ACL_TYPE_DEFAULT, *dpacl); + v9fs_set_acl(fid, ACL_TYPE_ACCESS, *pacl); + } } posix_acl_release(*dpacl); posix_acl_release(*pacl); -- cgit v1.2.3 From be308f07964a597ea1806a0c02477a383b92f53a Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 12:58:16 -0500 Subject: 9p: switch v9fs_acl_chmod() from dentry to inode+fid caller has both, might as well pass them explicitly. Signed-off-by: Al Viro --- fs/9p/acl.c | 6 +----- fs/9p/acl.h | 4 ++-- fs/9p/vfs_inode_dotl.c | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 506d8af26a1f..81ae143ff3f7 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -147,17 +147,13 @@ err_free_out: return retval; } -int v9fs_acl_chmod(struct dentry *dentry) +int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) { int retval = 0; struct posix_acl *acl; - struct inode *inode = dentry->d_inode; - struct p9_fid *fid = v9fs_fid_lookup(dentry); if (S_ISLNK(inode->i_mode)) return -EOPNOTSUPP; - if (IS_ERR(fid)) - return PTR_ERR(fid); acl = v9fs_get_cached_acl(inode, ACL_TYPE_ACCESS); if (acl) { retval = posix_acl_chmod(&acl, GFP_KERNEL, inode->i_mode); diff --git a/fs/9p/acl.h b/fs/9p/acl.h index 559556411965..3a609c57b6ea 100644 --- a/fs/9p/acl.h +++ b/fs/9p/acl.h @@ -17,7 +17,7 @@ #ifdef CONFIG_9P_FS_POSIX_ACL extern int v9fs_get_acl(struct inode *, struct p9_fid *); extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type); -extern int v9fs_acl_chmod(struct dentry *); +extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); extern int v9fs_set_create_acl(struct dentry *, struct posix_acl **, struct posix_acl **); extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, @@ -28,7 +28,7 @@ static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) { return 0; } -static inline int v9fs_acl_chmod(struct dentry *dentry) +static inline int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) { return 0; } diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 40895546e103..44485f353f19 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -567,10 +567,11 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) struct v9fs_session_info *v9ses; struct p9_fid *fid; struct p9_iattr_dotl p9attr; + struct inode *inode = dentry->d_inode; p9_debug(P9_DEBUG_VFS, "\n"); - retval = inode_change_ok(dentry->d_inode, iattr); + retval = inode_change_ok(inode, iattr); if (retval) return retval; @@ -591,23 +592,23 @@ int v9fs_vfs_setattr_dotl(struct dentry *dentry, struct iattr *iattr) return PTR_ERR(fid); /* Write all dirty data */ - if (S_ISREG(dentry->d_inode->i_mode)) - filemap_write_and_wait(dentry->d_inode->i_mapping); + if (S_ISREG(inode->i_mode)) + filemap_write_and_wait(inode->i_mapping); retval = p9_client_setattr(fid, &p9attr); if (retval < 0) return retval; if ((iattr->ia_valid & ATTR_SIZE) && - iattr->ia_size != i_size_read(dentry->d_inode)) - truncate_setsize(dentry->d_inode, iattr->ia_size); + iattr->ia_size != i_size_read(inode)) + truncate_setsize(inode, iattr->ia_size); - v9fs_invalidate_inode_attr(dentry->d_inode); - setattr_copy(dentry->d_inode, iattr); - mark_inode_dirty(dentry->d_inode); + v9fs_invalidate_inode_attr(inode); + setattr_copy(inode, iattr); + mark_inode_dirty(inode); if (iattr->ia_valid & ATTR_MODE) { /* We also want to update ACL when we update mode bits */ - retval = v9fs_acl_chmod(dentry); + retval = v9fs_acl_chmod(inode, fid); if (retval < 0) return retval; } -- cgit v1.2.3 From 5fa6300ae0ccf76018775ea16bc3a061cadc39a6 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 13:31:23 -0500 Subject: 9p: split dropping the acls from v9fs_set_create_acl() Signed-off-by: Al Viro --- fs/9p/acl.c | 26 ++++++++++++++------------ fs/9p/acl.h | 11 ++++++++--- fs/9p/vfs_inode_dotl.c | 12 ++++++------ 3 files changed, 28 insertions(+), 21 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 81ae143ff3f7..5b91689ac0b1 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -167,23 +167,25 @@ int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) } int v9fs_set_create_acl(struct dentry *dentry, - struct posix_acl **dpacl, struct posix_acl **pacl) + struct posix_acl *dacl, struct posix_acl *acl) { - if (dentry) { - struct p9_fid *fid = v9fs_fid_lookup(dentry); - set_cached_acl(dentry->d_inode, ACL_TYPE_DEFAULT, *dpacl); - set_cached_acl(dentry->d_inode, ACL_TYPE_ACCESS, *pacl); - if (!IS_ERR(fid)) { - v9fs_set_acl(fid, ACL_TYPE_DEFAULT, *dpacl); - v9fs_set_acl(fid, ACL_TYPE_ACCESS, *pacl); - } + struct p9_fid *fid = v9fs_fid_lookup(dentry); + set_cached_acl(dentry->d_inode, ACL_TYPE_DEFAULT, dacl); + set_cached_acl(dentry->d_inode, ACL_TYPE_ACCESS, acl); + if (!IS_ERR(fid)) { + v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); + v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); } - posix_acl_release(*dpacl); - posix_acl_release(*pacl); - *dpacl = *pacl = NULL; return 0; } +void v9fs_put_acl(struct posix_acl *dacl, + struct posix_acl *acl) +{ + posix_acl_release(dacl); + posix_acl_release(acl); +} + int v9fs_acl_mode(struct inode *dir, umode_t *modep, struct posix_acl **dpacl, struct posix_acl **pacl) { diff --git a/fs/9p/acl.h b/fs/9p/acl.h index 3a609c57b6ea..cb7fc54081f7 100644 --- a/fs/9p/acl.h +++ b/fs/9p/acl.h @@ -19,9 +19,10 @@ extern int v9fs_get_acl(struct inode *, struct p9_fid *); extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type); extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); extern int v9fs_set_create_acl(struct dentry *, - struct posix_acl **, struct posix_acl **); + struct posix_acl *, struct posix_acl *); extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, struct posix_acl **dpacl, struct posix_acl **pacl); +extern void v9fs_put_acl(struct posix_acl *dacl, struct posix_acl *acl); #else #define v9fs_iop_get_acl NULL static inline int v9fs_get_acl(struct inode *inode, struct p9_fid *fid) @@ -33,11 +34,15 @@ static inline int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) return 0; } static inline int v9fs_set_create_acl(struct dentry *dentry, - struct posix_acl **dpacl, - struct posix_acl **pacl) + struct posix_acl *dacl, + struct posix_acl *acl) { return 0; } +static inline void v9fs_put_acl(struct posix_acl *dacl, + struct posix_acl *acl) +{ +} static inline int v9fs_acl_mode(struct inode *dir, umode_t *modep, struct posix_acl **dpacl, struct posix_acl **pacl) diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index 44485f353f19..dd6355721fc7 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -331,7 +331,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, d_instantiate(dentry, inode); /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, &dacl, &pacl); + v9fs_set_create_acl(dentry, dacl, pacl); v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); @@ -364,6 +364,7 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, #endif *opened |= FILE_CREATED; out: + v9fs_put_acl(dacl, pacl); dput(res); return err; @@ -373,7 +374,6 @@ error: err_clunk_old_fid: if (ofid) p9_client_clunk(ofid); - v9fs_set_create_acl(NULL, &dacl, &pacl); goto out; } @@ -467,13 +467,13 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, d_instantiate(dentry, inode); } /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, &dacl, &pacl); + v9fs_set_create_acl(dentry, dacl, pacl); inc_nlink(dir); v9fs_invalidate_inode_attr(dir); error: if (fid) p9_client_clunk(fid); - v9fs_set_create_acl(NULL, &dacl, &pacl); + v9fs_put_acl(dacl, pacl); return err; } @@ -912,11 +912,11 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, d_instantiate(dentry, inode); } /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, &dacl, &pacl); + v9fs_set_create_acl(dentry, dacl, pacl); error: if (fid) p9_client_clunk(fid); - v9fs_set_create_acl(NULL, &dacl, &pacl); + v9fs_put_acl(dacl, pacl); return err; } -- cgit v1.2.3 From 3592ac444017996f5a8ecf85856af0a8938e8fd1 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 31 Jan 2013 13:45:39 -0500 Subject: 9p: switch v9fs_set_create_acl() to inode+fid, do it before d_instantiate() Signed-off-by: Al Viro --- fs/9p/acl.c | 13 +++++-------- fs/9p/acl.h | 5 +++-- fs/9p/vfs_inode_dotl.c | 50 +++++++++++++++++++++++++------------------------- 3 files changed, 33 insertions(+), 35 deletions(-) (limited to 'fs/9p') diff --git a/fs/9p/acl.c b/fs/9p/acl.c index 5b91689ac0b1..7af425f53bee 100644 --- a/fs/9p/acl.c +++ b/fs/9p/acl.c @@ -166,16 +166,13 @@ int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) return retval; } -int v9fs_set_create_acl(struct dentry *dentry, +int v9fs_set_create_acl(struct inode *inode, struct p9_fid *fid, struct posix_acl *dacl, struct posix_acl *acl) { - struct p9_fid *fid = v9fs_fid_lookup(dentry); - set_cached_acl(dentry->d_inode, ACL_TYPE_DEFAULT, dacl); - set_cached_acl(dentry->d_inode, ACL_TYPE_ACCESS, acl); - if (!IS_ERR(fid)) { - v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); - v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); - } + set_cached_acl(inode, ACL_TYPE_DEFAULT, dacl); + set_cached_acl(inode, ACL_TYPE_ACCESS, acl); + v9fs_set_acl(fid, ACL_TYPE_DEFAULT, dacl); + v9fs_set_acl(fid, ACL_TYPE_ACCESS, acl); return 0; } diff --git a/fs/9p/acl.h b/fs/9p/acl.h index cb7fc54081f7..e4f7e882272b 100644 --- a/fs/9p/acl.h +++ b/fs/9p/acl.h @@ -18,7 +18,7 @@ extern int v9fs_get_acl(struct inode *, struct p9_fid *); extern struct posix_acl *v9fs_iop_get_acl(struct inode *inode, int type); extern int v9fs_acl_chmod(struct inode *, struct p9_fid *); -extern int v9fs_set_create_acl(struct dentry *, +extern int v9fs_set_create_acl(struct inode *, struct p9_fid *, struct posix_acl *, struct posix_acl *); extern int v9fs_acl_mode(struct inode *dir, umode_t *modep, struct posix_acl **dpacl, struct posix_acl **pacl); @@ -33,7 +33,8 @@ static inline int v9fs_acl_chmod(struct inode *inode, struct p9_fid *fid) { return 0; } -static inline int v9fs_set_create_acl(struct dentry *dentry, +static inline int v9fs_set_create_acl(struct inode *inode, + struct p9_fid *fid, struct posix_acl *dacl, struct posix_acl *acl) { diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c index dd6355721fc7..7c295588150c 100644 --- a/fs/9p/vfs_inode_dotl.c +++ b/fs/9p/vfs_inode_dotl.c @@ -325,14 +325,14 @@ v9fs_vfs_atomic_open_dotl(struct inode *dir, struct dentry *dentry, p9_debug(P9_DEBUG_VFS, "inode creation failed %d\n", err); goto error; } + /* Now set the ACL based on the default value */ + v9fs_set_create_acl(inode, fid, dacl, pacl); + err = v9fs_fid_add(dentry, fid); if (err < 0) goto error; d_instantiate(dentry, inode); - /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, dacl, pacl); - v9inode = V9FS_I(inode); mutex_lock(&v9inode->v_mutex); if (v9ses->cache && !v9inode->writeback_fid && @@ -430,17 +430,17 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, if (err < 0) goto error; + fid = p9_client_walk(dfid, 1, &name, 1); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", + err); + fid = NULL; + goto error; + } + /* instantiate inode and assign the unopened fid to the dentry */ if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); if (IS_ERR(inode)) { err = PTR_ERR(inode); @@ -451,6 +451,7 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, err = v9fs_fid_add(dentry, fid); if (err < 0) goto error; + v9fs_set_create_acl(inode, fid, dacl, pacl); d_instantiate(dentry, inode); fid = NULL; } else { @@ -464,10 +465,9 @@ static int v9fs_vfs_mkdir_dotl(struct inode *dir, err = PTR_ERR(inode); goto error; } + v9fs_set_create_acl(inode, fid, dacl, pacl); d_instantiate(dentry, inode); } - /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, dacl, pacl); inc_nlink(dir); v9fs_invalidate_inode_attr(dir); error: @@ -876,17 +876,17 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, goto error; v9fs_invalidate_inode_attr(dir); + fid = p9_client_walk(dfid, 1, &name, 1); + if (IS_ERR(fid)) { + err = PTR_ERR(fid); + p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", + err); + fid = NULL; + goto error; + } + /* instantiate inode and assign the unopened fid to the dentry */ if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) { - fid = p9_client_walk(dfid, 1, &name, 1); - if (IS_ERR(fid)) { - err = PTR_ERR(fid); - p9_debug(P9_DEBUG_VFS, "p9_client_walk failed %d\n", - err); - fid = NULL; - goto error; - } - inode = v9fs_get_new_inode_from_fid(v9ses, fid, dir->i_sb); if (IS_ERR(inode)) { err = PTR_ERR(inode); @@ -894,6 +894,7 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, err); goto error; } + v9fs_set_create_acl(inode, fid, dacl, pacl); err = v9fs_fid_add(dentry, fid); if (err < 0) goto error; @@ -909,10 +910,9 @@ v9fs_vfs_mknod_dotl(struct inode *dir, struct dentry *dentry, umode_t omode, err = PTR_ERR(inode); goto error; } + v9fs_set_create_acl(inode, fid, dacl, pacl); d_instantiate(dentry, inode); } - /* Now set the ACL based on the default value */ - v9fs_set_create_acl(dentry, dacl, pacl); error: if (fid) p9_client_clunk(fid); -- cgit v1.2.3 From ecf3d1f1aa74da0d632b651a2e05a911f60e92c0 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Wed, 20 Feb 2013 11:19:05 -0500 Subject: vfs: kill FS_REVAL_DOT by adding a d_weak_revalidate dentry op The following set of operations on a NFS client and server will cause server# mkdir a client# cd a server# mv a a.bak client# sleep 30 # (or whatever the dir attrcache timeout is) client# stat . stat: cannot stat `.': Stale NFS file handle Obviously, we should not be getting an ESTALE error back there since the inode still exists on the server. The problem is that the lookup code will call d_revalidate on the dentry that "." refers to, because NFS has FS_REVAL_DOT set. nfs_lookup_revalidate will see that the parent directory has changed and will try to reverify the dentry by redoing a LOOKUP. That of course fails, so the lookup code returns ESTALE. The problem here is that d_revalidate is really a bad fit for this case. What we really want to know at this point is whether the inode is still good or not, but we don't really care what name it goes by or whether the dcache is still valid. Add a new d_op->d_weak_revalidate operation and have complete_walk call that instead of d_revalidate. The intent there is to allow for a "weaker" d_revalidate that just checks to see whether the inode is still good. This is also gives us an opportunity to kill off the FS_REVAL_DOT special casing. [AV: changed method name, added note in porting, fixed confusion re having it possibly called from RCU mode (it won't be)] Cc: NeilBrown Signed-off-by: Jeff Layton Signed-off-by: Al Viro --- Documentation/filesystems/Locking | 2 ++ Documentation/filesystems/porting | 4 ++++ Documentation/filesystems/vfs.txt | 24 +++++++++++++++++++++-- fs/9p/vfs_dentry.c | 1 + fs/9p/vfs_super.c | 2 +- fs/dcache.c | 3 +++ fs/namei.c | 8 ++------ fs/nfs/dir.c | 40 +++++++++++++++++++++++++++++++++++++++ fs/nfs/nfs4super.c | 6 +++--- fs/nfs/super.c | 6 +++--- include/linux/dcache.h | 3 +++ include/linux/fs.h | 1 - 12 files changed, 84 insertions(+), 16 deletions(-) (limited to 'fs/9p') diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index f48e0c6b4c42..0706d32a61e6 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -10,6 +10,7 @@ be able to use diff(1). --------------------------- dentry_operations -------------------------- prototypes: int (*d_revalidate)(struct dentry *, unsigned int); + int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, const struct inode *, struct qstr *); int (*d_compare)(const struct dentry *, const struct inode *, @@ -25,6 +26,7 @@ prototypes: locking rules: rename_lock ->d_lock may block rcu-walk d_revalidate: no no yes (ref-walk) maybe +d_weak_revalidate:no no yes no d_hash no no no maybe d_compare: yes no no maybe d_delete: no yes no no diff --git a/Documentation/filesystems/porting b/Documentation/filesystems/porting index 0472c31c163b..4db22f6491e0 100644 --- a/Documentation/filesystems/porting +++ b/Documentation/filesystems/porting @@ -441,3 +441,7 @@ d_make_root() drops the reference to inode if dentry allocation fails. two, it gets "is it an O_EXCL or equivalent?" boolean argument. Note that local filesystems can ignore tha argument - they are guaranteed that the object doesn't exist. It's remote/distributed ones that might care... +-- +[mandatory] + FS_REVAL_DOT is gone; if you used to have it, add ->d_weak_revalidate() +in your dentry operations instead. diff --git a/Documentation/filesystems/vfs.txt b/Documentation/filesystems/vfs.txt index e3869098163e..bc4b06b3160a 100644 --- a/Documentation/filesystems/vfs.txt +++ b/Documentation/filesystems/vfs.txt @@ -900,6 +900,7 @@ defined: struct dentry_operations { int (*d_revalidate)(struct dentry *, unsigned int); + int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, const struct inode *, struct qstr *); int (*d_compare)(const struct dentry *, const struct inode *, @@ -915,8 +916,13 @@ struct dentry_operations { d_revalidate: called when the VFS needs to revalidate a dentry. This is called whenever a name look-up finds a dentry in the - dcache. Most filesystems leave this as NULL, because all their - dentries in the dcache are valid + dcache. Most local filesystems leave this as NULL, because all their + dentries in the dcache are valid. Network filesystems are different + since things can change on the server without the client necessarily + being aware of it. + + This function should return a positive value if the dentry is still + valid, and zero or a negative error code if it isn't. d_revalidate may be called in rcu-walk mode (flags & LOOKUP_RCU). If in rcu-walk mode, the filesystem must revalidate the dentry without @@ -927,6 +933,20 @@ struct dentry_operations { If a situation is encountered that rcu-walk cannot handle, return -ECHILD and it will be called again in ref-walk mode. + d_weak_revalidate: called when the VFS needs to revalidate a "jumped" dentry. + This is called when a path-walk ends at dentry that was not acquired by + doing a lookup in the parent directory. This includes "/", "." and "..", + as well as procfs-style symlinks and mountpoint traversal. + + In this case, we are less concerned with whether the dentry is still + fully correct, but rather that the inode is still valid. As with + d_revalidate, most local filesystems will set this to NULL since their + dcache entries are always valid. + + This function has the same return code semantics as d_revalidate. + + d_weak_revalidate is only called after leaving rcu-walk mode. + d_hash: called when the VFS adds a dentry to the hash table. The first dentry passed to d_hash is the parent directory that the name is to be hashed into. The inode is the dentry's inode. diff --git a/fs/9p/vfs_dentry.c b/fs/9p/vfs_dentry.c index 64600b5d0522..9ad68628522c 100644 --- a/fs/9p/vfs_dentry.c +++ b/fs/9p/vfs_dentry.c @@ -137,6 +137,7 @@ out_valid: const struct dentry_operations v9fs_cached_dentry_operations = { .d_revalidate = v9fs_lookup_revalidate, + .d_weak_revalidate = v9fs_lookup_revalidate, .d_delete = v9fs_cached_dentry_delete, .d_release = v9fs_dentry_release, }; diff --git a/fs/9p/vfs_super.c b/fs/9p/vfs_super.c index 137d50396898..91dad63e5a2d 100644 --- a/fs/9p/vfs_super.c +++ b/fs/9p/vfs_super.c @@ -363,5 +363,5 @@ struct file_system_type v9fs_fs_type = { .mount = v9fs_mount, .kill_sb = v9fs_kill_super, .owner = THIS_MODULE, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT, + .fs_flags = FS_RENAME_DOES_D_MOVE, }; diff --git a/fs/dcache.c b/fs/dcache.c index ebab049826c0..68220dd0c135 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -1358,6 +1358,7 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) WARN_ON_ONCE(dentry->d_flags & (DCACHE_OP_HASH | DCACHE_OP_COMPARE | DCACHE_OP_REVALIDATE | + DCACHE_OP_WEAK_REVALIDATE | DCACHE_OP_DELETE )); dentry->d_op = op; if (!op) @@ -1368,6 +1369,8 @@ void d_set_d_op(struct dentry *dentry, const struct dentry_operations *op) dentry->d_flags |= DCACHE_OP_COMPARE; if (op->d_revalidate) dentry->d_flags |= DCACHE_OP_REVALIDATE; + if (op->d_weak_revalidate) + dentry->d_flags |= DCACHE_OP_WEAK_REVALIDATE; if (op->d_delete) dentry->d_flags |= DCACHE_OP_DELETE; if (op->d_prune) diff --git a/fs/namei.c b/fs/namei.c index 052c095c2808..dc984fee5532 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -600,14 +600,10 @@ static int complete_walk(struct nameidata *nd) if (likely(!(nd->flags & LOOKUP_JUMPED))) return 0; - if (likely(!(dentry->d_flags & DCACHE_OP_REVALIDATE))) + if (likely(!(dentry->d_flags & DCACHE_OP_WEAK_REVALIDATE))) return 0; - if (likely(!(dentry->d_sb->s_type->fs_flags & FS_REVAL_DOT))) - return 0; - - /* Note: we do not d_invalidate() */ - status = d_revalidate(dentry, nd->flags); + status = dentry->d_op->d_weak_revalidate(dentry, nd->flags); if (status > 0) return 0; diff --git a/fs/nfs/dir.c b/fs/nfs/dir.c index a8bd28cde7e2..f23f455be42b 100644 --- a/fs/nfs/dir.c +++ b/fs/nfs/dir.c @@ -1135,6 +1135,45 @@ out_error: return error; } +/* + * A weaker form of d_revalidate for revalidating just the dentry->d_inode + * when we don't really care about the dentry name. This is called when a + * pathwalk ends on a dentry that was not found via a normal lookup in the + * parent dir (e.g.: ".", "..", procfs symlinks or mountpoint traversals). + * + * In this situation, we just want to verify that the inode itself is OK + * since the dentry might have changed on the server. + */ +static int nfs_weak_revalidate(struct dentry *dentry, unsigned int flags) +{ + int error; + struct inode *inode = dentry->d_inode; + + /* + * I believe we can only get a negative dentry here in the case of a + * procfs-style symlink. Just assume it's correct for now, but we may + * eventually need to do something more here. + */ + if (!inode) { + dfprintk(LOOKUPCACHE, "%s: %s/%s has negative inode\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); + return 1; + } + + if (is_bad_inode(inode)) { + dfprintk(LOOKUPCACHE, "%s: %s/%s has dud inode\n", + __func__, dentry->d_parent->d_name.name, + dentry->d_name.name); + return 0; + } + + error = nfs_revalidate_inode(NFS_SERVER(inode), inode); + dfprintk(LOOKUPCACHE, "NFS: %s: inode %lu is %s\n", + __func__, inode->i_ino, error ? "invalid" : "valid"); + return !error; +} + /* * This is called from dput() when d_count is going to 0. */ @@ -1202,6 +1241,7 @@ static void nfs_d_release(struct dentry *dentry) const struct dentry_operations nfs_dentry_operations = { .d_revalidate = nfs_lookup_revalidate, + .d_weak_revalidate = nfs_weak_revalidate, .d_delete = nfs_dentry_delete, .d_iput = nfs_dentry_iput, .d_automount = nfs_d_automount, diff --git a/fs/nfs/nfs4super.c b/fs/nfs/nfs4super.c index 84d2e9e2f313..569b166cc050 100644 --- a/fs/nfs/nfs4super.c +++ b/fs/nfs/nfs4super.c @@ -28,7 +28,7 @@ static struct file_system_type nfs4_remote_fs_type = { .name = "nfs4", .mount = nfs4_remote_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; static struct file_system_type nfs4_remote_referral_fs_type = { @@ -36,7 +36,7 @@ static struct file_system_type nfs4_remote_referral_fs_type = { .name = "nfs4", .mount = nfs4_remote_referral_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; struct file_system_type nfs4_referral_fs_type = { @@ -44,7 +44,7 @@ struct file_system_type nfs4_referral_fs_type = { .name = "nfs4", .mount = nfs4_referral_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; static const struct super_operations nfs4_sops = { diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 2e7e8c878e5d..92acc26f9c5f 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -292,7 +292,7 @@ struct file_system_type nfs_fs_type = { .name = "nfs", .mount = nfs_fs_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; EXPORT_SYMBOL_GPL(nfs_fs_type); @@ -301,7 +301,7 @@ struct file_system_type nfs_xdev_fs_type = { .name = "nfs", .mount = nfs_xdev_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; const struct super_operations nfs_sops = { @@ -331,7 +331,7 @@ struct file_system_type nfs4_fs_type = { .name = "nfs4", .mount = nfs_fs_mount, .kill_sb = nfs_kill_super, - .fs_flags = FS_RENAME_DOES_D_MOVE|FS_REVAL_DOT|FS_BINARY_MOUNTDATA, + .fs_flags = FS_RENAME_DOES_D_MOVE|FS_BINARY_MOUNTDATA, }; EXPORT_SYMBOL_GPL(nfs4_fs_type); diff --git a/include/linux/dcache.h b/include/linux/dcache.h index 03d169288423..1a6bb81f0fe5 100644 --- a/include/linux/dcache.h +++ b/include/linux/dcache.h @@ -145,6 +145,7 @@ enum dentry_d_lock_class struct dentry_operations { int (*d_revalidate)(struct dentry *, unsigned int); + int (*d_weak_revalidate)(struct dentry *, unsigned int); int (*d_hash)(const struct dentry *, const struct inode *, struct qstr *); int (*d_compare)(const struct dentry *, const struct inode *, @@ -192,6 +193,8 @@ struct dentry_operations { #define DCACHE_GENOCIDE 0x0200 #define DCACHE_SHRINK_LIST 0x0400 +#define DCACHE_OP_WEAK_REVALIDATE 0x0800 + #define DCACHE_NFSFS_RENAMED 0x1000 /* this dentry has been "silly renamed" and has to be deleted on the last * dput() */ diff --git a/include/linux/fs.h b/include/linux/fs.h index 7f471520b88b..da94011ae83c 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1807,7 +1807,6 @@ struct file_system_type { #define FS_HAS_SUBTYPE 4 #define FS_USERNS_MOUNT 8 /* Can be mounted by userns root */ #define FS_USERNS_DEV_MOUNT 16 /* A userns mount does not imply MNT_NODEV */ -#define FS_REVAL_DOT 16384 /* Check the paths ".", ".." for staleness */ #define FS_RENAME_DOES_D_MOVE 32768 /* FS will handle d_move() during rename() internally. */ struct dentry *(*mount) (struct file_system_type *, int, const char *, void *); -- cgit v1.2.3