Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 416351f2 authored by David Howells's avatar David Howells Committed by Linus Torvalds
Browse files

AFS: AFS fixups



Make some miscellaneous changes to the AFS filesystem:

 (1) Assert RCU barriers on module exit to make sure RCU has finished with
     callbacks in this module.

 (2) Correctly handle the AFS server returning a zero-length read.

 (3) Split out data zapping calls into one function (afs_zap_data).

 (4) Rename some afs_file_*() functions to afs_*() where they apply to
     non-regular files too.

 (5) Be consistent about the presentation of volume ID:vnode ID in debugging
     output.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ef71c15c
Loading
Loading
Loading
Loading
+3 −6
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ void afs_init_callback_state(struct afs_server *server)
	while (!RB_EMPTY_ROOT(&server->cb_promises)) {
		vnode = rb_entry(server->cb_promises.rb_node,
				 struct afs_vnode, cb_promise);
		_debug("UNPROMISE { vid=%x vn=%u uq=%u}",
		_debug("UNPROMISE { vid=%x:%u uq=%u}",
		       vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
		rb_erase(&vnode->cb_promise, &server->cb_promises);
		vnode->cb_promised = false;
@@ -84,11 +84,8 @@ void afs_broken_callback_work(struct work_struct *work)

		/* if the vnode's data version number changed then its contents
		 * are different */
		if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
			_debug("zap data {%x:%u}",
			       vnode->fid.vid, vnode->fid.vnode);
			invalidate_remote_inode(&vnode->vfs_inode);
		}
		if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
			afs_zap_data(vnode);
	}

out:
+9 −9
Original line number Diff line number Diff line
@@ -55,7 +55,7 @@ const struct inode_operations afs_dir_inode_operations = {
	.rmdir		= afs_rmdir,
	.rename		= afs_rename,
	.permission	= afs_permission,
	.getattr	= afs_inode_getattr,
	.getattr	= afs_getattr,
};

static struct dentry_operations afs_fs_dentry_operations = {
@@ -491,7 +491,7 @@ static struct dentry *afs_lookup(struct inode *dir, struct dentry *dentry,

	vnode = AFS_FS_I(dir);

	_enter("{%x:%d},%p{%s},",
	_enter("{%x:%u},%p{%s},",
	       vnode->fid.vid, vnode->fid.vnode, dentry, dentry->d_name.name);

	ASSERTCMP(dentry->d_inode, ==, NULL);
@@ -731,7 +731,7 @@ static int afs_mkdir(struct inode *dir, struct dentry *dentry, int mode)

	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%s},%o",
	_enter("{%x:%u},{%s},%o",
	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);

	ret = -ENAMETOOLONG;
@@ -796,7 +796,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)

	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%s}",
	_enter("{%x:%u},{%s}",
	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);

	ret = -ENAMETOOLONG;
@@ -842,7 +842,7 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)

	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%s}",
	_enter("{%x:%u},{%s}",
	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name);

	ret = -ENAMETOOLONG;
@@ -916,7 +916,7 @@ static int afs_create(struct inode *dir, struct dentry *dentry, int mode,

	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%s},%o,",
	_enter("{%x:%u},{%s},%o,",
	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name, mode);

	ret = -ENAMETOOLONG;
@@ -983,7 +983,7 @@ static int afs_link(struct dentry *from, struct inode *dir,
	vnode = AFS_FS_I(from->d_inode);
	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%x:%d},{%s}",
	_enter("{%x:%u},{%x:%u},{%s}",
	       vnode->fid.vid, vnode->fid.vnode,
	       dvnode->fid.vid, dvnode->fid.vnode,
	       dentry->d_name.name);
