+ _leave(" = %d [cnt %d]", ret, vnode->update_cnt);
+ return ret;
+
+no_server:
+ spin_lock(&vnode->lock);
+ vnode->update_cnt--;
+ ASSERTCMP(vnode->update_cnt, >=, 0);
+ spin_unlock(&vnode->lock);
+ spin_lock(&dvnode->lock);
+ dvnode->update_cnt--;
+ ASSERTCMP(dvnode->update_cnt, >=, 0);
+ spin_unlock(&dvnode->lock);
+ _leave(" = %ld [cnt %d]", PTR_ERR(server), vnode->update_cnt);
+ return PTR_ERR(server);
+}
+
+/*
+ * create a symbolic link
+ */
+int afs_vnode_symlink(struct afs_vnode *vnode, struct key *key,
+ const char *name, const char *content,
+ struct afs_fid *newfid,
+ struct afs_file_status *newstatus,
+ struct afs_server **_server)
+{
+ struct afs_server *server;
+ int ret;
+
+ _enter("%s{%u,%u,%u},%x,%s,%s,,,",
+ vnode->volume->vlocation->vldb.name,
+ vnode->fid.vid,
+ vnode->fid.vnode,
+ vnode->fid.unique,
+ key_serial(key),
+ name, content);
+
+ /* this op will fetch the status on the directory we're creating in */
+ spin_lock(&vnode->lock);
+ vnode->update_cnt++;
+ spin_unlock(&vnode->lock);
+
+ do {
+ /* pick a server to query */
+ server = afs_volume_pick_fileserver(vnode);
+ if (IS_ERR(server))
+ goto no_server;
+
+ _debug("USING SERVER: %08x\n", ntohl(server->addr.s_addr));
+
+ ret = afs_fs_symlink(server, key, vnode, name, content,
+ newfid, newstatus, &afs_sync_call);
+
+ } while (!afs_volume_release_fileserver(vnode, server, ret));
+
+ /* adjust the flags */
+ if (ret == 0) {
+ afs_vnode_finalise_status_update(vnode, server);
+ *_server = server;
+ } else {
+ afs_vnode_status_update_failed(vnode, ret);
+ *_server = NULL;