/* * If no cached dentry exists or if it's negative, NFSv4 handled the * opens in ->lookup() or ->create(). * * We only get this far for a cached positive dentry. We skipped * revalidation, so handle it here by dropping the dentry and returning * -EOPENSTALE. The VFS will retry the lookup/create/open.
*/
dprintk("NFS: open file(%pd2)\n", dentry);
err = nfs_check_flags(openflags); if (err) return err;
/* We can't create new files here */
openflags &= ~(O_CREAT|O_EXCL);
parent = dget_parent(dentry);
dir = d_inode(parent);
/* * Flush all dirty pages, and check for write errors.
*/ staticint
nfs4_file_flush(struct file *file, fl_owner_t id)
{ struct inode *inode = file_inode(file);
errseq_t since;
dprintk("NFS: flush(%pD2)\n", file);
nfs_inc_stats(inode, NFSIOS_VFSFLUSH); if ((file->f_mode & FMODE_WRITE) == 0) return 0;
/* * If we're holding a write delegation, then check if we're required * to flush the i/o on close. If not, then just start the i/o now.
*/ if (!nfs4_delegation_flush_on_close(inode)) return filemap_fdatawrite(file->f_mapping);
/* Flush writes to the server and return any errors */
since = filemap_sample_wb_err(file->f_mapping);
nfs_wb_all(inode); return filemap_check_wb_err(file->f_mapping, since);
}
/* Only offload copy if superblock is the same */ if (file_in->f_op != &nfs4_file_operations) return -EXDEV; if (!nfs_server_capable(file_inode(file_out), NFS_CAP_COPY) ||
!nfs_server_capable(file_inode(file_in), NFS_CAP_COPY)) return -EOPNOTSUPP; if (file_inode(file_in) == file_inode(file_out)) return -EOPNOTSUPP; /* if the copy size if smaller than 2 RPC payloads, make it * synchronous
*/ if (count <= 2 * NFS_SERVER(file_inode(file_in))->rsize)
sync = true;
retry: if (!nfs42_files_from_same_server(file_in, file_out)) { /* * for inter copy, if copy size is too small * then fallback to generic copy.
*/ if (sync) return -EOPNOTSUPP;
cn_resp = kzalloc(sizeof(struct nfs42_copy_notify_res),
GFP_KERNEL); if (unlikely(cn_resp == NULL)) return -ENOMEM;
ret = nfs42_proc_copy_notify(file_in, file_out, cn_resp); if (ret) {
ret = -EOPNOTSUPP; goto out;
}
nss = &cn_resp->cnr_src;
cnrs = &cn_resp->cnr_stateid;
}
ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count,
nss, cnrs, sync);
out:
kfree(cn_resp);
/* NFS does not support deduplication. */ if (remap_flags & REMAP_FILE_DEDUP) return -EOPNOTSUPP;
if (remap_flags & ~REMAP_FILE_ADVISORY) return -EINVAL;
if (IS_SWAPFILE(dst_inode) || IS_SWAPFILE(src_inode)) return -ETXTBSY;
/* check alignment w.r.t. clone_blksize */
ret = -EINVAL; if (bs) { if (!IS_ALIGNED(src_off, bs) || !IS_ALIGNED(dst_off, bs)) goto out; if (!IS_ALIGNED(count, bs) && i_size_read(src_inode) != (src_off + count)) goto out;
}
/* XXX: do we lock at all? what if server needs CB_RECALL_LAYOUT? */
lock_two_nondirectories(src_inode, dst_inode); /* flush all pending writes on both src and dst so that server
* has the latest data */
nfs_file_block_o_direct(NFS_I(src_inode));
ret = nfs_sync_inode(src_inode); if (ret) goto out_unlock;
nfs_file_block_o_direct(NFS_I(dst_inode));
ret = nfs_sync_inode(dst_inode); if (ret) goto out_unlock;
ret = nfs42_proc_clone(src_file, dst_file, src_off, dst_off, count);
/* truncate inode page cache of the dst range so that future reads can fetch
* new data from server */ if (!ret)
truncate_inode_pages_range(&dst_inode->i_data, dst_off, dst_off + count - 1);
out_unlock:
unlock_two_nondirectories(src_inode, dst_inode);
out: return ret < 0 ? ret : count;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.