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

Commit 30062bd1 authored by David Howells's avatar David Howells
Browse files

afs: Implement YFS support in the fs client



Implement support for talking to YFS-variant fileservers in the cache
manager and the filesystem client.  These implement upgraded services on
the same port as their AFS services.

YFS fileservers provide expanded capabilities over AFS.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
parent d4936803
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -33,7 +33,8 @@ kafs-y := \
	vl_list.o \
	volume.o \
	write.o \
	xattr.o
	xattr.o \
	yfsclient.o

kafs-$(CONFIG_PROC_FS) += proc.o
obj-$(CONFIG_AFS_FS)  := kafs.o
+6 −3
Original line number Diff line number Diff line
@@ -210,12 +210,10 @@ void afs_init_callback_state(struct afs_server *server)
/*
 * actually break a callback
 */
void afs_break_callback(struct afs_vnode *vnode)
void __afs_break_callback(struct afs_vnode *vnode)
{
	_enter("");

	write_seqlock(&vnode->cb_lock);

	clear_bit(AFS_VNODE_NEW_CONTENT, &vnode->flags);
	if (test_and_clear_bit(AFS_VNODE_CB_PROMISED, &vnode->flags)) {
		vnode->cb_break++;
@@ -230,7 +228,12 @@ void afs_break_callback(struct afs_vnode *vnode)
			afs_lock_may_be_available(vnode);
		spin_unlock(&vnode->lock);
	}
}

void afs_break_callback(struct afs_vnode *vnode)
{
	write_seqlock(&vnode->cb_lock);
	__afs_break_callback(vnode);
	write_sequnlock(&vnode->cb_lock);
}

