Login
[x]
Log in using an account from:
Fedora Account System
Red Hat Associate
Red Hat Customer
Or login using a Red Hat Bugzilla account
Forgot Password
Login:
Hide Forgot
Create an Account
Red Hat Bugzilla – Attachment 151557 Details for
Bug 234587
VFS: Busy inodes at umount on NFSv4 filesystem
[?]
New
Simple Search
Advanced Search
My Links
Browse
Requests
Reports
Current State
Search
Tabular reports
Graphical reports
Duplicates
Other Reports
User Changes
Plotly Reports
Bug Status
Bug Severity
Non-Defaults
|
Product Dashboard
Help
Page Help!
Bug Writing Guidelines
What's new
Browser Support Policy
5.0.4.rh83 Release notes
FAQ
Guides index
User guide
Web Services
Contact
Legal
This site requires JavaScript to be enabled to function correctly, please enable it.
[patch]
patch -- track incomplete opens and clean up in setattr
linux-2.6.9-nfs4-incomplete-open.patch (text/plain), 5.04 KB, created by
Jeff Layton
on 2007-04-03 13:51:23 UTC
(
hide
)
Description:
patch -- track incomplete opens and clean up in setattr
Filename:
MIME Type:
Creator:
Jeff Layton
Created:
2007-04-03 13:51:23 UTC
Size:
5.04 KB
patch
obsolete
>diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c >index 0f57a94..9c81b2c 100644 >--- a/fs/nfs/nfs4proc.c >+++ b/fs/nfs/nfs4proc.c >@@ -606,6 +606,38 @@ struct nfs4_state *nfs4_do_open(struct inode *dir, struct qstr *name, int flags, > return res; > } > >+/* >+ * NFSv4 has a complex open scheme where the actual OPEN call is done in the >+ * in the lookup, and the file pointer is initialized in the open. If the >+ * lookup completes successfully, but open_namei returns an error, then the >+ * nfs4_state is left "dangling". The obvious way for this to occur is if >+ * a setattr that's eventually called from open_namei returns an error. We >+ * start tracking this info in nfs4_atomic_open, and then remove the tracking >+ * here. If this returns true then a dangling open was found and removed. In >+ * error condition we'll want to do an extra nfs4_close_state based on this >+ * return value to clean up the dangling open. >+ */ >+static int nfs4_remove_incomplete_open(struct nfs4_state *state, >+ unsigned long *flags) { >+ struct list_head *entry; >+ struct nfs4_inc_open *inc_open; >+ >+ spin_lock(&state->inode->i_lock); >+ list_for_each(entry, &state->inc_open) { >+ inc_open = list_entry(entry, struct nfs4_inc_open, state); >+ if (inc_open->task == current) { >+ list_del(&inc_open->state); >+ spin_unlock(&state->inode->i_lock); >+ if (flags) >+ *flags = inc_open->flags; >+ kfree(inc_open); >+ return 1; >+ } >+ } >+ spin_unlock(&state->inode->i_lock); >+ return 0; >+} >+ > static int _nfs4_do_setattr(struct nfs_server *server, struct nfs_fattr *fattr, > struct nfs_fh *fhandle, struct iattr *sattr, > struct nfs4_state *state) >@@ -768,6 +800,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) > struct iattr attr; > struct rpc_cred *cred; > struct nfs4_state *state; >+ struct nfs4_inc_open *inc_open; > > if (nd->flags & LOOKUP_CREATE) { > attr.ia_mode = nd->intent.open.create_mode; >@@ -779,11 +812,22 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd) > BUG_ON(nd->intent.open.flags & O_CREAT); > } > >+ /* track info in case the open never completes */ >+ if (!(inc_open = kmalloc(sizeof(*inc_open), GFP_KERNEL))); >+ return ERR_PTR(-ENOMEM); > cred = rpcauth_lookupcred(NFS_SERVER(dir)->client->cl_auth, 0); > state = nfs4_do_open(dir, &dentry->d_name, nd->intent.open.flags, &attr, cred); > put_rpccred(cred); >- if (IS_ERR(state)) >+ if (IS_ERR(state)) { >+ kfree(inc_open); > return (struct inode *)state; >+ } >+ inc_open->task = current; >+ inc_open->flags = nd->intent.open.flags; >+ INIT_LIST_HEAD(&inc_open->state); >+ spin_lock(&state->inode->i_lock); >+ list_add(&inc_open->state, &state->inc_open); >+ spin_unlock(&state->inode->i_lock); > return state->inode; > } > >@@ -1009,6 +1053,7 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, > struct nfs4_state *state = NULL; > int need_iput = 0; > int status; >+ unsigned long flags; > > nfs_fattr_init(fattr); > >@@ -1038,6 +1083,8 @@ nfs4_proc_setattr(struct dentry *dentry, struct nfs_fattr *fattr, > NFS_FH(inode), sattr, state); > if (status == 0) > nfs_setattr_update_inode(inode, sattr); >+ else if (state && nfs4_remove_incomplete_open(state, &flags)) >+ nfs4_close_state(state, flags); > out: > if (state) { > inode = state->inode; >@@ -2026,6 +2073,7 @@ nfs4_proc_file_open(struct inode *inode, struct file *filp) > state = nfs4_find_state(inode, cred, filp->f_mode); > if (unlikely(state == NULL)) > goto no_state; >+ nfs4_remove_incomplete_open(state, NULL); > ctx->state = state; > nfs4_close_state(state, filp->f_mode); > ctx->mode = filp->f_mode; >diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c >index 859763d..cb4a6ae 100644 >--- a/fs/nfs/nfs4state.c >+++ b/fs/nfs/nfs4state.c >@@ -358,6 +358,7 @@ nfs4_alloc_open_state(void) > memset(state->stateid.data, 0, sizeof(state->stateid.data)); > atomic_set(&state->count, 1); > INIT_LIST_HEAD(&state->lock_states); >+ INIT_LIST_HEAD(&state->inc_open); > init_MUTEX(&state->lock_sema); > rwlock_init(&state->state_lock); > return state; >diff --git a/fs/super.c b/fs/super.c >index 23ec715..ea6385a 100644 >--- a/fs/super.c >+++ b/fs/super.c >@@ -225,6 +225,7 @@ void generic_shutdown_super(struct super_block *sb) > > if (root) { > sb->s_root = NULL; >+ fsync_super(sb); > shrink_dcache_parent(root); > shrink_dcache_anon(sb); > dput(root); >diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h >index f8391f5..1555bcb 100644 >--- a/include/linux/nfs_fs.h >+++ b/include/linux/nfs_fs.h >@@ -765,10 +765,18 @@ enum { > NFS_DELEGATED_STATE, > }; > >+/* struct for tracking incomplete opens */ >+struct nfs4_inc_open { >+ struct list_head state; >+ struct task_struct *task; >+ unsigned long flags; >+}; >+ > struct nfs4_state { > struct list_head open_states; /* List of states for the same state_owner */ > struct list_head inode_states; /* List of states for the same inode */ > struct list_head lock_states; /* List of subservient lock stateids */ >+ struct list_head inc_open; /* List of incomplete opens */ > > struct nfs4_state_owner *owner; /* Pointer to the open owner */ > struct inode *inode; /* Pointer to the inode */
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 234587
:
151296
|
151557
|
151576
|
152181
|
152182