diff options
author | Dave Hansen <haveblue@us.ibm.com> | 2008-02-15 17:37:57 -0500 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2008-04-19 00:25:34 -0400 |
commit | 463c3197263bd26ac59a00d2484990e17e35c50e (patch) | |
tree | b27c04f978ccd447ae33f7387b6a4aba0033acc5 /fs/nfsd/vfs.c | |
parent | 0622753b800e4cc6cb9319b36b27658c72dd7cdc (diff) |
[PATCH] r/o bind mounts: get callers of vfs_mknod/create/mkdir()
This takes care of all of the direct callers of vfs_mknod().
Since a few of these cases also handle normal file creation
as well, this also covers some calls to vfs_create().
So that we don't have to make three mnt_want/drop_write()
calls inside of the switch statement, we move some of its
logic outside of the switch and into a helper function
suggested by Christoph.
This also encapsulates a fix for mknod(S_IFREG) that Miklos
found.
[AV: merged mkdir handling, added missing nfsd pieces]
Acked-by: Al Viro <viro@ZenIV.linux.org.uk>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Dave Hansen <haveblue@us.ibm.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r-- | fs/nfsd/vfs.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index efff58a5818c..14d582467029 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -1255,23 +1255,35 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1255 | err = 0; | 1255 | err = 0; |
1256 | switch (type) { | 1256 | switch (type) { |
1257 | case S_IFREG: | 1257 | case S_IFREG: |
1258 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1259 | if (host_err) | ||
1260 | goto out_nfserr; | ||
1258 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1261 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1259 | break; | 1262 | break; |
1260 | case S_IFDIR: | 1263 | case S_IFDIR: |
1264 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1265 | if (host_err) | ||
1266 | goto out_nfserr; | ||
1261 | host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); | 1267 | host_err = vfs_mkdir(dirp, dchild, iap->ia_mode); |
1262 | break; | 1268 | break; |
1263 | case S_IFCHR: | 1269 | case S_IFCHR: |
1264 | case S_IFBLK: | 1270 | case S_IFBLK: |
1265 | case S_IFIFO: | 1271 | case S_IFIFO: |
1266 | case S_IFSOCK: | 1272 | case S_IFSOCK: |
1273 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1274 | if (host_err) | ||
1275 | goto out_nfserr; | ||
1267 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); | 1276 | host_err = vfs_mknod(dirp, dchild, iap->ia_mode, rdev); |
1268 | break; | 1277 | break; |
1269 | default: | 1278 | default: |
1270 | printk("nfsd: bad file type %o in nfsd_create\n", type); | 1279 | printk("nfsd: bad file type %o in nfsd_create\n", type); |
1271 | host_err = -EINVAL; | 1280 | host_err = -EINVAL; |
1281 | goto out_nfserr; | ||
1272 | } | 1282 | } |
1273 | if (host_err < 0) | 1283 | if (host_err < 0) { |
1284 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1274 | goto out_nfserr; | 1285 | goto out_nfserr; |
1286 | } | ||
1275 | 1287 | ||
1276 | if (EX_ISSYNC(fhp->fh_export)) { | 1288 | if (EX_ISSYNC(fhp->fh_export)) { |
1277 | err = nfserrno(nfsd_sync_dir(dentry)); | 1289 | err = nfserrno(nfsd_sync_dir(dentry)); |
@@ -1282,6 +1294,7 @@ nfsd_create(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1282 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); | 1294 | err2 = nfsd_create_setattr(rqstp, resfhp, iap); |
1283 | if (err2) | 1295 | if (err2) |
1284 | err = err2; | 1296 | err = err2; |
1297 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1285 | /* | 1298 | /* |
1286 | * Update the file handle to get the new inode info. | 1299 | * Update the file handle to get the new inode info. |
1287 | */ | 1300 | */ |
@@ -1359,6 +1372,9 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1359 | v_atime = verifier[1]&0x7fffffff; | 1372 | v_atime = verifier[1]&0x7fffffff; |
1360 | } | 1373 | } |
1361 | 1374 | ||
1375 | host_err = mnt_want_write(fhp->fh_export->ex_path.mnt); | ||
1376 | if (host_err) | ||
1377 | goto out_nfserr; | ||
1362 | if (dchild->d_inode) { | 1378 | if (dchild->d_inode) { |
1363 | err = 0; | 1379 | err = 0; |
1364 | 1380 | ||
@@ -1390,12 +1406,15 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1390 | case NFS3_CREATE_GUARDED: | 1406 | case NFS3_CREATE_GUARDED: |
1391 | err = nfserr_exist; | 1407 | err = nfserr_exist; |
1392 | } | 1408 | } |
1409 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1393 | goto out; | 1410 | goto out; |
1394 | } | 1411 | } |
1395 | 1412 | ||
1396 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); | 1413 | host_err = vfs_create(dirp, dchild, iap->ia_mode, NULL); |
1397 | if (host_err < 0) | 1414 | if (host_err < 0) { |
1415 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1398 | goto out_nfserr; | 1416 | goto out_nfserr; |
1417 | } | ||
1399 | if (created) | 1418 | if (created) |
1400 | *created = 1; | 1419 | *created = 1; |
1401 | 1420 | ||
@@ -1420,6 +1439,7 @@ nfsd_create_v3(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1420 | if (err2) | 1439 | if (err2) |
1421 | err = err2; | 1440 | err = err2; |
1422 | 1441 | ||
1442 | mnt_drop_write(fhp->fh_export->ex_path.mnt); | ||
1423 | /* | 1443 | /* |
1424 | * Update the filehandle to get the new inode info. | 1444 | * Update the filehandle to get the new inode info. |
1425 | */ | 1445 | */ |