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

Commit 260a9803 authored by David Howells's avatar David Howells Committed by David S. Miller
Browse files

[AFS]: Add "directory write" support.



Add support for the create, link, symlink, unlink, mkdir, rmdir and
rename VFS operations to the in-kernel AFS filesystem.

Also:

 (1) Fix dentry and inode revalidation.  d_revalidate should only look at
     state of the dentry.  Revalidation of the contents of an inode pointed to
     by a dentry is now separate.

 (2) Fix afs_lookup() to hash negative dentries as well as positive ones.

Signed-off-by: default avatarDavid Howells <dhowells@redhat.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c35eccb1
Loading
Loading
Loading
Loading
+22 −4
Original line number Diff line number Diff line
@@ -106,18 +106,36 @@ struct afs_file_status {

	afs_file_type_t		type;		/* file type */
	unsigned		nlink;		/* link count */
	size_t			size;		/* file size */
	u64			size;		/* file size */
	afs_dataversion_t	data_version;	/* current data version */
	unsigned		author;		/* author ID */
	unsigned		owner;		/* owner ID */
	u32			author;		/* author ID */
	u32			owner;		/* owner ID */
	u32			group;		/* group ID */
	afs_access_t		caller_access;	/* access rights for authenticated caller */
	afs_access_t		anon_access;	/* access rights for unauthenticated caller */
	umode_t			mode;		/* UNIX mode */
	struct afs_fid		parent;		/* parent file ID */
	struct afs_fid		parent;		/* parent dir ID for non-dirs only */
	time_t			mtime_client;	/* last time client changed data */
	time_t			mtime_server;	/* last time server changed data */
};

/*
 * AFS file status change request
 */
struct afs_store_status {
	u32			mask;		/* which bits of the struct are set */
	u32			mtime_client;	/* last time client changed data */
	u32			owner;		/* owner ID */
	u32			group;		/* group ID */
	umode_t			mode;		/* UNIX mode */
};

#define AFS_SET_MTIME		0x01		/* set the mtime */
#define AFS_SET_OWNER		0x02		/* set the owner ID */
#define AFS_SET_GROUP		0x04		/* set the group ID (unsupported?) */
#define AFS_SET_MODE		0x08		/* set the UNIX mode */
#define AFS_SET_SEG_SIZE	0x10		/* set the segment size (unsupported) */

/*
 * AFS volume synchronisation information
 */
+9 −2
Original line number Diff line number Diff line
@@ -16,12 +16,19 @@
#define FS_SERVICE		1	/* AFS File Service ID */

enum AFS_FS_Operations {
	FSFETCHSTATUS		= 132,	/* AFS Fetch file status */
	FSFETCHDATA		= 130,	/* AFS Fetch file data */
	FSFETCHSTATUS		= 132,	/* AFS Fetch file status */
	FSREMOVEFILE		= 136,	/* AFS Remove a file */
	FSCREATEFILE		= 137,	/* AFS Create a file */
	FSRENAME		= 138,	/* AFS Rename or move a file or directory */
	FSSYMLINK		= 139,	/* AFS Create a symbolic link */
	FSLINK			= 140,	/* AFS Create a hard link */
	FSMAKEDIR		= 141,	/* AFS Create a directory */
	FSREMOVEDIR		= 142,	/* AFS Remove a directory */
	FSGIVEUPCALLBACKS	= 147,	/* AFS Discard callback promises */
	FSGETVOLUMEINFO		= 148,	/* AFS Get root volume information */
	FSGETROOTVOLUME		= 151,	/* AFS Get root volume name */
	FSLOOKUP		= 161	/* AFS lookup file in directory */
	FSLOOKUP		= 161,	/* AFS lookup file in directory */
};

enum AFS_FS_Errors {
+32 −4
Original line number Diff line number Diff line
@@ -44,7 +44,8 @@ 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);
		printk("\nUNPROMISE on %p\n", vnode);
		_debug("UNPROMISE { vid=%x vn=%u uq=%u}",
		       vnode->fid.vid, vnode->fid.vnode, vnode->fid.unique);
		rb_erase(&vnode->cb_promise, &server->cb_promises);
		vnode->cb_promised = false;
	}
@@ -68,7 +69,7 @@ void afs_broken_callback_work(struct work_struct *work)

	/* we're only interested in dealing with a broken callback on *this*
	 * vnode and only if no-one else has dealt with it yet */
	if (!mutex_trylock(&vnode->cb_broken_lock))
	if (!mutex_trylock(&vnode->validate_lock))
		return; /* someone else is dealing with it */

	if (test_bit(AFS_VNODE_CB_BROKEN, &vnode->flags)) {
@@ -84,13 +85,14 @@ 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");
			_debug("zap data {%x:%u}",
			       vnode->fid.vid, vnode->fid.vnode);
			invalidate_remote_inode(&vnode->vfs_inode);
		}
	}

out:
	mutex_unlock(&vnode->cb_broken_lock);
	mutex_unlock(&vnode->validate_lock);

	/* avoid the potential race whereby the mutex_trylock() in this
	 * function happens again between the clear_bit() and the
@@ -251,6 +253,32 @@ static void afs_do_give_up_callback(struct afs_server *server,
	_leave("");
}

/*
 * discard the callback on a deleted item
 */
void afs_discard_callback_on_delete(struct afs_vnode *vnode)
{
	struct afs_server *server = vnode->server;

	_enter("%d", vnode->cb_promised);

	if (!vnode->cb_promised) {
		_leave(" [not promised]");
		return;
	}

	ASSERT(server != NULL);

	spin_lock(&server->cb_lock);
	if (vnode->cb_promised) {
		ASSERT(server->cb_promises.rb_node != NULL);
		rb_erase(&vnode->cb_promise, &server->cb_promises);
		vnode->cb_promised = false;
	}
	spin_unlock(&server->cb_lock);
	_leave("");
}

/*
 * give up the callback registered for a vnode on the file server when the
 * inode is being cleared
+536 −140

File changed.

Preview size limit exceeded, changes collapsed.

+7 −0
Original line number Diff line number Diff line
@@ -50,6 +50,7 @@ int afs_open(struct inode *inode, struct file *file)
{
	struct afs_vnode *vnode = AFS_FS_I(inode);
	struct key *key;
	int ret;

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

@@ -59,6 +60,12 @@ int afs_open(struct inode *inode, struct file *file)
		return PTR_ERR(key);
	}

	ret = afs_validate(vnode, key);
	if (ret < 0) {
		_leave(" = %d [val]", ret);
		return ret;
	}

	file->private_data = key;
	_leave(" = 0");
	return 0;
Loading