|
8 | 8 | #include <linux/file.h>
|
9 | 9 | #include <linux/falloc.h>
|
10 | 10 | #include <linux/nfs_fs.h>
|
| 11 | +#include <linux/file.h> |
11 | 12 | #include "delegation.h"
|
12 | 13 | #include "internal.h"
|
13 | 14 | #include "iostat.h"
|
@@ -286,6 +287,99 @@ static loff_t nfs42_remap_file_range(struct file *src_file, loff_t src_off,
|
286 | 287 | out:
|
287 | 288 | return ret < 0 ? ret : count;
|
288 | 289 | }
|
| 290 | + |
| 291 | +static int read_name_gen = 1; |
| 292 | +#define SSC_READ_NAME_BODY "ssc_read_%d" |
| 293 | + |
| 294 | +struct file * |
| 295 | +nfs42_ssc_open(struct vfsmount *ss_mnt, struct nfs_fh *src_fh, |
| 296 | + nfs4_stateid *stateid) |
| 297 | +{ |
| 298 | + struct nfs_fattr fattr; |
| 299 | + struct file *filep, *res; |
| 300 | + struct nfs_server *server; |
| 301 | + struct inode *r_ino = NULL; |
| 302 | + struct nfs_open_context *ctx; |
| 303 | + struct nfs4_state_owner *sp; |
| 304 | + char *read_name; |
| 305 | + int len, status = 0; |
| 306 | + |
| 307 | + server = NFS_SERVER(ss_mnt->mnt_root->d_inode); |
| 308 | + |
| 309 | + nfs_fattr_init(&fattr); |
| 310 | + |
| 311 | + status = nfs4_proc_getattr(server, src_fh, &fattr, NULL, NULL); |
| 312 | + if (status < 0) { |
| 313 | + res = ERR_PTR(status); |
| 314 | + goto out; |
| 315 | + } |
| 316 | + |
| 317 | + res = ERR_PTR(-ENOMEM); |
| 318 | + len = strlen(SSC_READ_NAME_BODY) + 16; |
| 319 | + read_name = kzalloc(len, GFP_NOFS); |
| 320 | + if (read_name == NULL) |
| 321 | + goto out; |
| 322 | + snprintf(read_name, len, SSC_READ_NAME_BODY, read_name_gen++); |
| 323 | + |
| 324 | + r_ino = nfs_fhget(ss_mnt->mnt_root->d_inode->i_sb, src_fh, &fattr, |
| 325 | + NULL); |
| 326 | + if (IS_ERR(r_ino)) { |
| 327 | + res = ERR_CAST(r_ino); |
| 328 | + goto out; |
| 329 | + } |
| 330 | + |
| 331 | + filep = alloc_file_pseudo(r_ino, ss_mnt, read_name, FMODE_READ, |
| 332 | + r_ino->i_fop); |
| 333 | + if (IS_ERR(filep)) { |
| 334 | + res = ERR_CAST(filep); |
| 335 | + goto out; |
| 336 | + } |
| 337 | + filep->f_mode |= FMODE_READ; |
| 338 | + |
| 339 | + ctx = alloc_nfs_open_context(filep->f_path.dentry, filep->f_mode, |
| 340 | + filep); |
| 341 | + if (IS_ERR(ctx)) { |
| 342 | + res = ERR_CAST(ctx); |
| 343 | + goto out_filep; |
| 344 | + } |
| 345 | + |
| 346 | + res = ERR_PTR(-EINVAL); |
| 347 | + sp = nfs4_get_state_owner(server, ctx->cred, GFP_KERNEL); |
| 348 | + if (sp == NULL) |
| 349 | + goto out_ctx; |
| 350 | + |
| 351 | + ctx->state = nfs4_get_open_state(r_ino, sp); |
| 352 | + if (ctx->state == NULL) |
| 353 | + goto out_stateowner; |
| 354 | + |
| 355 | + set_bit(NFS_OPEN_STATE, &ctx->state->flags); |
| 356 | + memcpy(&ctx->state->open_stateid.other, &stateid->other, |
| 357 | + NFS4_STATEID_OTHER_SIZE); |
| 358 | + update_open_stateid(ctx->state, stateid, NULL, filep->f_mode); |
| 359 | + |
| 360 | + nfs_file_set_open_context(filep, ctx); |
| 361 | + put_nfs_open_context(ctx); |
| 362 | + |
| 363 | + file_ra_state_init(&filep->f_ra, filep->f_mapping->host->i_mapping); |
| 364 | + res = filep; |
| 365 | +out: |
| 366 | + return res; |
| 367 | +out_stateowner: |
| 368 | + nfs4_put_state_owner(sp); |
| 369 | +out_ctx: |
| 370 | + put_nfs_open_context(ctx); |
| 371 | +out_filep: |
| 372 | + fput(filep); |
| 373 | + goto out; |
| 374 | +} |
| 375 | +EXPORT_SYMBOL_GPL(nfs42_ssc_open); |
| 376 | +void nfs42_ssc_close(struct file *filep) |
| 377 | +{ |
| 378 | + struct nfs_open_context *ctx = nfs_file_open_context(filep); |
| 379 | + |
| 380 | + ctx->state->flags = 0; |
| 381 | +} |
| 382 | +EXPORT_SYMBOL_GPL(nfs42_ssc_close); |
289 | 383 | #endif /* CONFIG_NFS_V4_2 */
|
290 | 384 |
|
291 | 385 | const struct file_operations nfs4_file_operations = {
|
|
0 commit comments