aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ceph/caps.c2
-rw-r--r--fs/ceph/snap.c23
-rw-r--r--fs/ceph/super.h8
-rw-r--r--fs/ceph/xattr.c1
4 files changed, 23 insertions, 11 deletions
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index 0ac2703f3bd..ba5bbf318fe 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -1282,7 +1282,7 @@ retry:
1282 &capsnap->mtime, &capsnap->atime, 1282 &capsnap->mtime, &capsnap->atime,
1283 capsnap->time_warp_seq, 1283 capsnap->time_warp_seq,
1284 capsnap->uid, capsnap->gid, capsnap->mode, 1284 capsnap->uid, capsnap->gid, capsnap->mode,
1285 0, NULL, 1285 capsnap->xattr_version, capsnap->xattr_blob,
1286 capsnap->follows); 1286 capsnap->follows);
1287 1287
1288 next_follows = capsnap->follows + 1; 1288 next_follows = capsnap->follows + 1;
diff --git a/fs/ceph/snap.c b/fs/ceph/snap.c
index c0b26b6badb..2cb190c2bd9 100644
--- a/fs/ceph/snap.c
+++ b/fs/ceph/snap.c
@@ -435,7 +435,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
435{ 435{
436 struct inode *inode = &ci->vfs_inode; 436 struct inode *inode = &ci->vfs_inode;
437 struct ceph_cap_snap *capsnap; 437 struct ceph_cap_snap *capsnap;
438 int used; 438 int used, dirty;
439 439
440 capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS); 440 capsnap = kzalloc(sizeof(*capsnap), GFP_NOFS);
441 if (!capsnap) { 441 if (!capsnap) {
@@ -445,6 +445,7 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
445 445
446 spin_lock(&inode->i_lock); 446 spin_lock(&inode->i_lock);
447 used = __ceph_caps_used(ci); 447 used = __ceph_caps_used(ci);
448 dirty = __ceph_caps_dirty(ci);
448 if (__ceph_have_pending_cap_snap(ci)) { 449 if (__ceph_have_pending_cap_snap(ci)) {
449 /* there is no point in queuing multiple "pending" cap_snaps, 450 /* there is no point in queuing multiple "pending" cap_snaps,
450 as no new writes are allowed to start when pending, so any 451 as no new writes are allowed to start when pending, so any
@@ -452,11 +453,13 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
452 cap_snap. lucky us. */ 453 cap_snap. lucky us. */
453 dout("queue_cap_snap %p already pending\n", inode); 454 dout("queue_cap_snap %p already pending\n", inode);
454 kfree(capsnap); 455 kfree(capsnap);
455 } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR)) { 456 } else if (ci->i_wrbuffer_ref_head || (used & CEPH_CAP_FILE_WR) ||
457 (dirty & (CEPH_CAP_AUTH_EXCL|CEPH_CAP_XATTR_EXCL|
458 CEPH_CAP_FILE_EXCL|CEPH_CAP_FILE_WR))) {
456 struct ceph_snap_context *snapc = ci->i_head_snapc; 459 struct ceph_snap_context *snapc = ci->i_head_snapc;
457 460
458 igrab(inode); 461 igrab(inode);
459 462
460 atomic_set(&capsnap->nref, 1); 463 atomic_set(&capsnap->nref, 1);
461 capsnap->ci = ci; 464 capsnap->ci = ci;
462 INIT_LIST_HEAD(&capsnap->ci_item); 465 INIT_LIST_HEAD(&capsnap->ci_item);
@@ -464,15 +467,21 @@ void ceph_queue_cap_snap(struct ceph_inode_info *ci)
464 467
465 capsnap->follows = snapc->seq - 1; 468 capsnap->follows = snapc->seq - 1;
466 capsnap->issued = __ceph_caps_issued(ci, NULL); 469 capsnap->issued = __ceph_caps_issued(ci, NULL);
467 capsnap->dirty = __ceph_caps_dirty(ci); 470 capsnap->dirty = dirty;
468 471
469 capsnap->mode = inode->i_mode; 472 capsnap->mode = inode->i_mode;
470 capsnap->uid = inode->i_uid; 473 capsnap->uid = inode->i_uid;
471 capsnap->gid = inode->i_gid; 474 capsnap->gid = inode->i_gid;
472 475
473 /* fixme? */ 476 if (dirty & CEPH_CAP_XATTR_EXCL) {
474 capsnap->xattr_blob = NULL; 477 __ceph_build_xattrs_blob(ci);
475 capsnap->xattr_len = 0; 478 capsnap->xattr_blob =
479 ceph_buffer_get(ci->i_xattrs.blob);
480 capsnap->xattr_version = ci->i_xattrs.version;
481 } else {
482 capsnap->xattr_blob = NULL;
483 capsnap->xattr_version = 0;
484 }
476 485
477 /* dirty page count moved from _head to this cap_snap; 486 /* dirty page count moved from _head to this cap_snap;
478 all subsequent writes page dirties occur _after_ this 487 all subsequent writes page dirties occur _after_ this
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 2482d696f0d..b33929d8f28 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -216,8 +216,7 @@ struct ceph_cap_snap {
216 uid_t uid; 216 uid_t uid;
217 gid_t gid; 217 gid_t gid;
218 218
219 void *xattr_blob; 219 struct ceph_buffer *xattr_blob;
220 int xattr_len;
221 u64 xattr_version; 220 u64 xattr_version;
222 221
223 u64 size; 222 u64 size;
@@ -229,8 +228,11 @@ struct ceph_cap_snap {
229 228
230static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap) 229static inline void ceph_put_cap_snap(struct ceph_cap_snap *capsnap)
231{ 230{
232 if (atomic_dec_and_test(&capsnap->nref)) 231 if (atomic_dec_and_test(&capsnap->nref)) {
232 if (capsnap->xattr_blob)
233 ceph_buffer_put(capsnap->xattr_blob);
233 kfree(capsnap); 234 kfree(capsnap);
235 }
234} 236}
235 237
236/* 238/*
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index 097a2654c00..9578af610b7 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -485,6 +485,7 @@ void __ceph_build_xattrs_blob(struct ceph_inode_info *ci)
485 ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob; 485 ci->i_xattrs.blob = ci->i_xattrs.prealloc_blob;
486 ci->i_xattrs.prealloc_blob = NULL; 486 ci->i_xattrs.prealloc_blob = NULL;
487 ci->i_xattrs.dirty = false; 487 ci->i_xattrs.dirty = false;
488 ci->i_xattrs.version++;
488 } 489 }
489} 490}
490 491