diff options
Diffstat (limited to 'fs/nfs/proc.c')
| -rw-r--r-- | fs/nfs/proc.c | 144 |
1 files changed, 82 insertions, 62 deletions
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c index 0288be80444f..611bec22f552 100644 --- a/fs/nfs/proc.c +++ b/fs/nfs/proc.c | |||
| @@ -224,35 +224,60 @@ static int nfs_proc_readlink(struct inode *inode, struct page *page, | |||
| 224 | return status; | 224 | return status; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | struct nfs_createdata { | ||
| 228 | struct nfs_createargs arg; | ||
| 229 | struct nfs_diropok res; | ||
| 230 | struct nfs_fh fhandle; | ||
| 231 | struct nfs_fattr fattr; | ||
| 232 | }; | ||
| 233 | |||
| 234 | static struct nfs_createdata *nfs_alloc_createdata(struct inode *dir, | ||
| 235 | struct dentry *dentry, struct iattr *sattr) | ||
| 236 | { | ||
| 237 | struct nfs_createdata *data; | ||
| 238 | |||
| 239 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
| 240 | |||
| 241 | if (data != NULL) { | ||
| 242 | data->arg.fh = NFS_FH(dir); | ||
| 243 | data->arg.name = dentry->d_name.name; | ||
| 244 | data->arg.len = dentry->d_name.len; | ||
| 245 | data->arg.sattr = sattr; | ||
| 246 | nfs_fattr_init(&data->fattr); | ||
| 247 | data->fhandle.size = 0; | ||
| 248 | data->res.fh = &data->fhandle; | ||
| 249 | data->res.fattr = &data->fattr; | ||
| 250 | } | ||
| 251 | return data; | ||
| 252 | }; | ||
| 253 | |||
| 254 | static void nfs_free_createdata(const struct nfs_createdata *data) | ||
| 255 | { | ||
| 256 | kfree(data); | ||
| 257 | } | ||
| 258 | |||
| 227 | static int | 259 | static int |
| 228 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 260 | nfs_proc_create(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 229 | int flags, struct nameidata *nd) | 261 | int flags, struct nameidata *nd) |
| 230 | { | 262 | { |
| 231 | struct nfs_fh fhandle; | 263 | struct nfs_createdata *data; |
| 232 | struct nfs_fattr fattr; | ||
| 233 | struct nfs_createargs arg = { | ||
| 234 | .fh = NFS_FH(dir), | ||
| 235 | .name = dentry->d_name.name, | ||
| 236 | .len = dentry->d_name.len, | ||
| 237 | .sattr = sattr | ||
| 238 | }; | ||
| 239 | struct nfs_diropok res = { | ||
| 240 | .fh = &fhandle, | ||
| 241 | .fattr = &fattr | ||
| 242 | }; | ||
| 243 | struct rpc_message msg = { | 264 | struct rpc_message msg = { |
| 244 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 265 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
| 245 | .rpc_argp = &arg, | ||
| 246 | .rpc_resp = &res, | ||
| 247 | }; | 266 | }; |
| 248 | int status; | 267 | int status = -ENOMEM; |
| 249 | 268 | ||
| 250 | nfs_fattr_init(&fattr); | ||
| 251 | dprintk("NFS call create %s\n", dentry->d_name.name); | 269 | dprintk("NFS call create %s\n", dentry->d_name.name); |
| 270 | data = nfs_alloc_createdata(dir, dentry, sattr); | ||
| 271 | if (data == NULL) | ||
| 272 | goto out; | ||
| 273 | msg.rpc_argp = &data->arg; | ||
| 274 | msg.rpc_resp = &data->res; | ||
| 252 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 275 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 253 | nfs_mark_for_revalidate(dir); | 276 | nfs_mark_for_revalidate(dir); |
| 254 | if (status == 0) | 277 | if (status == 0) |
| 255 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 278 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
| 279 | nfs_free_createdata(data); | ||
| 280 | out: | ||
| 256 | dprintk("NFS reply create: %d\n", status); | 281 | dprintk("NFS reply create: %d\n", status); |
| 257 | return status; | 282 | return status; |
| 258 | } | 283 | } |
| @@ -264,24 +289,12 @@ static int | |||
| 264 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | 289 | nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, |
| 265 | dev_t rdev) | 290 | dev_t rdev) |
| 266 | { | 291 | { |
| 267 | struct nfs_fh fhandle; | 292 | struct nfs_createdata *data; |
| 268 | struct nfs_fattr fattr; | ||
| 269 | struct nfs_createargs arg = { | ||
| 270 | .fh = NFS_FH(dir), | ||
| 271 | .name = dentry->d_name.name, | ||
| 272 | .len = dentry->d_name.len, | ||
| 273 | .sattr = sattr | ||
| 274 | }; | ||
| 275 | struct nfs_diropok res = { | ||
| 276 | .fh = &fhandle, | ||
| 277 | .fattr = &fattr | ||
| 278 | }; | ||
| 279 | struct rpc_message msg = { | 293 | struct rpc_message msg = { |
| 280 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], | 294 | .rpc_proc = &nfs_procedures[NFSPROC_CREATE], |
| 281 | .rpc_argp = &arg, | ||
| 282 | .rpc_resp = &res, | ||
| 283 | }; | 295 | }; |
| 284 | int status, mode; | 296 | umode_t mode; |
| 297 | int status = -ENOMEM; | ||
| 285 | 298 | ||
| 286 | dprintk("NFS call mknod %s\n", dentry->d_name.name); | 299 | dprintk("NFS call mknod %s\n", dentry->d_name.name); |
| 287 | 300 | ||
| @@ -294,17 +307,24 @@ nfs_proc_mknod(struct inode *dir, struct dentry *dentry, struct iattr *sattr, | |||
| 294 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ | 307 | sattr->ia_size = new_encode_dev(rdev);/* get out your barf bag */ |
| 295 | } | 308 | } |
| 296 | 309 | ||
| 297 | nfs_fattr_init(&fattr); | 310 | data = nfs_alloc_createdata(dir, dentry, sattr); |
| 311 | if (data == NULL) | ||
| 312 | goto out; | ||
| 313 | msg.rpc_argp = &data->arg; | ||
| 314 | msg.rpc_resp = &data->res; | ||
| 315 | |||
| 298 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 316 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 299 | nfs_mark_for_revalidate(dir); | 317 | nfs_mark_for_revalidate(dir); |
| 300 | 318 | ||
| 301 | if (status == -EINVAL && S_ISFIFO(mode)) { | 319 | if (status == -EINVAL && S_ISFIFO(mode)) { |
| 302 | sattr->ia_mode = mode; | 320 | sattr->ia_mode = mode; |
| 303 | nfs_fattr_init(&fattr); | 321 | nfs_fattr_init(data->res.fattr); |
| 304 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 322 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 305 | } | 323 | } |
| 306 | if (status == 0) | 324 | if (status == 0) |
| 307 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 325 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
| 326 | nfs_free_createdata(data); | ||
| 327 | out: | ||
| 308 | dprintk("NFS reply mknod: %d\n", status); | 328 | dprintk("NFS reply mknod: %d\n", status); |
| 309 | return status; | 329 | return status; |
| 310 | } | 330 | } |
| @@ -398,8 +418,8 @@ static int | |||
| 398 | nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | 418 | nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, |
| 399 | unsigned int len, struct iattr *sattr) | 419 | unsigned int len, struct iattr *sattr) |
| 400 | { | 420 | { |
| 401 | struct nfs_fh fhandle; | 421 | struct nfs_fh *fh; |
| 402 | struct nfs_fattr fattr; | 422 | struct nfs_fattr *fattr; |
| 403 | struct nfs_symlinkargs arg = { | 423 | struct nfs_symlinkargs arg = { |
| 404 | .fromfh = NFS_FH(dir), | 424 | .fromfh = NFS_FH(dir), |
| 405 | .fromname = dentry->d_name.name, | 425 | .fromname = dentry->d_name.name, |
| @@ -412,12 +432,18 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
| 412 | .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], | 432 | .rpc_proc = &nfs_procedures[NFSPROC_SYMLINK], |
| 413 | .rpc_argp = &arg, | 433 | .rpc_argp = &arg, |
| 414 | }; | 434 | }; |
| 415 | int status; | 435 | int status = -ENAMETOOLONG; |
| 436 | |||
| 437 | dprintk("NFS call symlink %s\n", dentry->d_name.name); | ||
| 416 | 438 | ||
| 417 | if (len > NFS2_MAXPATHLEN) | 439 | if (len > NFS2_MAXPATHLEN) |
| 418 | return -ENAMETOOLONG; | 440 | goto out; |
| 419 | 441 | ||
| 420 | dprintk("NFS call symlink %s\n", dentry->d_name.name); | 442 | fh = nfs_alloc_fhandle(); |
| 443 | fattr = nfs_alloc_fattr(); | ||
| 444 | status = -ENOMEM; | ||
| 445 | if (fh == NULL || fattr == NULL) | ||
| 446 | goto out; | ||
| 421 | 447 | ||
| 422 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 448 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 423 | nfs_mark_for_revalidate(dir); | 449 | nfs_mark_for_revalidate(dir); |
| @@ -427,12 +453,12 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
| 427 | * filehandle size to zero indicates to nfs_instantiate that it | 453 | * filehandle size to zero indicates to nfs_instantiate that it |
| 428 | * should fill in the data with a LOOKUP call on the wire. | 454 | * should fill in the data with a LOOKUP call on the wire. |
| 429 | */ | 455 | */ |
| 430 | if (status == 0) { | 456 | if (status == 0) |
| 431 | nfs_fattr_init(&fattr); | 457 | status = nfs_instantiate(dentry, fh, fattr); |
| 432 | fhandle.size = 0; | ||
| 433 | status = nfs_instantiate(dentry, &fhandle, &fattr); | ||
| 434 | } | ||
| 435 | 458 | ||
| 459 | nfs_free_fattr(fattr); | ||
| 460 | nfs_free_fhandle(fh); | ||
| 461 | out: | ||
| 436 | dprintk("NFS reply symlink: %d\n", status); | 462 | dprintk("NFS reply symlink: %d\n", status); |
| 437 | return status; | 463 | return status; |
| 438 | } | 464 | } |
| @@ -440,31 +466,25 @@ nfs_proc_symlink(struct inode *dir, struct dentry *dentry, struct page *page, | |||
| 440 | static int | 466 | static int |
| 441 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) | 467 | nfs_proc_mkdir(struct inode *dir, struct dentry *dentry, struct iattr *sattr) |
| 442 | { | 468 | { |
| 443 | struct nfs_fh fhandle; | 469 | struct nfs_createdata *data; |
| 444 | struct nfs_fattr fattr; | ||
| 445 | struct nfs_createargs arg = { | ||
| 446 | .fh = NFS_FH(dir), | ||
| 447 | .name = dentry->d_name.name, | ||
| 448 | .len = dentry->d_name.len, | ||
| 449 | .sattr = sattr | ||
| 450 | }; | ||
| 451 | struct nfs_diropok res = { | ||
| 452 | .fh = &fhandle, | ||
| 453 | .fattr = &fattr | ||
| 454 | }; | ||
| 455 | struct rpc_message msg = { | 470 | struct rpc_message msg = { |
| 456 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], | 471 | .rpc_proc = &nfs_procedures[NFSPROC_MKDIR], |
| 457 | .rpc_argp = &arg, | ||
| 458 | .rpc_resp = &res, | ||
| 459 | }; | 472 | }; |
| 460 | int status; | 473 | int status = -ENOMEM; |
| 461 | 474 | ||
| 462 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); | 475 | dprintk("NFS call mkdir %s\n", dentry->d_name.name); |
| 463 | nfs_fattr_init(&fattr); | 476 | data = nfs_alloc_createdata(dir, dentry, sattr); |
| 477 | if (data == NULL) | ||
| 478 | goto out; | ||
| 479 | msg.rpc_argp = &data->arg; | ||
| 480 | msg.rpc_resp = &data->res; | ||
| 481 | |||
| 464 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); | 482 | status = rpc_call_sync(NFS_CLIENT(dir), &msg, 0); |
| 465 | nfs_mark_for_revalidate(dir); | 483 | nfs_mark_for_revalidate(dir); |
| 466 | if (status == 0) | 484 | if (status == 0) |
| 467 | status = nfs_instantiate(dentry, &fhandle, &fattr); | 485 | status = nfs_instantiate(dentry, data->res.fh, data->res.fattr); |
| 486 | nfs_free_createdata(data); | ||
| 487 | out: | ||
| 468 | dprintk("NFS reply mkdir: %d\n", status); | 488 | dprintk("NFS reply mkdir: %d\n", status); |
| 469 | return status; | 489 | return status; |
| 470 | } | 490 | } |