@@ -1032,7 +1032,7 @@ static int afs_symlink(struct inode *dir, struct dentry *dentry,

	dvnode = AFS_FS_I(dir);

	_enter("{%x:%d},{%s},%s",
	_enter("{%x:%u},{%s},%s",
	       dvnode->fid.vid, dvnode->fid.vnode, dentry->d_name.name,
	       content);

@@ -1104,7 +1104,7 @@ static int afs_rename(struct inode *old_dir, struct dentry *old_dentry,
	orig_dvnode = AFS_FS_I(old_dir);
	new_dvnode = AFS_FS_I(new_dir);

	_enter("{%x:%d},{%x:%d},{%x:%d},{%s}",
	_enter("{%x:%u},{%x:%u},{%x:%u},{%s}",
	       orig_dvnode->fid.vid, orig_dvnode->fid.vnode,
	       vnode->fid.vid, vnode->fid.vnode,
	       new_dvnode->fid.vid, new_dvnode->fid.vnode,
+26 −49
Original line number Diff line number Diff line
@@ -17,9 +17,9 @@
#include <linux/pagemap.h>
#include "internal.h"

static int afs_file_readpage(struct file *file, struct page *page);
static void afs_file_invalidatepage(struct page *page, unsigned long offset);
static int afs_file_releasepage(struct page *page, gfp_t gfp_flags);
static int afs_readpage(struct file *file, struct page *page);
static void afs_invalidatepage(struct page *page, unsigned long offset);
static int afs_releasepage(struct page *page, gfp_t gfp_flags);

const struct file_operations afs_file_operations = {
	.open		= afs_open,
@@ -32,15 +32,15 @@ const struct file_operations afs_file_operations = {
};

const struct inode_operations afs_file_inode_operations = {
	.getattr	= afs_inode_getattr,
	.getattr	= afs_getattr,
	.permission	= afs_permission,
};

const struct address_space_operations afs_fs_aops = {
	.readpage	= afs_file_readpage,
	.readpage	= afs_readpage,
	.set_page_dirty	= __set_page_dirty_nobuffers,
	.releasepage	= afs_file_releasepage,
	.invalidatepage	= afs_file_invalidatepage,
	.releasepage	= afs_releasepage,
	.invalidatepage	= afs_invalidatepage,
};

/*
@@ -52,7 +52,7 @@ int afs_open(struct inode *inode, struct file *file)
	struct key *key;
	int ret;

	_enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
	_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);

	key = afs_request_key(vnode->volume->cell);
	if (IS_ERR(key)) {
@@ -78,7 +78,7 @@ int afs_release(struct inode *inode, struct file *file)
{
	struct afs_vnode *vnode = AFS_FS_I(inode);

	_enter("{%x:%x},", vnode->fid.vid, vnode->fid.vnode);
	_enter("{%x:%u},", vnode->fid.vid, vnode->fid.vnode);

	key_put(file->private_data);
	_leave(" = 0");
@@ -89,7 +89,7 @@ int afs_release(struct inode *inode, struct file *file)
 * deal with notification that a page was read from the cache
 */
#ifdef AFS_CACHING_SUPPORT
static void afs_file_readpage_read_complete(void *cookie_data,
static void afs_readpage_read_complete(void *cookie_data,
				       struct page *page,
				       void *data,
				       int error)
@@ -109,7 +109,7 @@ static void afs_file_readpage_read_complete(void *cookie_data,
 * deal with notification that a page was written to the cache
 */
#ifdef AFS_CACHING_SUPPORT
static void afs_file_readpage_write_complete(void *cookie_data,
static void afs_readpage_write_complete(void *cookie_data,
					struct page *page,
					void *data,
					int error)
@@ -121,9 +121,9 @@ static void afs_file_readpage_write_complete(void *cookie_data,
#endif

/*
 * AFS read page from file (or symlink)
 * AFS read page from file, directory or symlink
 */
static int afs_file_readpage(struct file *file, struct page *page)
static int afs_readpage(struct file *file, struct page *page)
{
	struct afs_vnode *vnode;
	struct inode *inode;
@@ -218,31 +218,14 @@ static int afs_file_readpage(struct file *file, struct page *page)
	return ret;
}

/*
 * get a page cookie for the specified page
 */
#ifdef AFS_CACHING_SUPPORT
int afs_cache_get_page_cookie(struct page *page,
			      struct cachefs_page **_page_cookie)
{
	int ret;

	_enter("");
	ret = cachefs_page_get_private(page,_page_cookie, GFP_NOIO);

	_leave(" = %d", ret);
	return ret;
}
#endif

/*
 * invalidate part or all of a page
 */
static void afs_file_invalidatepage(struct page *page, unsigned long offset)
static void afs_invalidatepage(struct page *page, unsigned long offset)
{
	int ret = 1;

	_enter("{%lu},%lu", page->index, offset);
	kenter("{%lu},%lu", page->index, offset);

	BUG_ON(!PageLocked(page));

@@ -274,23 +257,17 @@ static void afs_file_invalidatepage(struct page *page, unsigned long offset)
/*
 * release a page and cleanup its private data
 */
static int afs_file_releasepage(struct page *page, gfp_t gfp_flags)
static int afs_releasepage(struct page *page, gfp_t gfp_flags)
{
	struct cachefs_page *pageio;
	struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);

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

	if (PagePrivate(page)) {
#ifdef AFS_CACHING_SUPPORT
		struct afs_vnode *vnode = AFS_FS_I(page->mapping->host);
		cachefs_uncache_page(vnode->cache, page);
#endif

		pageio = (struct cachefs_page *) page_private(page);
		set_page_private(page, 0);
		ClearPagePrivate(page);

		kfree(pageio);
	}

	_leave(" = 0");
+20 −17
Original line number Diff line number Diff line
@@ -206,7 +206,7 @@ int afs_fs_fetch_file_status(struct afs_server *server,
	struct afs_call *call;
	__be32 *bp;

	_enter(",%x,{%x:%d},,",
	_enter(",%x,{%x:%u},,",
	       key_serial(key), vnode->fid.vid, vnode->fid.vnode);

	call = afs_alloc_flat_call(&afs_RXFSFetchStatus, 16, (21 + 3 + 6) * 4);
@@ -265,26 +265,21 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
		call->offset = 0;
		call->unmarshall++;

		if (call->count < PAGE_SIZE) {
			page = call->reply3;
			buffer = kmap_atomic(page, KM_USER0);
			memset(buffer + PAGE_SIZE - call->count, 0,
			       call->count);
			kunmap_atomic(buffer, KM_USER0);
		}

		/* extract the returned data */
	case 2:
		_debug("extract data");
		if (call->count > 0) {
			page = call->reply3;
			buffer = kmap_atomic(page, KM_USER0);
		ret = afs_extract_data(call, skb, last, buffer, call->count);
			ret = afs_extract_data(call, skb, last, buffer,
					       call->count);
			kunmap_atomic(buffer, KM_USER0);
			switch (ret) {
			case 0:		break;
			case -EAGAIN:	return 0;
			default:	return ret;
			}
		}

		call->offset = 0;
		call->unmarshall++;
@@ -318,6 +313,14 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call,
	if (!last)
		return 0;

	if (call->count < PAGE_SIZE) {
		_debug("clear");
		page = call->reply3;
		buffer = kmap_atomic(page, KM_USER0);
		memset(buffer + call->count, 0, PAGE_SIZE - call->count);
		kunmap_atomic(buffer, KM_USER0);
	}

	_leave(" = 0 [done]");
	return 0;
}
+18 −7
Original line number Diff line number Diff line
@@ -125,7 +125,7 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
	struct inode *inode;
	int ret;

	_enter(",{%u,%u,%u},,", fid->vid, fid->vnode, fid->unique);
	_enter(",{%x:%u.%u},,", fid->vid, fid->vnode, fid->unique);

	as = sb->s_fs_info;
	data.volume = as->volume;
@@ -203,6 +203,19 @@ struct inode *afs_iget(struct super_block *sb, struct key *key,
	return ERR_PTR(ret);
}

/*
 * mark the data attached to an inode as obsolete due to a write on the server
 * - might also want to ditch all the outstanding writes and dirty pages
 */
void afs_zap_data(struct afs_vnode *vnode)
{
	kenter("zap data {%x:%u}", vnode->fid.vid, vnode->fid.vnode);

	/* nuke all the non-dirty pages that aren't locked, mapped or being
	 * written back */
	invalidate_remote_inode(&vnode->vfs_inode);
}

/*
 * validate a vnode/inode
 * - there are several things we need to check
@@ -258,10 +271,8 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)

	/* if the vnode's data version number changed then its contents are
	 * different */
	if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags)) {
		_debug("zap data {%x:%d}", vnode->fid.vid, vnode->fid.vnode);
		invalidate_remote_inode(&vnode->vfs_inode);
	}
	if (test_and_clear_bit(AFS_VNODE_ZAP_DATA, &vnode->flags))
		afs_zap_data(vnode);

	clear_bit(AFS_VNODE_MODIFIED, &vnode->flags);
	mutex_unlock(&vnode->validate_lock);
@@ -278,7 +289,7 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
/*
 * read the attributes of an inode
 */
int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry,
int afs_getattr(struct vfsmount *mnt, struct dentry *dentry,
		      struct kstat *stat)
{
	struct inode *inode;
@@ -301,7 +312,7 @@ void afs_clear_inode(struct inode *inode)

	vnode = AFS_FS_I(inode);

	_enter("{%x:%d.%d} v=%u x=%u t=%u }",
	_enter("{%x:%u.%d} v=%u x=%u t=%u }",
	       vnode->fid.vid,
	       vnode->fid.vnode,
	       vnode->fid.unique,
Loading