struct timespec *mtime, struct timespec *atime,
u64 time_warp_seq,
uid_t uid, gid_t gid, mode_t mode,
+ void *xattrs_blob, int xattrs_blob_size,
u64 follows, int mds)
{
struct ceph_mds_caps *fc;
ceph_cap_string(dirty),
seq, mseq, follows, size);
- msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, sizeof(*fc), 0, 0, NULL);
+ msg = ceph_msg_new(CEPH_MSG_CLIENT_CAPS, sizeof(*fc) + xattrs_blob_size, 0, 0, NULL);
if (IS_ERR(msg))
return;
fc->gid = cpu_to_le32(gid);
fc->mode = cpu_to_le32(mode);
+ fc->xattrs_blob_size = xattrs_blob_size;
+ memcpy(&fc->xattrs_blob[0], xattrs_blob, xattrs_blob_size);
+
ceph_send_msg_mds(mdsc, msg, mds);
}
uid_t uid;
gid_t gid;
int mds = cap->session->s_mds;
+ void *xattrs_blob;
+ int xattrs_blob_size;
dout(10, "__send_cap cap %p session %p %s -> %s (revoking %s)\n",
cap, cap->session,
uid = inode->i_uid;
gid = inode->i_gid;
mode = inode->i_mode;
+
+ if (dropping & CEPH_CAP_XATTR_RDCACHE) {
+ __ceph_build_xattrs_blob(ci, &xattrs_blob, &xattrs_blob_size);
+ ci->i_xattrs.prealloc_blob = 0;
+ ci->i_xattrs.prealloc_size = 0;
+ } else {
+ xattrs_blob = NULL;
+ }
spin_unlock(&inode->i_lock);
if (dropping & CEPH_CAP_FILE_RDCACHE) {
op, keep, want, flushing, seq, mseq,
size, max_size, &mtime, &atime, time_warp_seq,
uid, gid, mode,
+ xattrs_blob, xattrs_blob_size,
follows, mds);
+ if (xattrs_blob)
+ kfree(xattrs_blob);
+
if (wake)
wake_up(&ci->i_cap_wq);
}
&capsnap->mtime, &capsnap->atime,
capsnap->time_warp_seq,
capsnap->uid, capsnap->gid, capsnap->mode,
+ NULL, 0,
capsnap->follows, mds);
next_follows = capsnap->follows + 1;
return err;
}
-void *__ceph_build_xattrs_blob(struct ceph_inode_info *ci)
+int __get_required_blob_size(struct ceph_inode_info *ci)
+{
+ return 4 + ci->i_xattrs.count*(4 + 4) +
+ ci->i_xattrs.names_size +
+ ci->i_xattrs.vals_size;
+}
+
+void __ceph_build_xattrs_blob(struct ceph_inode_info *ci,
+ void **xattrs_blob,
+ int *blob_size)
{
struct rb_node *p;
struct ceph_inode_xattr *xattr = NULL;
void *dest;
if (ci->i_xattrs.names_size) {
- BUG_ON(!ci->i_xattrs.prealloc_blob);
+ int required_blob_size = __get_required_blob_size(ci);
+
+ BUG_ON(required_blob_size > ci->i_xattrs.prealloc_size);
p = rb_first(&ci->i_xattrs.xattrs);
p = rb_next(p);
}
- return ci->i_xattrs.prealloc_blob;
+ *xattrs_blob = ci->i_xattrs.prealloc_blob;
+ *blob_size = ci->i_xattrs.prealloc_size;
} else {
- /*just use the blob that we hold */
- return ci->i_xattrs.data;
+ /* actually, we're using the same data that we got from the
+ mds, don't build anything */
+ *xattrs_blob = NULL;
+ *blob_size = 0;
}
}
return err;
}
-int __get_required_blob_size(struct ceph_inode_info *ci)
-{
- return 4 + ci->i_xattrs.count*(4 + 4) +
- ci->i_xattrs.names_size +
- ci->i_xattrs.vals_size;
-}
-
int ceph_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size, int flags)
{
extern ssize_t ceph_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t ceph_listxattr(struct dentry *, char *, size_t);
extern int ceph_removexattr(struct dentry *, const char *);
+extern void __ceph_build_xattrs_blob(struct ceph_inode_info *ci,
+ void **xattrs_blob,
+ int *blob_size);
/* caps.c */
extern const char *ceph_cap_string(int c);