Skip to content

Commit 4343d00

Browse files
committed
afs: Get rid of the afs_writeback record
Get rid of the afs_writeback record that kAFS is using to match keys with writes made by that key. Instead, keep a list of keys that have a file open for writing and/or sync'ing and iterate through those. Signed-off-by: David Howells <[email protected]>
1 parent 215804a commit 4343d00

File tree

7 files changed

+412
-395
lines changed

7 files changed

+412
-395
lines changed

fs/afs/file.c

Lines changed: 57 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ static int afs_readpage(struct file *file, struct page *page);
2323
static void afs_invalidatepage(struct page *page, unsigned int offset,
2424
unsigned int length);
2525
static int afs_releasepage(struct page *page, gfp_t gfp_flags);
26-
static int afs_launder_page(struct page *page);
2726

2827
static int afs_readpages(struct file *filp, struct address_space *mapping,
2928
struct list_head *pages, unsigned nr_pages);
@@ -62,6 +61,50 @@ const struct address_space_operations afs_fs_aops = {
6261
.writepages = afs_writepages,
6362
};
6463

64+
/*
65+
* Discard a pin on a writeback key.
66+
*/
67+
void afs_put_wb_key(struct afs_wb_key *wbk)
68+
{
69+
if (refcount_dec_and_test(&wbk->usage)) {
70+
key_put(wbk->key);
71+
kfree(wbk);
72+
}
73+
}
74+
75+
/*
76+
* Cache key for writeback.
77+
*/
78+
int afs_cache_wb_key(struct afs_vnode *vnode, struct afs_file *af)
79+
{
80+
struct afs_wb_key *wbk, *p;
81+
82+
wbk = kzalloc(sizeof(struct afs_wb_key), GFP_KERNEL);
83+
if (!wbk)
84+
return -ENOMEM;
85+
refcount_set(&wbk->usage, 2);
86+
wbk->key = af->key;
87+
88+
spin_lock(&vnode->wb_lock);
89+
list_for_each_entry(p, &vnode->wb_keys, vnode_link) {
90+
if (p->key == wbk->key)
91+
goto found;
92+
}
93+
94+
key_get(wbk->key);
95+
list_add_tail(&wbk->vnode_link, &vnode->wb_keys);
96+
spin_unlock(&vnode->wb_lock);
97+
af->wb = wbk;
98+
return 0;
99+
100+
found:
101+
refcount_inc(&p->usage);
102+
spin_unlock(&vnode->wb_lock);
103+
af->wb = p;
104+
kfree(wbk);
105+
return 0;
106+
}
107+
65108
/*
66109
* open an AFS file or directory and attach a key to it
67110
*/
@@ -85,12 +128,18 @@ int afs_open(struct inode *inode, struct file *file)
85128
ret = -ENOMEM;
86129
goto error_key;
87130
}
131+
af->key = key;
88132

89133
ret = afs_validate(vnode, key);
90134
if (ret < 0)
91135
goto error_af;
92136

93-
af->key = key;
137+
if (file->f_mode & FMODE_WRITE) {
138+
ret = afs_cache_wb_key(vnode, af);
139+
if (ret < 0)
140+
goto error_af;
141+
}
142+
94143
file->private_data = af;
95144
_leave(" = 0");
96145
return 0;
@@ -115,8 +164,11 @@ int afs_release(struct inode *inode, struct file *file)
115164
_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);
116165

117166
file->private_data = NULL;
167+
if (af->wb)
168+
afs_put_wb_key(af->wb);
118169
key_put(af->key);
119170
kfree(af);
171+
afs_prune_wb_keys(vnode);
120172
_leave(" = 0");
121173
return 0;
122174
}
@@ -516,16 +568,6 @@ static int afs_readpages(struct file *file, struct address_space *mapping,
516568
return ret;
517569
}
518570

