/** * Copy the encoded flock and fcntl locks into the pagelist. * Format is: #fcntl locks, sequential fcntl locks, #flock locks, * sequential flock locks. * Returns zero on success. */ int ceph_locks_to_pagelist(struct ceph_filelock *flocks, struct ceph_pagelist *pagelist, int num_fcntl_locks, int num_flock_locks) { int err = 0; __le32 nlocks; nlocks = cpu_to_le32(num_fcntl_locks); err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks)); if (err) goto out_fail; err = ceph_pagelist_append(pagelist, flocks, num_fcntl_locks * sizeof(*flocks)); if (err) goto out_fail; nlocks = cpu_to_le32(num_flock_locks); err = ceph_pagelist_append(pagelist, &nlocks, sizeof(nlocks)); if (err) goto out_fail; err = ceph_pagelist_append(pagelist, &flocks[num_fcntl_locks], num_flock_locks * sizeof(*flocks)); out_fail: return err; }
/** * Encode the flock and fcntl locks for the given inode into the pagelist. * Format is: #fcntl locks, sequential fcntl locks, #flock locks, * sequential flock locks. * Must be called with lock_flocks() already held. * If we encounter more of a specific lock type than expected, * we return the value 1. */ int ceph_encode_locks(struct inode *inode, struct ceph_pagelist *pagelist, int num_fcntl_locks, int num_flock_locks) { struct file_lock *lock; struct ceph_filelock cephlock; int err = 0; int seen_fcntl = 0; int seen_flock = 0; dout("encoding %d flock and %d fcntl locks", num_flock_locks, num_fcntl_locks); err = ceph_pagelist_append(pagelist, &num_fcntl_locks, sizeof(u32)); if (err) goto fail; for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_POSIX) { ++seen_fcntl; if (seen_fcntl > num_fcntl_locks) { err = -ENOSPC; goto fail; } err = lock_to_ceph_filelock(lock, &cephlock); if (err) goto fail; err = ceph_pagelist_append(pagelist, &cephlock, sizeof(struct ceph_filelock)); } if (err) goto fail; } err = ceph_pagelist_append(pagelist, &num_flock_locks, sizeof(u32)); if (err) goto fail; for (lock = inode->i_flock; lock != NULL; lock = lock->fl_next) { if (lock->fl_flags & FL_FLOCK) { ++seen_flock; if (seen_flock > num_flock_locks) { err = -ENOSPC; goto fail; } err = lock_to_ceph_filelock(lock, &cephlock); if (err) goto fail; err = ceph_pagelist_append(pagelist, &cephlock, sizeof(struct ceph_filelock)); } if (err) goto fail; } fail: return err; }
static void osd_req_encode_op(struct ceph_osd_request *req, struct ceph_osd_op *dst, struct ceph_osd_req_op *src) { dst->op = cpu_to_le16(src->op); switch (src->op) { case CEPH_OSD_OP_READ: case CEPH_OSD_OP_WRITE: dst->extent.offset = cpu_to_le64(src->extent.offset); dst->extent.length = cpu_to_le64(src->extent.length); dst->extent.truncate_size = cpu_to_le64(src->extent.truncate_size); dst->extent.truncate_seq = cpu_to_le32(src->extent.truncate_seq); break; case CEPH_OSD_OP_GETXATTR: case CEPH_OSD_OP_SETXATTR: case CEPH_OSD_OP_CMPXATTR: BUG_ON(!req->r_trail); dst->xattr.name_len = cpu_to_le32(src->xattr.name_len); dst->xattr.value_len = cpu_to_le32(src->xattr.value_len); dst->xattr.cmp_op = src->xattr.cmp_op; dst->xattr.cmp_mode = src->xattr.cmp_mode; ceph_pagelist_append(req->r_trail, src->xattr.name, src->xattr.name_len); ceph_pagelist_append(req->r_trail, src->xattr.val, src->xattr.value_len); break; case CEPH_OSD_OP_CALL: BUG_ON(!req->r_trail); dst->cls.class_len = src->cls.class_len; dst->cls.method_len = src->cls.method_len; dst->cls.indata_len = cpu_to_le32(src->cls.indata_len); ceph_pagelist_append(req->r_trail, src->cls.class_name, src->cls.class_len); ceph_pagelist_append(req->r_trail, src->cls.method_name, src->cls.method_len); ceph_pagelist_append(req->r_trail, src->cls.indata, src->cls.indata_len); break; case CEPH_OSD_OP_ROLLBACK: dst->snap.snapid = cpu_to_le64(src->snap.snapid); break; case CEPH_OSD_OP_STARTSYNC: break; case CEPH_OSD_OP_NOTIFY: { __le32 prot_ver = cpu_to_le32(src->watch.prot_ver); __le32 timeout = cpu_to_le32(src->watch.timeout); BUG_ON(!req->r_trail); ceph_pagelist_append(req->r_trail, &prot_ver, sizeof(prot_ver)); ceph_pagelist_append(req->r_trail, &timeout, sizeof(timeout)); } case CEPH_OSD_OP_NOTIFY_ACK: case CEPH_OSD_OP_WATCH: dst->watch.cookie = cpu_to_le64(src->watch.cookie); dst->watch.ver = cpu_to_le64(src->watch.ver); dst->watch.flag = src->watch.flag; break; default: pr_err("unrecognized osd opcode %d\n", dst->op); WARN_ON(1); break; } dst->payload_len = cpu_to_le32(src->payload_len); }
int ceph_pre_init_acls(struct inode *dir, umode_t *mode, struct ceph_acls_info *info) { struct posix_acl *acl, *default_acl; size_t val_size1 = 0, val_size2 = 0; struct ceph_pagelist *pagelist = NULL; void *tmp_buf = NULL; int err; err = posix_acl_create(dir, mode, &default_acl, &acl); if (err) return err; if (acl) { int ret = posix_acl_equiv_mode(acl, mode); if (ret < 0) goto out_err; if (ret == 0) { posix_acl_release(acl); acl = NULL; } } if (!default_acl && !acl) return 0; if (acl) val_size1 = posix_acl_xattr_size(acl->a_count); if (default_acl) val_size2 = posix_acl_xattr_size(default_acl->a_count); err = -ENOMEM; tmp_buf = kmalloc(max(val_size1, val_size2), GFP_KERNEL); if (!tmp_buf) goto out_err; pagelist = kmalloc(sizeof(struct ceph_pagelist), GFP_KERNEL); if (!pagelist) goto out_err; ceph_pagelist_init(pagelist); err = ceph_pagelist_reserve(pagelist, PAGE_SIZE); if (err) goto out_err; ceph_pagelist_encode_32(pagelist, acl && default_acl ? 2 : 1); if (acl) { size_t len = strlen(XATTR_NAME_POSIX_ACL_ACCESS); err = ceph_pagelist_reserve(pagelist, len + val_size1 + 8); if (err) goto out_err; ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_ACCESS, len); err = posix_acl_to_xattr(&init_user_ns, acl, tmp_buf, val_size1); if (err < 0) goto out_err; ceph_pagelist_encode_32(pagelist, val_size1); ceph_pagelist_append(pagelist, tmp_buf, val_size1); } if (default_acl) { size_t len = strlen(XATTR_NAME_POSIX_ACL_DEFAULT); err = ceph_pagelist_reserve(pagelist, len + val_size2 + 8); if (err) goto out_err; err = ceph_pagelist_encode_string(pagelist, XATTR_NAME_POSIX_ACL_DEFAULT, len); err = posix_acl_to_xattr(&init_user_ns, default_acl, tmp_buf, val_size2); if (err < 0) goto out_err; ceph_pagelist_encode_32(pagelist, val_size2); ceph_pagelist_append(pagelist, tmp_buf, val_size2); } kfree(tmp_buf); info->acl = acl; info->default_acl = default_acl; info->pagelist = pagelist; return 0; out_err: posix_acl_release(acl); posix_acl_release(default_acl); kfree(tmp_buf); if (pagelist) ceph_pagelist_release(pagelist); return err; }