Skip to content

Commit 31143d5

Browse files
dhowellsLinus Torvalds
authored andcommitted
AFS: implement basic file write support
Implement support for writing to regular AFS files, including: (1) write (2) truncate (3) fsync, fdatasync (4) chmod, chown, chgrp, utime. AFS writeback attempts to batch writes into as chunks as large as it can manage up to the point that it writes back 65535 pages in one chunk or it meets a locked page. Furthermore, if a page has been written to using a particular key, then should another write to that page use some other key, the first write will be flushed before the second is allowed to take place. If the first write fails due to a security error, then the page will be scrapped and reread before the second write takes place. If a page is dirty and the callback on it is broken by the server, then the dirty data is not discarded (same behaviour as NFS). Shared-writable mappings are not supported by this patch. [akpm@linux-foundation.org: fix a bunch of warnings] Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
1 parent 416351f commit 31143d5

File tree

11 files changed

+1483
-27
lines changed

11 files changed

+1483
-27
lines changed

fs/afs/Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ kafs-objs := \
2222
vlclient.o \
2323
vlocation.o \
2424
vnode.o \
25-
volume.o
25+
volume.o \
26+
write.o
2627

2728
obj-$(CONFIG_AFS_FS) := kafs.o

fs/afs/afs_fs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
enum AFS_FS_Operations {
1919
FSFETCHDATA = 130, /* AFS Fetch file data */
2020
FSFETCHSTATUS = 132, /* AFS Fetch file status */
21+
FSSTOREDATA = 133, /* AFS Store file data */
22+
FSSTORESTATUS = 135, /* AFS Store file status */
2123
FSREMOVEFILE = 136, /* AFS Remove a file */
2224
FSCREATEFILE = 137, /* AFS Create a file */
2325
FSRENAME = 138, /* AFS Rename or move a file or directory */

fs/afs/dir.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ const struct inode_operations afs_dir_inode_operations = {
5656
.rename = afs_rename,
5757
.permission = afs_permission,
5858
.getattr = afs_getattr,
59+
.setattr = afs_setattr,
5960
};
6061

6162
static struct dentry_operations afs_fs_dentry_operations = {

fs/afs/file.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,32 +15,43 @@
1515
#include <linux/slab.h>
1616
#include <linux/fs.h>
1717
#include <linux/pagemap.h>
18+
#include <linux/writeback.h>
1819
#include "internal.h"
1920

2021
static int afs_readpage(struct file *file, struct page *page);
2122
static void afs_invalidatepage(struct page *page, unsigned long offset);
2223
static int afs_releasepage(struct page *page, gfp_t gfp_flags);
24+
static int afs_launder_page(struct page *page);
2325

2426
const struct file_operations afs_file_operations = {
2527
.open = afs_open,
2628
.release = afs_release,
2729
.llseek = generic_file_llseek,
2830
.read = do_sync_read,
31+
.write = do_sync_write,
2932
.aio_read = generic_file_aio_read,
33+
.aio_write = afs_file_write,
3034
.mmap = generic_file_readonly_mmap,
3135
.sendfile = generic_file_sendfile,
36+
.fsync = afs_fsync,
3237
};
3338

3439
const struct inode_operations afs_file_inode_operations = {
3540
.getattr = afs_getattr,
41+
.setattr = afs_setattr,
3642
.permission = afs_permission,
3743
};
3844

3945
const struct address_space_operations afs_fs_aops = {
4046
.readpage = afs_readpage,
41-
.set_page_dirty = __set_page_dirty_nobuffers,
47+
.set_page_dirty = afs_set_page_dirty,
48+
.launder_page = afs_launder_page,
4249
.releasepage = afs_releasepage,
4350
.invalidatepage = afs_invalidatepage,
51+
.prepare_write = afs_prepare_write,
52+
.commit_write = afs_commit_write,
53+
.writepage = afs_writepage,
54+
.writepages = afs_writepages,
4455
};
4556

4657
/*
@@ -230,11 +241,6 @@ static void afs_invalidatepage(struct page *page, unsigned long offset)
230241
BUG_ON(!PageLocked(page));
231242

232243
if (PagePrivate(page)) {
233-
#ifdef AFS_CACHING_SUPPORT
234-
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
235-
cachefs_uncache_page(vnode->cache,page);
236-
#endif
237-
238244
/* We release buffers only if the entire page is being
239245
* invalidated.
240246
* The get_block cached value has been unconditionally
@@ -254,20 +260,34 @@ static void afs_invalidatepage(struct page *page, unsigned long offset)
254260
_leave(" = %d", ret);
255261
}
256262

263+
/*
264+
* write back a dirty page
265+
*/
266+
static int afs_launder_page(struct page *page)
267+
{
268+
_enter("{%lu}", page->index);
269+
270+
return 0;
271+
}
272+
257273
/*
258274
* release a page and cleanup its private data
259275
*/
260276
static int afs_releasepage(struct page *page, gfp_t gfp_flags)
261277
{
262278
struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
279+
struct afs_writeback *wb;
263280

264281
_enter("{{%x:%u}[%lu],%lx},%x",
265282
vnode->fid.vid, vnode->fid.vnode, page->index, page->flags,
266283
gfp_flags);
267284

268285
if (PagePrivate(page)) {
286+
wb = (struct afs_writeback *) page_private(page);
287+
ASSERT(wb != NULL);
269288
set_page_private(page, 0);
270289
ClearPagePrivate(page);
290+
afs_put_writeback(wb);
271291
}
272292

273293
_leave(" = 0");

0 commit comments

Comments
 (0)