+17 −4
Original line number Diff line number Diff line
@@ -1200,7 +1200,7 @@ static int afs_rmdir(struct inode *dir, struct dentry *dentry)
	if (afs_begin_vnode_operation(&fc, dvnode, key)) {
		while (afs_select_fileserver(&fc)) {
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
			afs_fs_remove(&fc, dentry->d_name.name, true,
			afs_fs_remove(&fc, vnode, dentry->d_name.name, true,
				      data_version);
		}

@@ -1245,7 +1245,9 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
	if (d_really_is_positive(dentry)) {
		struct afs_vnode *vnode = AFS_FS_I(d_inode(dentry));

		if (dir_valid) {
		if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
			/* Already done */
		} else if (dir_valid) {
			drop_nlink(&vnode->vfs_inode);
			if (vnode->vfs_inode.i_nlink == 0) {
				set_bit(AFS_VNODE_DELETED, &vnode->flags);
@@ -1274,7 +1276,7 @@ static int afs_dir_remove_link(struct dentry *dentry, struct key *key,
static int afs_unlink(struct inode *dir, struct dentry *dentry)
{
	struct afs_fs_cursor fc;
	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode;
	struct afs_vnode *dvnode = AFS_FS_I(dir), *vnode = NULL;
	struct key *key;
	unsigned long d_version = (unsigned long)dentry->d_fsdata;
	u64 data_version = dvnode->status.data_version;
@@ -1304,7 +1306,18 @@ static int afs_unlink(struct inode *dir, struct dentry *dentry)
	if (afs_begin_vnode_operation(&fc, dvnode, key)) {
		while (afs_select_fileserver(&fc)) {
			fc.cb_break = afs_calc_vnode_cb_break(dvnode);
			afs_fs_remove(&fc, dentry->d_name.name, false,

			if (test_bit(AFS_SERVER_FL_IS_YFS, &fc.cbi->server->flags) &&
			    !test_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags)) {
				yfs_fs_remove_file2(&fc, vnode, dentry->d_name.name,
						    data_version);
				if (fc.ac.error != -ECONNABORTED ||
				    fc.ac.abort_code != RXGEN_OPCODE)
					continue;
				set_bit(AFS_SERVER_FL_NO_RM2, &fc.cbi->server->flags);
			}

			afs_fs_remove(&fc, vnode, dentry->d_name.name, false,
				      data_version);
		}

+86 −18
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#include "internal.h"
#include "afs_fs.h"
#include "xdr_fs.h"
#include "protocol_yfs.h"

static const struct afs_fid afs_zero_fid;

@@ -312,14 +313,18 @@ static void xdr_decode_AFSVolSync(const __be32 **_bp,
				  struct afs_volsync *volsync)
{
	const __be32 *bp = *_bp;
	u32 creation;

	volsync->creation = ntohl(*bp++);
	creation = ntohl(*bp++);
	bp++; /* spare2 */
	bp++; /* spare3 */
	bp++; /* spare4 */
	bp++; /* spare5 */
	bp++; /* spare6 */
	*_bp = bp;

	if (volsync)
		volsync->creation = creation;
}

/*
@@ -380,6 +385,8 @@ static void xdr_decode_AFSFetchVolumeStatus(const __be32 **_bp,
	vs->blocks_in_use	= ntohl(*bp++);
	vs->part_blocks_avail	= ntohl(*bp++);
	vs->part_max_blocks	= ntohl(*bp++);
	vs->vol_copy_date	= 0;
	vs->vol_backup_date	= 0;
	*_bp = bp;
}

@@ -405,7 +412,6 @@ static int afs_deliver_fs_fetch_status_vnode(struct afs_call *call)
	if (ret < 0)
		return ret;
	xdr_decode_AFSCallBack(call, vnode, &bp);
	if (call->reply[1])
	xdr_decode_AFSVolSync(&bp, call->reply[1]);

	_leave(" = 0 [done]");
@@ -433,6 +439,9 @@ int afs_fs_fetch_file_status(struct afs_fs_cursor *fc, struct afs_volsync *volsy
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_fetch_file_status(fc, volsync, new_inode);

	_enter(",%x,{%llx:%llu},,",
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);

@@ -567,7 +576,6 @@ static int afs_deliver_fs_fetch_data(struct afs_call *call)
		if (ret < 0)
			return ret;
		xdr_decode_AFSCallBack(call, vnode, &bp);
		if (call->reply[1])
		xdr_decode_AFSVolSync(&bp, call->reply[1]);

		call->unmarshall++;
@@ -665,6 +673,9 @@ int afs_fs_fetch_data(struct afs_fs_cursor *fc, struct afs_read *req)
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_fetch_data(fc, req);

	if (upper_32_bits(req->pos) ||
	    upper_32_bits(req->len) ||
	    upper_32_bits(req->pos + req->len))
@@ -765,6 +776,15 @@ int afs_fs_create(struct afs_fs_cursor *fc,
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags)){
		if (S_ISDIR(mode))
			return yfs_fs_make_dir(fc, name, mode, current_data_version,
					       newfid, newstatus, newcb);
		else
			return yfs_fs_create_file(fc, name, mode, current_data_version,
						  newfid, newstatus, newcb);
	}

	_enter("");

	namesz = strlen(name);
@@ -857,15 +877,18 @@ static const struct afs_call_type afs_RXFSRemoveDir = {
/*
 * remove a file or directory
 */
int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir,
		  u64 current_data_version)
int afs_fs_remove(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
		  const char *name, bool isdir, u64 current_data_version)
{
	struct afs_vnode *vnode = fc->vnode;
	struct afs_vnode *dvnode = fc->vnode;
	struct afs_call *call;
	struct afs_net *net = afs_v2net(vnode);
	struct afs_net *net = afs_v2net(dvnode);
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_remove(fc, vnode, name, isdir, current_data_version);

	_enter("");

	namesz = strlen(name);
@@ -879,15 +902,16 @@ int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir,
		return -ENOMEM;

	call->key = fc->key;
	call->reply[0] = vnode;
	call->reply[0] = dvnode;
	call->reply[1] = vnode;
	call->expected_version = current_data_version + 1;

	/* marshall the parameters */
	bp = call->request;
	*bp++ = htonl(isdir ? FSREMOVEDIR : FSREMOVEFILE);
	*bp++ = htonl(vnode->fid.vid);
	*bp++ = htonl(vnode->fid.vnode);
	*bp++ = htonl(vnode->fid.unique);
	*bp++ = htonl(dvnode->fid.vid);
	*bp++ = htonl(dvnode->fid.vnode);
	*bp++ = htonl(dvnode->fid.unique);
	*bp++ = htonl(namesz);
	memcpy(bp, name, namesz);
	bp = (void *) bp + namesz;
@@ -897,7 +921,7 @@ int afs_fs_remove(struct afs_fs_cursor *fc, const char *name, bool isdir,
	}

	afs_use_fs_server(call, fc->cbi);
	trace_afs_make_fs_call(call, &vnode->fid);
	trace_afs_make_fs_call(call, &dvnode->fid);
	return afs_make_call(&fc->ac, call, GFP_NOFS, false);
}

@@ -953,6 +977,9 @@ int afs_fs_link(struct afs_fs_cursor *fc, struct afs_vnode *vnode,
	size_t namesz, reqsz, padsz;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_link(fc, vnode, name, current_data_version);

	_enter("");

	namesz = strlen(name);
@@ -1047,6 +1074,10 @@ int afs_fs_symlink(struct afs_fs_cursor *fc,
	size_t namesz, reqsz, padsz, c_namesz, c_padsz;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_symlink(fc, name, contents, current_data_version,
				      newfid, newstatus);

	_enter("");

	namesz = strlen(name);
@@ -1159,6 +1190,12 @@ int afs_fs_rename(struct afs_fs_cursor *fc,
	size_t reqsz, o_namesz, o_padsz, n_namesz, n_padsz;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_rename(fc, orig_name,
				     new_dvnode, new_name,
				     current_orig_data_version,
				     current_new_data_version);

	_enter("");

	o_namesz = strlen(orig_name);
@@ -1329,6 +1366,9 @@ int afs_fs_store_data(struct afs_fs_cursor *fc, struct address_space *mapping,
	loff_t size, pos, i_size;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_store_data(fc, mapping, first, last, offset, to);

	_enter(",%x,{%llx:%llu},,",
	       key_serial(fc->key), vnode->fid.vid, vnode->fid.vnode);

@@ -1544,6 +1584,9 @@ int afs_fs_setattr(struct afs_fs_cursor *fc, struct iattr *attr)
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_setattr(fc, attr);

	if (attr->ia_valid & ATTR_SIZE)
		return afs_fs_setattr_size(fc, attr);

@@ -1728,6 +1771,9 @@ int afs_fs_get_volume_status(struct afs_fs_cursor *fc,
	__be32 *bp;
	void *tmpbuf;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_get_volume_status(fc, vs);

	_enter("");

	tmpbuf = kmalloc(AFSOPAQUEMAX, GFP_KERNEL);
@@ -1817,6 +1863,9 @@ int afs_fs_set_lock(struct afs_fs_cursor *fc, afs_lock_type_t type)
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_set_lock(fc, type);

	_enter("");

	call = afs_alloc_flat_call(net, &afs_RXFSSetLock, 5 * 4, 6 * 4);
@@ -1849,6 +1898,9 @@ int afs_fs_extend_lock(struct afs_fs_cursor *fc)
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_extend_lock(fc);

	_enter("");

	call = afs_alloc_flat_call(net, &afs_RXFSExtendLock, 4 * 4, 6 * 4);
@@ -1880,6 +1932,9 @@ int afs_fs_release_lock(struct afs_fs_cursor *fc)
	struct afs_net *net = afs_v2net(vnode);
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_release_lock(fc);

	_enter("");

	call = afs_alloc_flat_call(net, &afs_RXFSReleaseLock, 4 * 4, 6 * 4);
@@ -1951,6 +2006,7 @@ int afs_fs_give_up_all_callbacks(struct afs_net *net,
 */
static int afs_deliver_fs_get_capabilities(struct afs_call *call)
{
	struct afs_server *server = call->reply[0];
	u32 count;
	int ret;

@@ -1986,6 +2042,11 @@ static int afs_deliver_fs_get_capabilities(struct afs_call *call)
		break;
	}

	if (call->service_id == YFS_FS_SERVICE)
		set_bit(AFS_SERVER_FL_IS_YFS, &server->flags);
	else
		clear_bit(AFS_SERVER_FL_IS_YFS, &server->flags);

	_leave(" = 0 [done]");
	return 0;
}
@@ -2019,6 +2080,8 @@ int afs_fs_get_capabilities(struct afs_net *net,
		return -ENOMEM;

	call->key = key;
	call->reply[0] = server;
	call->upgrade = true;

	/* marshall the parameters */
	bp = call->request;
@@ -2054,7 +2117,6 @@ static int afs_deliver_fs_fetch_status(struct afs_call *call)
	if (ret < 0)
		return ret;
	xdr_decode_AFSCallBack_raw(call, &bp, callback);
	if (volsync)
	xdr_decode_AFSVolSync(&bp, volsync);

	_leave(" = 0 [done]");
@@ -2084,6 +2146,9 @@ int afs_fs_fetch_status(struct afs_fs_cursor *fc,
	struct afs_call *call;
	__be32 *bp;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_fetch_status(fc, net, fid, status, callback, volsync);

	_enter(",%x,{%llx:%llu},,",
	       key_serial(fc->key), fid->vid, fid->vnode);

@@ -2218,7 +2283,6 @@ static int afs_deliver_fs_inline_bulk_status(struct afs_call *call)
			return ret;

		bp = call->buffer;
		if (call->reply[3])
		xdr_decode_AFSVolSync(&bp, call->reply[3]);

		call->unmarshall++;
@@ -2256,6 +2320,10 @@ int afs_fs_inline_bulk_status(struct afs_fs_cursor *fc,
	__be32 *bp;
	int i;

	if (test_bit(AFS_SERVER_FL_IS_YFS, &fc->cbi->server->flags))
		return yfs_fs_inline_bulk_status(fc, net, fids, statuses, callbacks,
						 nr_fids, volsync);

	_enter(",%x,{%llx:%llu},%u",
	       key_serial(fc->key), fids[0].vid, fids[1].vnode, nr_fids);

+34 −1
Original line number Diff line number Diff line
@@ -459,6 +459,8 @@ struct afs_server {
#define AFS_SERVER_FL_PROBING	6		/* Fileserver is being probed */
#define AFS_SERVER_FL_NO_IBULK	7		/* Fileserver doesn't support FS.InlineBulkStatus */
#define AFS_SERVER_FL_MAY_HAVE_CB 8		/* May have callbacks on this fileserver */
#define AFS_SERVER_FL_IS_YFS	9		/* Server is YFS not AFS */
#define AFS_SERVER_FL_NO_RM2	10		/* Fileserver doesn't support YFS.RemoveFile2 */
	atomic_t		usage;
	u32			addr_version;	/* Address list version */

@@ -751,6 +753,7 @@ extern struct fscache_cookie_def afs_vnode_cache_index_def;
 * callback.c
 */
extern void afs_init_callback_state(struct afs_server *);
extern void __afs_break_callback(struct afs_vnode *);
extern void afs_break_callback(struct afs_vnode *);
extern void afs_break_callbacks(struct afs_server *, size_t, struct afs_callback_break*);

@@ -864,7 +867,7 @@ extern int afs_fs_give_up_callbacks(struct afs_net *, struct afs_server *);
extern int afs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *);
extern int afs_fs_create(struct afs_fs_cursor *, const char *, umode_t, u64,
			 struct afs_fid *, struct afs_file_status *, struct afs_callback *);
extern int afs_fs_remove(struct afs_fs_cursor *, const char *, bool, u64);
extern int afs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64);
extern int afs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
extern int afs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64,
			  struct afs_fid *, struct afs_file_status *);
@@ -1228,6 +1231,36 @@ extern int afs_launder_page(struct page *);
extern const struct xattr_handler *afs_xattr_handlers[];
extern ssize_t afs_listxattr(struct dentry *, char *, size_t);

/*
 * yfsclient.c
 */
extern int yfs_fs_fetch_file_status(struct afs_fs_cursor *, struct afs_volsync *, bool);
extern int yfs_fs_fetch_data(struct afs_fs_cursor *, struct afs_read *);
extern int yfs_fs_create_file(struct afs_fs_cursor *, const char *, umode_t, u64,
			      struct afs_fid *, struct afs_file_status *, struct afs_callback *);
extern int yfs_fs_make_dir(struct afs_fs_cursor *, const char *, umode_t, u64,
			 struct afs_fid *, struct afs_file_status *, struct afs_callback *);
extern int yfs_fs_remove_file2(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
extern int yfs_fs_remove(struct afs_fs_cursor *, struct afs_vnode *, const char *, bool, u64);
extern int yfs_fs_link(struct afs_fs_cursor *, struct afs_vnode *, const char *, u64);
extern int yfs_fs_symlink(struct afs_fs_cursor *, const char *, const char *, u64,
			  struct afs_fid *, struct afs_file_status *);
extern int yfs_fs_rename(struct afs_fs_cursor *, const char *,
			 struct afs_vnode *, const char *, u64, u64);
extern int yfs_fs_store_data(struct afs_fs_cursor *, struct address_space *,
			     pgoff_t, pgoff_t, unsigned, unsigned);
extern int yfs_fs_setattr(struct afs_fs_cursor *, struct iattr *);
extern int yfs_fs_get_volume_status(struct afs_fs_cursor *, struct afs_volume_status *);
extern int yfs_fs_set_lock(struct afs_fs_cursor *, afs_lock_type_t);
extern int yfs_fs_extend_lock(struct afs_fs_cursor *);
extern int yfs_fs_release_lock(struct afs_fs_cursor *);
extern int yfs_fs_fetch_status(struct afs_fs_cursor *, struct afs_net *,
			       struct afs_fid *, struct afs_file_status *,
			       struct afs_callback *, struct afs_volsync *);
extern int yfs_fs_inline_bulk_status(struct afs_fs_cursor *, struct afs_net *,
				     struct afs_fid *, struct afs_file_status *,
				     struct afs_callback *, unsigned int,
				     struct afs_volsync *);

/*
 * Miscellaneous inline functions.
Loading