get caps for a given file handle -- the inode should have @need caps issued by the mds and @want caps not revoked (or not under revocation). this routine blocks till the cap requirement is satisfied. also account (track) for capability hit when required (when cap requirement succeedes).
| 3910 | // this routine blocks till the cap requirement is satisfied. also account |
| 3911 | // (track) for capability hit when required (when cap requirement succeedes). |
| 3912 | int Client::get_caps(Fh *fh, int need, int want, int *phave, loff_t endoff) |
| 3913 | { |
| 3914 | Inode *in = fh->inode.get(); |
| 3915 | |
| 3916 | int r = check_pool_perm(in, need); |
| 3917 | if (r < 0) |
| 3918 | return r; |
| 3919 | |
| 3920 | while (1) { |
| 3921 | int file_wanted = in->caps_file_wanted(); |
| 3922 | if ((file_wanted & need) != need) { |
| 3923 | ldout(cct, 10) << "get_caps " << *in << " need " << ccap_string(need) |
| 3924 | << " file_wanted " << ccap_string(file_wanted) << ", EBADF " |
| 3925 | << dendl; |
| 3926 | return -EBADF; |
| 3927 | } |
| 3928 | |
| 3929 | if ((fh->mode & CEPH_FILE_MODE_WR) && fh->gen != fd_gen) |
| 3930 | return -EBADF; |
| 3931 | |
| 3932 | if ((in->flags & I_ERROR_FILELOCK) && fh->has_any_filelocks()) |
| 3933 | return -EIO; |
| 3934 | |
| 3935 | int implemented; |
| 3936 | int have = in->caps_issued(&implemented); |
| 3937 | |
| 3938 | bool waitfor_caps = false; |
| 3939 | bool waitfor_commit = false; |
| 3940 | |
| 3941 | if (have & need & CEPH_CAP_FILE_WR) { |
| 3942 | if (endoff > 0) { |
| 3943 | if ((endoff >= (loff_t)in->max_size || |
| 3944 | endoff > (loff_t)(in->size << 1)) && |
| 3945 | endoff > (loff_t)in->wanted_max_size) { |
| 3946 | ldout(cct, 10) << "wanted_max_size " << in->wanted_max_size << " -> " << endoff << dendl; |
| 3947 | uint64_t want = endoff; |
| 3948 | #if defined(__linux__) |
| 3949 | if (in->fscrypt_auth.size()) { |
| 3950 | want = fscrypt_block_start(endoff + FSCRYPT_BLOCK_SIZE - 1); |
| 3951 | } |
| 3952 | #endif |
| 3953 | in->wanted_max_size = want; |
| 3954 | } |
| 3955 | if (in->wanted_max_size > in->max_size && |
| 3956 | in->wanted_max_size > in->requested_max_size) |
| 3957 | check_caps(in, 0); |
| 3958 | } |
| 3959 | |
| 3960 | if (endoff >= 0 && endoff > (loff_t)in->max_size) { |
| 3961 | ldout(cct, 10) << "waiting on max_size, endoff " << endoff << " max_size " << in->max_size << " on " << *in << dendl; |
| 3962 | waitfor_caps = true; |
| 3963 | } |
| 3964 | if (!in->cap_snaps.empty()) { |
| 3965 | if (in->cap_snaps.rbegin()->second.writing) { |
| 3966 | ldout(cct, 10) << "waiting on cap_snap write to complete" << dendl; |
| 3967 | waitfor_caps = true; |
| 3968 | } |
| 3969 | for (auto &p : in->cap_snaps) { |
no test coverage detected