519-
/*
520-
* write back a dirty page
521-
*/
522-
static int afs_launder_page(struct page *page)
523-
{
524-
_enter("{%lu}", page->index);
525-
526-
return 0;
527-
}
528-
529571
/*
530572
* invalidate part or all of a page
531573
* - release a page and clean up its private data if offset is 0 (indicating
@@ -534,8 +576,6 @@ static int afs_launder_page(struct page *page)
534576
static void afs_invalidatepage(struct page *page, unsigned int offset,
535577
unsigned int length)
536578
{
537-
struct afs_writeback *wb = (struct afs_writeback *) page_private(page);
538-
539579
_enter("{%lu},%u,%u", page->index, offset, length);
540580

541581
BUG_ON(!PageLocked(page));
@@ -551,13 +591,8 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
551591
#endif
552592

553593
if (PagePrivate(page)) {
554-
if (wb && !PageWriteback(page)) {
555-
set_page_private(page, 0);
556-
afs_put_writeback(wb);
557-
}
558-
559-
if (!page_private(page))
560-
ClearPagePrivate(page);
594+
set_page_private(page, 0);
595+
ClearPagePrivate(page);
561596
}
562597
}
563598

@@ -570,7 +605,6 @@ static void afs_invalidatepage(struct page *page, unsigned int offset,
570605
*/
571606
static int afs_releasepage(struct page *page, gfp_t gfp_flags)
572607
{
573-
struct afs_writeback *wb = (struct afs_writeback *) page_private(page);
574608
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
575609

576610
_enter("{{%x:%u}[%lu],%lx},%x",
@@ -587,10 +621,7 @@ static int afs_releasepage(struct page *page, gfp_t gfp_flags)
587621
#endif
588622

589623
if (PagePrivate(page)) {
590-
if (wb) {
591-
set_page_private(page, 0);
592-
afs_put_writeback(wb);
593-
}
624+
set_page_private(page, 0);
594625
ClearPagePrivate(page);
595626
}
596627

fs/afs/fsclient.c

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1119,29 +1119,28 @@ static const struct afs_call_type afs_RXFSStoreData64 = {
11191119
* store a set of pages to a very large file
11201120
*/
11211121
static int afs_fs_store_data64(struct afs_fs_cursor *fc,
1122-
struct afs_writeback *wb,
1122+
struct address_space *mapping,
11231123
pgoff_t first, pgoff_t last,
11241124
unsigned offset, unsigned to,
11251125
loff_t size, loff_t pos, loff_t i_size)
11261126
{
1127-
struct afs_vnode *vnode = wb->vnode;
1127+
struct afs_vnode *vnode = fc->vnode;
11281128
struct afs_call *call;
11291129
struct afs_net *net = afs_v2net(vnode);
11301130
__be32 *bp;
11311131

11321132
_enter(",%x,{%x:%u},,",
1133-
key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1133+
key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
11341134

11351135
call = afs_alloc_flat_call(net, &afs_RXFSStoreData64,
11361136
(4 + 6 + 3 * 2) * 4,
11371137
(21 + 6) * 4);
11381138
if (!call)
11391139
return -ENOMEM;
11401140

1141-
call->wb = wb;
1142-
call->key = wb->key;
1141+
call->key = fc->key;
1142+
call->mapping = mapping;
11431143
call->reply[0] = vnode;
1144-
call->mapping = vnode->vfs_inode.i_mapping;
11451144
call->first = first;
11461145
call->last = last;
11471146
call->first_offset = offset;
@@ -1177,18 +1176,18 @@ static int afs_fs_store_data64(struct afs_fs_cursor *fc,
11771176
/*
11781177
* store a set of pages
11791178
*/
1180-
int afs_fs_store_data(struct afs_fs_cursor *fc, struct afs_writeback *wb,
1179+
int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
11811180
pgoff_t first, pgoff_t last,
11821181
unsigned offset, unsigned to)
11831182
{
1184-
struct afs_vnode *vnode = wb->vnode;
1183+
struct afs_vnode *vnode = fc->vnode;
11851184
struct afs_call *call;
11861185
struct afs_net *net = afs_v2net(vnode);
11871186
loff_t size, pos, i_size;
11881187
__be32 *bp;
11891188

11901189
_enter(",%x,{%x:%u},,",
1191-
key_serial(wb->key), vnode->fid.vid, vnode->fid.vnode);
1190+
key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);
11921191

11931192
size = (loff_t)to - (loff_t)offset;
11941193
if (first != last)
@@ -1205,7 +1204,7 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct afs_writeback *wb,
12051204
(unsigned long long) i_size);
12061205

12071206
if (pos >> 32 || i_size >> 32 || size >> 32 || (pos + size) >> 32)
1208-
return afs_fs_store_data64(fc, wb, first, last, offset, to,
1207+
return afs_fs_store_data64(fc, mapping, first, last, offset, to,
12091208
size, pos, i_size);
12101209

12111210
call = afs_alloc_flat_call(net, &afs_RXFSStoreData,
@@ -1214,10 +1213,9 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct afs_writeback *wb,
12141213
if (!call)
12151214
return -ENOMEM;
12161215

1217-
call->wb = wb;
1218-
call->key = wb->key;
1216+
call->key = fc->key;
1217+
call->mapping = mapping;
12191218
call->reply[0] = vnode;
1220-
call->mapping = vnode->vfs_inode.i_mapping;
12211219
call->first = first;
12221220
call->last = last;
12231221
call->first_offset = offset;

fs/afs/inode.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,12 @@ void afs_evict_inode(struct inode *inode)
482482
vnode->cb_interest = NULL;
483483
}
484484

485-
ASSERT(list_empty(&vnode->writebacks));
485+
while (!list_empty(&vnode->wb_keys)) {
486+
struct afs_wb_key *wbk = list_entry(vnode->wb_keys.next,
487+
struct afs_wb_key, vnode_link);
488+
list_del(&wbk->vnode_link);
489+
afs_put_wb_key(wbk);
490+
}
486491

487492
#ifdef CONFIG_AFS_FSCACHE
488493
fscache_relinquish_cookie(vnode->cache, 0);
@@ -514,10 +519,8 @@ int afs_setattr(struct dentry *dentry, struct iattr *attr)
514519
}
515520

516521
/* flush any dirty data outstanding on a regular file */
517-
if (S_ISREG(vnode->vfs_inode.i_mode)) {
522+
if (S_ISREG(vnode->vfs_inode.i_mode))
518523
filemap_write_and_wait(vnode->vfs_inode.i_mapping);
519-
afs_writeback_all(vnode);
520-
}
521524

522525
if (attr->ia_valid & ATTR_FILE) {
523526
key = afs_file_key(attr->ia_file);

fs/afs/internal.h

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,7 @@ struct afs_call {
8989
struct afs_server *cm_server; /* Server affected by incoming CM call */
9090
struct afs_cb_interest *cbi; /* Callback interest for server used */
9191
void *request; /* request data (first part) */
92-
struct address_space *mapping; /* page set */
93-
struct afs_writeback *wb; /* writeback being performed */
92+
struct address_space *mapping; /* Pages being written from */
9493
void *buffer; /* reply receive buffer */
9594
void *reply[4]; /* Where to put the reply */
9695
pgoff_t first; /* first page in mapping to deal with */
@@ -138,11 +137,21 @@ struct afs_call_type {
138137
void (*work)(struct work_struct *work);
139138
};
140139

140+
/*
141+
* Key available for writeback on a file.
142+
*/
143+
struct afs_wb_key {
144+
refcount_t usage;
145+
struct key *key;
146+
struct list_head vnode_link; /* Link in vnode->wb_keys */
147+
};
148+
141149
/*
142150
* AFS open file information record. Pointed to by file->private_data.
143151
*/
144152
struct afs_file {
145153
struct key *key; /* The key this file was opened with */
154+
struct afs_wb_key *wb; /* Writeback key record for this file */
146155
};
147156

148157
static inline struct key *afs_file_key(struct file *file)
@@ -167,32 +176,6 @@ struct afs_read {
167176
struct page *pages[];
168177
};
169178

170-
/*
171-
* record of an outstanding writeback on a vnode
172-
*/
173-
struct afs_writeback {
174-
struct list_head link; /* link in vnode->writebacks */
175-
struct work_struct writer; /* work item to perform the writeback */
176-
struct afs_vnode *vnode; /* vnode to which this write applies */
177-
struct key *key; /* owner of this write */
178-
wait_queue_head_t waitq; /* completion and ready wait queue */
179-
pgoff_t first; /* first page in batch */
180-
pgoff_t point; /* last page in current store op */
181-
pgoff_t last; /* last page in batch (inclusive) */
182-
unsigned offset_first; /* offset into first page of start of write */
183-
unsigned to_last; /* offset into last page of end of write */
184-
int num_conflicts; /* count of conflicting writes in list */
185-
int usage;
186-
bool conflicts; /* T if has dependent conflicts */
187-
enum {
188-
AFS_WBACK_SYNCING, /* synchronisation being performed */
189-
AFS_WBACK_PENDING, /* write pending */
190-
AFS_WBACK_CONFLICTING, /* conflicting writes posted */
191-
AFS_WBACK_WRITING, /* writing back */
192-
AFS_WBACK_COMPLETE /* the writeback record has been unlinked */
193-
} state __attribute__((packed));
194-
};
195-
196179
/*
197180
* AFS superblock private data
198181
* - there's one superblock per volume
@@ -460,7 +443,7 @@ struct afs_vnode {
460443
struct afs_permits *permit_cache; /* cache of permits so far obtained */
461444
struct mutex io_lock; /* Lock for serialising I/O on this mutex */
462445
struct mutex validate_lock; /* lock for validating this vnode */
463-
spinlock_t writeback_lock; /* lock for writebacks */
446+
spinlock_t wb_lock; /* lock for wb_keys */
464447
spinlock_t lock; /* waitqueue/flags lock */
465448
unsigned long flags;
466449
#define AFS_VNODE_CB_PROMISED 0 /* Set if vnode has a callback promise */
@@ -476,7 +459,7 @@ struct afs_vnode {
476459
#define AFS_VNODE_AUTOCELL 10 /* set if Vnode is an auto mount point */
477460
#define AFS_VNODE_PSEUDODIR 11 /* set if Vnode is a pseudo directory */
478461

479-
struct list_head writebacks; /* alterations in pagecache that need writing */
462+
struct list_head wb_keys; /* List of keys available for writeback */
480463
struct list_head pending_locks; /* locks waiting to be granted */
481464
struct list_head granted_locks; /* locks granted on this file */
482465
struct delayed_work lock_work; /* work to be done in locking */
@@ -648,6 +631,8 @@ extern const struct address_space_operations afs_fs_aops;
648631
extern const struct inode_operations afs_file_inode_operations;
649632
extern const struct file_operations afs_file_operations;
650633

634+
extern int afs_cache_wb_key(struct afs_vnode *, struct afs_file *);
635+
extern void afs_put_wb_key(struct afs_wb_key *);
651636
extern int afs_open(struct inode *, struct file *);
652637
extern int afs_release(struct inode *, struct file *);
653638
extern int afs_fetch_data(struct afs_vnode *, struct key *, struct afs_read *);
@@ -678,7 +663,7 @@ extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *,
678663
struct afs_fid *, struct afs_file_status *);
679664
extern int afs_fs_rename(struct afs_fs_cursor *, const char *,
680665
struct afs_vnode *, const char *);
681-
extern int afs_fs_store_data(struct afs_fs_cursor *, struct afs_writeback *,
666+
extern int afs_fs_store_data(struct afs_fs_cursor *, struct address_space *,
682667
pgoff_t, pgoff_t, unsigned, unsigned);
683668
extern int afs_fs_setattr(struct afs_fs_cursor *, struct iattr *);
684669
extern int afs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *);
@@ -889,7 +874,6 @@ extern int afs_check_volume_status(struct afs_volume *, struct key *);
889874
* write.c
890875
*/
891876
extern int afs_set_page_dirty(struct page *);
892-
extern void afs_put_writeback(struct afs_writeback *);
893877
extern int afs_write_begin(struct file *file, struct address_space *mapping,
894878
loff_t pos, unsigned len, unsigned flags,
895879
struct page **pagep, void **fsdata);
@@ -900,9 +884,10 @@ extern int afs_writepage(struct page *, struct writeback_control *);
900884
extern int afs_writepages(struct address_space *, struct writeback_control *);
901885
extern void afs_pages_written_back(struct afs_vnode *, struct afs_call *);
902886
extern ssize_t afs_file_write(struct kiocb *, struct iov_iter *);
903-
extern int afs_writeback_all(struct afs_vnode *);
904887
extern int afs_flush(struct file *, fl_owner_t);
905888
extern int afs_fsync(struct file *, loff_t, loff_t, int);
889+
extern void afs_prune_wb_keys(struct afs_vnode *);
890+
extern int afs_launder_page(struct page *);
906891

907892
/*
908893
* xattr.c

fs/afs/super.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,9 +546,9 @@ static void afs_i_init_once(void *_vnode)
546546
inode_init_once(&vnode->vfs_inode);
547547
mutex_init(&vnode->io_lock);
548548
mutex_init(&vnode->validate_lock);
549-
spin_lock_init(&vnode->writeback_lock);
549+
spin_lock_init(&vnode->wb_lock);
550550
spin_lock_init(&vnode->lock);
551-
INIT_LIST_HEAD(&vnode->writebacks);
551+
INIT_LIST_HEAD(&vnode->wb_keys);
552552
INIT_LIST_HEAD(&vnode->pending_locks);
553553
INIT_LIST_HEAD(&vnode->granted_locks);
554554
INIT_DELAYED_WORK(&vnode->lock_work, afs_lock_work);

0 commit comments

Comments
 (0)