aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4proc.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2007-06-05 10:31:33 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2007-07-10 23:40:24 -0400
commit4a35bd41aff5714deb41c8f14766df3871e2e8f7 (patch)
tree3542c76b1e0aabcd0ee6bb76fdd8228e6f3b5479 /fs/nfs/nfs4proc.c
parentad389da79f7bf9dc12dbc79c9c2740f9ed2f13d1 (diff)
NFSv4: Ensure that nfs4_do_close() doesn't race with umount
nfs4_do_close() does not currently have any way to ensure that the user won't attempt to unmount the partition while the asynchronous RPC call is completing. This again may cause Oopses in nfs_update_inode(). Add a vfsmount argument to nfs4_close_state to ensure that the partition remains mounted while we're closing the file. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4proc.c')
-rw-r--r--fs/nfs/nfs4proc.c35
1 files changed, 20 insertions, 15 deletions
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 895e8e649c91..8feaf232f2e4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -453,7 +453,7 @@ static int nfs4_open_recover(struct nfs4_opendata *opendata, struct nfs4_state *
453 opendata->owner->so_cred, 453 opendata->owner->so_cred,
454 &opendata->o_res); 454 &opendata->o_res);
455 } 455 }
456 nfs4_close_state(newstate, opendata->o_arg.open_flags); 456 nfs4_close_state(&opendata->path, newstate, opendata->o_arg.open_flags);
457 } 457 }
458 if (newstate != state) 458 if (newstate != state)
459 return -ESTALE; 459 return -ESTALE;
@@ -603,7 +603,7 @@ static void nfs4_open_confirm_release(void *calldata)
603 nfs_confirm_seqid(&data->owner->so_seqid, 0); 603 nfs_confirm_seqid(&data->owner->so_seqid, 0);
604 state = nfs4_opendata_to_nfs4_state(data); 604 state = nfs4_opendata_to_nfs4_state(data);
605 if (state != NULL) 605 if (state != NULL)
606 nfs4_close_state(state, data->o_arg.open_flags); 606 nfs4_close_state(&data->path, state, data->o_arg.open_flags);
607out_free: 607out_free:
608 nfs4_opendata_free(data); 608 nfs4_opendata_free(data);
609} 609}
@@ -706,7 +706,7 @@ static void nfs4_open_release(void *calldata)
706 nfs_confirm_seqid(&data->owner->so_seqid, 0); 706 nfs_confirm_seqid(&data->owner->so_seqid, 0);
707 state = nfs4_opendata_to_nfs4_state(data); 707 state = nfs4_opendata_to_nfs4_state(data);
708 if (state != NULL) 708 if (state != NULL)
709 nfs4_close_state(state, data->o_arg.open_flags); 709 nfs4_close_state(&data->path, state, data->o_arg.open_flags);
710out_free: 710out_free:
711 nfs4_opendata_free(data); 711 nfs4_opendata_free(data);
712} 712}
@@ -1103,6 +1103,7 @@ static int nfs4_do_setattr(struct inode *inode, struct nfs_fattr *fattr,
1103} 1103}
1104 1104
1105struct nfs4_closedata { 1105struct nfs4_closedata {
1106 struct path path;
1106 struct inode *inode; 1107 struct inode *inode;
1107 struct nfs4_state *state; 1108 struct nfs4_state *state;
1108 struct nfs_closeargs arg; 1109 struct nfs_closeargs arg;
@@ -1119,6 +1120,8 @@ static void nfs4_free_closedata(void *data)
1119 nfs4_put_open_state(calldata->state); 1120 nfs4_put_open_state(calldata->state);
1120 nfs_free_seqid(calldata->arg.seqid); 1121 nfs_free_seqid(calldata->arg.seqid);
1121 nfs4_put_state_owner(sp); 1122 nfs4_put_state_owner(sp);
1123 dput(calldata->path.dentry);
1124 mntput(calldata->path.mnt);
1122 kfree(calldata); 1125 kfree(calldata);
1123} 1126}
1124 1127
@@ -1211,18 +1214,18 @@ static const struct rpc_call_ops nfs4_close_ops = {
1211 * 1214 *
1212 * NOTE: Caller must be holding the sp->so_owner semaphore! 1215 * NOTE: Caller must be holding the sp->so_owner semaphore!
1213 */ 1216 */
1214int nfs4_do_close(struct inode *inode, struct nfs4_state *state) 1217int nfs4_do_close(struct path *path, struct nfs4_state *state)
1215{ 1218{
1216 struct nfs_server *server = NFS_SERVER(inode); 1219 struct nfs_server *server = NFS_SERVER(state->inode);
1217 struct nfs4_closedata *calldata; 1220 struct nfs4_closedata *calldata;
1218 int status = -ENOMEM; 1221 int status = -ENOMEM;
1219 1222
1220 calldata = kmalloc(sizeof(*calldata), GFP_KERNEL); 1223 calldata = kmalloc(sizeof(*calldata), GFP_KERNEL);
1221 if (calldata == NULL) 1224 if (calldata == NULL)
1222 goto out; 1225 goto out;
1223 calldata->inode = inode; 1226 calldata->inode = state->inode;
1224 calldata->state = state; 1227 calldata->state = state;
1225 calldata->arg.fh = NFS_FH(inode); 1228 calldata->arg.fh = NFS_FH(state->inode);
1226 calldata->arg.stateid = &state->stateid; 1229 calldata->arg.stateid = &state->stateid;
1227 /* Serialization for the sequence id */ 1230 /* Serialization for the sequence id */
1228 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid); 1231 calldata->arg.seqid = nfs_alloc_seqid(&state->owner->so_seqid);
@@ -1231,6 +1234,8 @@ int nfs4_do_close(struct inode *inode, struct nfs4_state *state)
1231 calldata->arg.bitmask = server->attr_bitmask; 1234 calldata->arg.bitmask = server->attr_bitmask;
1232 calldata->res.fattr = &calldata->fattr; 1235 calldata->res.fattr = &calldata->fattr;
1233 calldata->res.server = server; 1236 calldata->res.server = server;
1237 calldata->path.mnt = mntget(path->mnt);
1238 calldata->path.dentry = dget(path->dentry);
1234 1239
1235 status = nfs4_call_async(server->client, &nfs4_close_ops, calldata); 1240 status = nfs4_call_async(server->client, &nfs4_close_ops, calldata);
1236 if (status == 0) 1241 if (status == 0)
@@ -1243,18 +1248,18 @@ out:
1243 return status; 1248 return status;
1244} 1249}
1245 1250
1246static int nfs4_intent_set_file(struct nameidata *nd, struct dentry *dentry, struct nfs4_state *state) 1251static int nfs4_intent_set_file(struct nameidata *nd, struct path *path, struct nfs4_state *state)
1247{ 1252{
1248 struct file *filp; 1253 struct file *filp;
1249 1254
1250 filp = lookup_instantiate_filp(nd, dentry, NULL); 1255 filp = lookup_instantiate_filp(nd, path->dentry, NULL);
1251 if (!IS_ERR(filp)) { 1256 if (!IS_ERR(filp)) {
1252 struct nfs_open_context *ctx; 1257 struct nfs_open_context *ctx;
1253 ctx = (struct nfs_open_context *)filp->private_data; 1258 ctx = (struct nfs_open_context *)filp->private_data;
1254 ctx->state = state; 1259 ctx->state = state;
1255 return 0; 1260 return 0;
1256 } 1261 }
1257 nfs4_close_state(state, nd->intent.open.flags); 1262 nfs4_close_state(path, state, nd->intent.open.flags);
1258 return PTR_ERR(filp); 1263 return PTR_ERR(filp);
1259} 1264}
1260 1265
@@ -1293,7 +1298,7 @@ nfs4_atomic_open(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
1293 res = d_add_unique(dentry, igrab(state->inode)); 1298 res = d_add_unique(dentry, igrab(state->inode));
1294 if (res != NULL) 1299 if (res != NULL)
1295 dentry = res; 1300 dentry = res;
1296 nfs4_intent_set_file(nd, dentry, state); 1301 nfs4_intent_set_file(nd, &path, state);
1297 return res; 1302 return res;
1298} 1303}
1299 1304
@@ -1328,10 +1333,10 @@ nfs4_open_revalidate(struct inode *dir, struct dentry *dentry, int openflags, st
1328 } 1333 }
1329 } 1334 }
1330 if (state->inode == dentry->d_inode) { 1335 if (state->inode == dentry->d_inode) {
1331 nfs4_intent_set_file(nd, dentry, state); 1336 nfs4_intent_set_file(nd, &path, state);
1332 return 1; 1337 return 1;
1333 } 1338 }
1334 nfs4_close_state(state, openflags); 1339 nfs4_close_state(&path, state, openflags);
1335out_drop: 1340out_drop:
1336 d_drop(dentry); 1341 d_drop(dentry);
1337 return 0; 1342 return 0;
@@ -1789,9 +1794,9 @@ nfs4_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr,
1789 nfs_setattr_update_inode(state->inode, sattr); 1794 nfs_setattr_update_inode(state->inode, sattr);
1790 } 1795 }
1791 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0) 1796 if (status == 0 && (nd->flags & LOOKUP_OPEN) != 0)
1792 status = nfs4_intent_set_file(nd, dentry, state); 1797 status = nfs4_intent_set_file(nd, &path, state);
1793 else 1798 else
1794 nfs4_close_state(state, flags); 1799 nfs4_close_state(&path, state, flags);
1795out: 1800out:
1796 return status; 1801 return status;
1797} 1802}