mirror of
https://github.com/versity/scoutfs.git
synced 2026-02-07 11:10:44 +00:00
Add symlinks back
Convert symlinks to use the new item cache API. This is so much easier because our max item size matches the symlink size. Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
108
kmod/src/dir.c
108
kmod/src/dir.c
@@ -628,6 +628,15 @@ out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void init_symlink_key(struct scoutfs_key_buf *key,
|
||||
struct scoutfs_symlink_key *skey, u64 ino)
|
||||
{
|
||||
skey->type = SCOUTFS_SYMLINK_KEY;
|
||||
skey->ino = cpu_to_be64(ino);
|
||||
|
||||
scoutfs_key_init(key, skey, sizeof(struct scoutfs_symlink_key));
|
||||
}
|
||||
|
||||
/*
|
||||
* Full a buffer with the null terminated symlink, point nd at it, and
|
||||
* return it so put_link can free it once the vfs is done.
|
||||
@@ -640,18 +649,12 @@ static void *scoutfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
{
|
||||
struct inode *inode = dentry->d_inode;
|
||||
struct super_block *sb = inode->i_sb;
|
||||
struct scoutfs_btree_root *meta = SCOUTFS_META(sb);
|
||||
loff_t size = i_size_read(inode);
|
||||
struct scoutfs_btree_val val;
|
||||
struct scoutfs_key key;
|
||||
struct scoutfs_symlink_key skey;
|
||||
struct scoutfs_key_buf key;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
char *path;
|
||||
int bytes;
|
||||
int off;
|
||||
int ret;
|
||||
int k;
|
||||
|
||||
/* update for kvec items */
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
/* XXX corruption */
|
||||
if (size == 0 || size > SCOUTFS_SYMLINK_MAX_SIZE)
|
||||
@@ -665,30 +668,17 @@ static void *scoutfs_follow_link(struct dentry *dentry, struct nameidata *nd)
|
||||
if (!path)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
|
||||
for (off = 0, k = 0; off < size ; k++) {
|
||||
scoutfs_set_key(&key, scoutfs_ino(inode),
|
||||
SCOUTFS_SYMLINK_KEY, k);
|
||||
bytes = min_t(int, size - off, SCOUTFS_MAX_ITEM_LEN);
|
||||
scoutfs_btree_init_val(&val, path + off, bytes);
|
||||
val.check_size_eq = 1;
|
||||
init_symlink_key(&key, &skey, scoutfs_ino(inode));
|
||||
scoutfs_kvec_init(val, path, size);
|
||||
|
||||
ret = scoutfs_btree_lookup(sb, meta, &key, &val);
|
||||
if (ret < 0) {
|
||||
/* XXX corruption */
|
||||
if (ret == -ENOENT)
|
||||
ret = -EIO;
|
||||
break;
|
||||
}
|
||||
ret = scoutfs_item_lookup(sb, &key, val);
|
||||
|
||||
off += bytes;
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
/* XXX corruption */
|
||||
if (ret == 0 && (off != size || path[off - 1] != '\0'))
|
||||
/* XXX corruption: missing item, wrong size, not null term */
|
||||
if (ret == -ENOENT ||
|
||||
(ret >= 0 && (ret != size || path[size - 1] != '\0')))
|
||||
ret = -EIO;
|
||||
|
||||
if (ret) {
|
||||
if (ret < 0) {
|
||||
kfree(path);
|
||||
path = ERR_PTR(ret);
|
||||
} else {
|
||||
@@ -724,18 +714,12 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||
const char *symname)
|
||||
{
|
||||
struct super_block *sb = dir->i_sb;
|
||||
struct scoutfs_btree_root *meta = SCOUTFS_META(sb);
|
||||
struct scoutfs_btree_val val;
|
||||
struct inode *inode = NULL;
|
||||
struct scoutfs_key key;
|
||||
const int name_len = strlen(symname) + 1;
|
||||
int off;
|
||||
int bytes;
|
||||
struct scoutfs_symlink_key skey;
|
||||
struct scoutfs_key_buf key;
|
||||
struct inode *inode = NULL;
|
||||
SCOUTFS_DECLARE_KVEC(val);
|
||||
int ret;
|
||||
int k = 0;
|
||||
|
||||
/* update for kvec items */
|
||||
return -EINVAL;
|
||||
|
||||
/* path_max includes null as does our value for nd_set_link */
|
||||
if (name_len > PATH_MAX || name_len > SCOUTFS_SYMLINK_MAX_SIZE)
|
||||
@@ -755,17 +739,12 @@ static int scoutfs_symlink(struct inode *dir, struct dentry *dentry,
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (k = 0, off = 0; off < name_len; off += bytes, k++) {
|
||||
scoutfs_set_key(&key, scoutfs_ino(inode), SCOUTFS_SYMLINK_KEY,
|
||||
k);
|
||||
bytes = min(name_len - off, SCOUTFS_MAX_ITEM_LEN);
|
||||
init_symlink_key(&key, &skey, scoutfs_ino(inode));
|
||||
scoutfs_kvec_init(val, (void *)symname, name_len);
|
||||
|
||||
scoutfs_btree_init_val(&val, (char *)symname + off, bytes);
|
||||
|
||||
ret = scoutfs_btree_insert(sb, meta, &key, &val);
|
||||
if (ret)
|
||||
goto out;
|
||||
}
|
||||
ret = scoutfs_item_create(sb, &key, val);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
ret = add_entry_items(dir, dentry, inode);
|
||||
if (ret)
|
||||
@@ -788,41 +767,24 @@ out:
|
||||
if (!IS_ERR_OR_NULL(inode))
|
||||
iput(inode);
|
||||
|
||||
while (k--) {
|
||||
scoutfs_set_key(&key, scoutfs_ino(inode),
|
||||
SCOUTFS_SYMLINK_KEY, k);
|
||||
scoutfs_btree_delete(sb, meta, &key);
|
||||
}
|
||||
scoutfs_item_delete(sb, &key);
|
||||
}
|
||||
|
||||
scoutfs_release_trans(sb);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Delete all the symlink items. There should only ever be a handful of
|
||||
* these that contain the target path of the symlink.
|
||||
*/
|
||||
int scoutfs_symlink_drop(struct super_block *sb, u64 ino)
|
||||
{
|
||||
struct scoutfs_btree_root *meta = SCOUTFS_META(sb);
|
||||
struct scoutfs_key key;
|
||||
struct scoutfs_symlink_key skey;
|
||||
struct scoutfs_key_buf key;
|
||||
int ret;
|
||||
int nr;
|
||||
int k;
|
||||
|
||||
nr = DIV_ROUND_UP(SCOUTFS_SYMLINK_MAX_SIZE, SCOUTFS_MAX_ITEM_LEN);
|
||||
init_symlink_key(&key, &skey, ino);
|
||||
|
||||
for (k = 0; k < nr; k++) {
|
||||
scoutfs_set_key(&key, ino, SCOUTFS_SYMLINK_KEY, k);
|
||||
|
||||
ret = scoutfs_btree_delete(sb, meta, &key);
|
||||
if (ret < 0) {
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
ret = scoutfs_item_delete(sb, &key);
|
||||
if (ret == -ENOENT)
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -301,6 +301,12 @@ struct scoutfs_xattr_val_header {
|
||||
__u8 last_part;
|
||||
} __packed;
|
||||
|
||||
/* value is the null terminated target path */
|
||||
struct scoutfs_symlink_key {
|
||||
__u8 type;
|
||||
__be64 ino;
|
||||
} __packed;
|
||||
|
||||
struct scoutfs_btree_root {
|
||||
u8 height;
|
||||
struct scoutfs_block_ref ref;
|
||||
|
||||
@@ -25,8 +25,6 @@ int scoutfs_item_next_same_min(struct super_block *sb,
|
||||
struct kvec *val, int len);
|
||||
int scoutfs_item_next_same(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
struct scoutfs_key_buf *last, struct kvec *val);
|
||||
int scoutfs_item_insert(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
struct kvec *val);
|
||||
int scoutfs_item_create(struct super_block *sb, struct scoutfs_key_buf *key,
|
||||
struct kvec *val);
|
||||
int scoutfs_item_create_ephemeral(struct super_block *sb,
|
||||
|
||||
Reference in New Issue
Block a user