]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.20-afs.patch
- ported from linux-2.4.25-atmdd.patch
[packages/kernel.git] / linux-2.4.20-afs.patch
Content-type: text/html ]> git.pld-linux.org Git - packages/kernel.git/blame - linux-2.4.20-afs.patch


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 16942.
This page took 1.108006 seconds and 4 git commands to generate.
CommitLineData
2c4f4c6a 1diff -urNp linux-5240/fs/afs/cache.c linux-5250/fs/afs/cache.c
2--- linux-5240/fs/afs/cache.c 1970-01-01 01:00:00.000000000 +0100
3+++ linux-5250/fs/afs/cache.c
4@@ -0,0 +1,664 @@
5+/* cache.c: AFS local cache management
6+ *
7+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
8+ * Written by David Howells (dhowells@redhat.com)
9+ *
10+ * This program is free software; you can redistribute it and/or
11+ * modify it under the terms of the GNU General Public License
12+ * as published by the Free Software Foundation; either version
13+ * 2 of the License, or (at your option) any later version.
14+ */
15+
16+#include <linux/kernel.h>
17+#include <linux/module.h>
18+#include <linux/init.h>
19+#include <linux/slab.h>
20+#include <linux/fs.h>
21+#include <linux/namei.h>
22+#include <linux/pagemap.h>
23+#include <linux/devfs_fs_kernel.h>
24+#include <linux/buffer_head.h>
25+#include "cell.h"
26+#include "cmservice.h"
27+#include "fsclient.h"
28+#include "cache.h"
29+#include "volume.h"
30+#include "vnode.h"
31+#include "internal.h"
32+
33+static LIST_HEAD(afs_cache_list);
34+static DECLARE_MUTEX(afs_cache_list_sem);
35+
36+static int afs_cache_read_sig(afs_cache_t *cache);
37+
38+/*****************************************************************************/
39+/*
40+ * stat a cache device to find its device numbers
41+ */
42+static int afs_cache_get_kdev(const char *cachename, kdev_t *_kdev, struct file **_bdfile)
43+{
44+ struct nameidata nd;
45+ struct inode *inode;
46+ struct file *bdfile;
47+ int ret;
48+
49+ /* look up the cache device file */
50+ if (!cachename)
51+ return -EINVAL;
52+
53+ ret = path_lookup(cachename,LOOKUP_FOLLOW,&nd);
54+ if (ret)
55+ return ret;
56+
57+ /* check it's a block device file */
58+ inode = nd.dentry->d_inode;
59+ ret = -ENOTBLK;
60+ if (!S_ISBLK(inode->i_mode)) {
61+ path_release(&nd);
62+ return ret;
63+ }
64+
65+ /* open a file for it */
66+ bdfile = dentry_open(nd.dentry,nd.mnt,O_RDWR);
67+ if (IS_ERR(bdfile))
68+ return ret;
69+
70+ *_kdev = inode->i_rdev;
71+ *_bdfile = bdfile;
72+ return 0;
73+} /* end afs_cache_get_kdev() */
74+
75+/*****************************************************************************/
76+/*
77+ * open a cache device
78+ */
79+int afs_cache_open(const char *cachename, afs_cache_t **_cache)
80+{
81+ struct list_head *_p;
82+ afs_cache_t *cache, *ncache;
83+ kdev_t dev;
84+ int ret = 0;
85+
86+ _enter("{%s}",cachename);
87+
88+ BUG();
89+
90+ /* pre-allocate a cache record */
91+ ret = -ENOMEM;
92+ ncache = kmalloc(sizeof(*ncache),GFP_KERNEL);
93+ if (!ncache) {
94+ _leave(" = %d [lookup failed]",ret);
95+ return ret;
96+ }
97+ memset(ncache,0,sizeof(*ncache));
98+
99+ atomic_set(&ncache->usage,1);
100+ INIT_LIST_HEAD(&ncache->link);
101+ init_rwsem(&ncache->sem);
102+
103+ /* lookup the block device */
104+ ret = afs_cache_get_kdev(cachename,&dev,&ncache->bdfile);
105+ if (ret<0) {
106+ kfree(ncache);
107+ _leave(" = %d [lookup failed]",ret);
108+ return ret;
109+ }
110+
111+ ncache->dev = dev;
112+
113+ /* see if we've already got the cache open */
114+ cache = NULL;
115+ down(&afs_cache_list_sem);
116+
117+ list_for_each(_p,&afs_cache_list) {
118+ cache = list_entry(_p,afs_cache_t,link);
119+ if (kdev_same(cache->dev,dev))
120+ goto found;
121+ }
122+ goto not_found;
123+
124+ /* we already have the cache open */
125+ found:
126+ kdebug("kAFS re-using cache block dev %s",kdevname(dev));
127+ filp_close(cache->bdfile,NULL);
128+ kfree(ncache);
129+ ncache = NULL;
130+ afs_get_cache(cache);
131+ goto success;
132+
133+ /* we don't already have the cache open */
134+ not_found:
135+ kdebug("kAFS using cache block dev %s",kdevname(dev));
136+ cache = ncache;
137+ ncache = NULL;
138+
139+ /* grab a handle to the block device */
140+ ret = -ENOMEM;
141+ cache->bdev = bdget(kdev_t_to_nr(dev));
142+ if (!cache->bdev)
143+ goto out;
144+
145+ /* open the block device node */
146+ ret = blkdev_get(cache->bdev,FMODE_READ|FMODE_WRITE,0,BDEV_RAW);
147+ if (ret)
148+ goto out;
149+
150+ /* quick insanity check */
151+ check_disk_change(cache->dev);
152+ ret = -EACCES;
153+ if (is_read_only(cache->dev))
154+ goto out;
155+
156+ /* mark it as mine */
157+ ret = bd_claim(cache->bdev,cache);
158+ if (ret)
159+ goto out;
160+
161+ /* check it */
162+ ret = afs_cache_read_sig(cache);
163+ if (ret<0)
164+ goto out_unclaim;
165+
166+ list_add_tail(&cache->link,&afs_cache_list);
167+
168+ success:
169+ *_cache = cache;
170+ up(&afs_cache_list_sem);
171+ _leave(" = 0 (%p{%x})",cache->bdev,kdev_t_to_nr(cache->dev));
172+ return 0;
173+
174+ out_unclaim:
175+ bd_release(cache->bdev);
176+ out:
177+ if (cache->bdfile)
178+ filp_close(cache->bdfile,NULL);
179+ if (cache->bdev) {
180+ blkdev_put(cache->bdev,BDEV_RAW);
181+ cache->bdev = NULL;
182+ }
183+
184+ kfree(cache);
185+
186+ up(&afs_cache_list_sem);
187+ _leave(" = %d",ret);
188+ return ret;
189+
190+} /* end afs_cache_open() */
191+
192+/*****************************************************************************/
193+/*
194+ * release a cache device
195+ */
196+void afs_put_cache(afs_cache_t *cache)
197+{
198+ _enter("%p{u=%d}",cache,atomic_read(&cache->usage));
199+
200+ down(&afs_cache_list_sem);
201+
202+ if (!atomic_dec_and_test(&cache->usage))
203+ cache = NULL;
204+ else
205+ list_del(&cache->link);
206+
207+ up(&afs_cache_list_sem);
208+
209+ /* if that was the last ref, then release the kernel resources */
210+ if (cache) {
211+ kdebug("kAFS releasing cache block dev %s",kdevname(cache->dev));
212+ filp_close(cache->bdfile,NULL);
213+ bd_release(cache->bdev);
214+ blkdev_put(cache->bdev,BDEV_RAW);
215+ kfree(cache);
216+ }
217+
218+ _leave("");
219+} /* end afs_put_cache() */
220+
221+/*****************************************************************************/
222+/*
223+ * read the cache signature block from the cache device
224+ */
225+static int afs_cache_read_sig(afs_cache_t *cache)
226+{
227+ struct afs_cache_super_block *csb;
228+ struct buffer_head *bh;
229+
230+ bh = __bread(cache->bdev,0,PAGE_CACHE_SIZE);
231+ if (!bh)
232+ return -EIO;
233+
234+ csb = (struct afs_cache_super_block*) bh->b_data;
235+
236+ /* validate the cache superblock */
237+ if (memcmp(csb->magic,AFS_CACHE_SUPER_MAGIC,sizeof(csb->magic))!=0) {
238+ printk("kAFS cache magic string doesn't match\n");
239+ return -EINVAL;
240+ }
241+ if (csb->endian!=AFS_CACHE_SUPER_ENDIAN) {
242+ printk("kAFS endian spec doesn't match (%hx not %hx)\n",
243+ csb->endian,AFS_CACHE_SUPER_ENDIAN);
244+ return -EINVAL;
245+ }
246+ if (csb->version!=AFS_CACHE_SUPER_VERSION) {
247+ printk("kAFS version doesn't match (%u not %u)\n",
248+ csb->version,AFS_CACHE_SUPER_VERSION);
249+ return -EINVAL;
250+ }
251+
252+ /* copy the layout into the cache management structure */
253+ memcpy(&cache->layout,csb,sizeof(cache->layout));
254+
255+ brelse(bh);
256+ return 0;
257+} /* end afs_cache_read_sig() */
258+
259+/*****************************************************************************/
260+/*
261+ * update part of one page in the cache
262+ * - the caller must hold any required protective locks
263+ * - based on rw_swap_page_base()
264+ */
265+static int afs_cache_update_region(afs_cache_t *cache, afs_cache_bix_t bix,
266+ unsigned off, size_t size, void *buf)
267+{
268+ mm_segment_t oldfs;
269+ loff_t pos;
270+ int ret;
271+
272+ _enter("%s,%u,%u,%u,",kdevname(cache->dev),bix,off,size);
273+
274+ pos = bix*cache->layout.bsize + off;
275+
276+ oldfs = get_fs();
277+ set_fs(KERNEL_DS);
278+ ret = generic_file_write(cache->bdfile,buf,size,&pos);
279+ set_fs(oldfs);
280+
281+ if (ret>0)
282+ ret = 0;
283+
284+ _leave(" = %d",ret);
285+ return ret;
286+} /* end afs_cache_update_region() */
287+
288+/*****************************************************************************/
289+/*
290+ * look up cell information in the cache
291+ * - mkafscache preloads /etc/sysconfig/kafs/cell-serv-db into the cache
292+ */
293+int afs_cache_lookup_cell(afs_cache_t *cache,
294+ afs_cell_t *cell)
295+{
296+ struct afs_cache_cell_block *ccells;
297+ struct afs_cache_cell *ccell;
298+ struct buffer_head *bh;
299+ afs_cache_cellix_t cix, stop, rem;
300+ afs_cache_bix_t bix;
301+ int loop;
302+
303+ _enter("%s,%s",kdevname(cache->dev),cell->name);
304+
305+ BUG();
306+
307+ rem = cache->layout.ncells;
308+
309+ for (bix=cache->layout.off_cell_cache; bix<cache->layout.off_volume_bitmap; bix++) {
310+ /* read the next block */
311+ bh = __bread(cache->bdev,bix,PAGE_CACHE_SIZE);
312+ if (!bh) {
313+ kleave(" = -EIO (block %u)",bix);
314+ return -EIO;
315+ }
316+
317+ ccells = (struct afs_cache_cell_block*) bh->b_data;
318+
319+ /* and scan it */
320+ stop = min((size_t)rem,
321+ sizeof(struct afs_cache_cell_block)/sizeof(struct afs_cache_cell));
322+ rem -= stop;
323+
324+ for (cix=0; cix<stop; cix++) {
325+ ccell = &ccells->entries[cix];
326+ if (strncmp(cell->name,ccell->name,sizeof(ccell->name))==0)
327+ goto found;
328+ }
329+
330+ brelse(bh);
331+ }
332+
333+ _leave(" = -ENOENT");
334+ return -ENOENT;
335+
336+ found:
337+ /* found the cell record - copy out the details */
338+ bix -= cache->layout.off_cell_cache;
339+ cell->cache_ix = cix;
340+ cell->cache_ix += bix * sizeof(struct afs_cache_cell_block)/sizeof(struct afs_cache_cell);
341+
342+ memcpy(cell->vl_addrs,ccell->servers,sizeof(cell->vl_addrs));
343+
344+ for (loop=0; loop<sizeof(cell->vl_addrs)/sizeof(cell->vl_addrs[0]); loop++)
345+ if (!cell->vl_addrs[loop].s_addr)
346+ break;
347+ cell->vl_naddrs = loop;
348+
349+ brelse(bh);
350+ _leave(" = 0 (bix=%u cix=%u ccix=%u)",bix,cix,cell->cache_ix);
351+ return 0;
352+
353+} /* end afs_cache_lookup_cell() */
354+
355+/*****************************************************************************/
356+/*
357+ * search for a volume location record in the cache
358+ */
359+int afs_cache_lookup_vlocation(afs_vlocation_t *vlocation)
360+{
361+ BUG();
362+
363+#if 0
364+ struct afs_cache_volume_block *cvols;
365+ struct afs_cache_volume *cvol;
366+ struct buffer_head *bh;
367+ afs_cache_bix_t bix;
368+ unsigned rem, stop, ix;
369+
370+ _enter("%s,{v=%s cix=%u}",
371+ kdevname(vlocation->cache->dev),vlocation->vldb.name,vlocation->vldb.cell_ix);
372+
373+ rem = vlocation->cache->layout.nvols;
374+
375+ for (bix=vlocation->cache->layout.off_volume_cache;
376+ bix<vlocation->cache->layout.off_vnode_bitmap;
377+ bix++
378+ ) {
379+ /* read the next block */
380+ bh = __bread(vlocation->cache->bdev,bix,PAGE_CACHE_SIZE);
381+ if (!bh) {
382+ kleave(" = -EIO (block %u)",bix);
383+ return -EIO;
384+ }
385+
386+ cvols = (struct afs_cache_volume_block*) bh->b_data;
387+
388+ /* and scan it */
389+ stop = min((size_t)rem,sizeof(*cvols)/sizeof(*cvol));
390+ rem -= stop;
391+
392+ for (ix=0; ix<stop; ix++) {
393+ cvol = &cvols->entries[ix];
394+ if (cvol->name[0])
395+ _debug("FOUND[%u.%u]: cell %u vol '%s' %08x",
396+ bix,ix,cvol->cell_ix,cvol->name,cvol->vid[0]);
397+ if (cvol->cell_ix==vlocation->vldb.cell_ix &&
398+ memcmp(vlocation->vldb.name,cvol->name,sizeof(cvol->name))==0) {
399+ goto found;
400+ }
401+ }
402+
403+ brelse(bh);
404+ }
405+
406+ _leave(" = %d",-ENOENT);
407+ return -ENOENT;
408+
409+ found:
410+ /* found the cell record */
411+ memcpy(&vlocation->vldb,cvol,sizeof(*cvol));
412+ brelse(bh);
413+
414+ /* note the volume ID */
415+ bix -= vlocation->cache->layout.off_volume_cache;
416+ vlocation->vix.index = (ix + bix * (sizeof(*cvols)/sizeof(*cvol))) << 2;
417+
418+ _leave(" = 0 (bix=%u ix=%u vix=%hu)",bix,ix,vlocation->vix.index);
419+#endif
420+ return 0;
421+
422+} /* end afs_cache_lookup_vlocation() */
423+
424+/*****************************************************************************/
425+/*
426+ * search for a volume location record in the cache, and if one's not available then reap the
427+ * eldest not currently in use
428+ */
429+int afs_cache_update_vlocation(afs_vlocation_t *vlocation)
430+{
431+ BUG();
432+
433+#if 0
434+ struct afs_cache_volume_block *cvols;
435+ struct afs_cache_volume *cvol;
436+ struct buffer_head *bh;
437+ afs_cache_bix_t bix;
438+ unsigned rem, stop, ix, candidate, tmp;
439+ time_t cand_age;
440+ int ret;
441+
442+
443+ _enter("%s,{v=%s cix=%u}",
444+ kdevname(vlocation->cache->dev),vlocation->vldb.name,vlocation->vldb.cell_ix);
445+
446+ candidate = UINT_MAX;
447+ cand_age = ULONG_MAX;
448+ rem = vlocation->cache->layout.nvols;
449+
450+ for (bix=vlocation->cache->layout.off_volume_cache;
451+ bix<vlocation->cache->layout.off_vnode_bitmap;
452+ bix++
453+ ) {
454+ /* read the next block */
455+ bh = __bread(vlocation->cache->bdev,bix,PAGE_CACHE_SIZE);
456+ if (!bh) {
457+ kleave(" = -EIO (block %u)",bix);
458+ return -EIO;
459+ }
460+
461+ cvols = (struct afs_cache_volume_block*) bh->b_data;
462+
463+ /* and scan it */
464+ stop = min((size_t)rem,sizeof(*cvols)/sizeof(*cvol));
465+ rem -= stop;
466+
467+ for (ix=0; ix<stop; ix++) {
468+ cvol = &cvols->entries[ix];
469+ if (cvol->name[0])
470+ _debug("FOUND[%u.%u]: cell %u vol '%s' %08x",
471+ bix,ix,cvol->cell_ix,cvol->name,cvol->vid[0]);
472+ if (cvol->cell_ix==vlocation->vldb.cell_ix &&
473+ memcmp(vlocation->vldb.name,cvol->name,sizeof(cvol->name))==0) {
474+ goto found;
475+ }
476+
477+ if (candidate!=UINT_MAX && cvol->ctime<cand_age) {
478+ /* TODO: don't recycle volumes currently in use */
479+ cand_age = cvol->ctime;
480+ candidate = bix - vlocation->cache->layout.off_volume_cache;
481+ candidate = ix + candidate * sizeof(*cvols)/sizeof(*cvol);
482+ }
483+ }
484+
485+ brelse(bh);
486+ }
487+
488+ /* TODO: recycle old entry if no spare slots available */
489+ if (vlocation->cache->layout.nvols>=vlocation->cache->layout.maxvols)
490+ BUG();
491+
492+ /* insert new entry */
493+ ix = vlocation->vix.index = vlocation->cache->layout.nvols++;
494+ tmp = (sizeof(*cvols)/sizeof(*cvol));
495+ bix = ix / tmp + vlocation->cache->layout.off_volume_cache;
496+ ix %= tmp;
497+
498+ kdebug("INSERT (bix=%u ix=%u)",bix,ix);
499+ ret = afs_cache_update_region(vlocation->cache,
500+ bix,
501+ ix*sizeof(*cvol),
502+ sizeof(*cvol),
503+ &vlocation->vldb);
504+ if (ret<0)
505+ goto out;
506+
507+ /* update the superblock */
508+ ret = afs_cache_update_region(vlocation->cache,
509+ 0,0,
510+ sizeof(vlocation->cache->layout),
511+ &vlocation->cache->layout);
512+
513+ /* TODO: handle failure by winding back cache->layout.nvols */
514+
515+ out:
516+ _leave(" = %d (bix=%u ix=%u vix=%hu)",ret,bix,ix,vlocation->vix.index);
517+ return ret;
518+
519+ found:
520+ brelse(bh);
521+
522+ /* update the on-disk cache with the latest news */
523+ _debug("UPDATE (bix=%u ix=%u)",bix,ix);
524+ ret = afs_cache_update_region(vlocation->cache,
525+ bix,
526+ ix*sizeof(*cvol),
527+ sizeof(*cvol),
528+ &vlocation->vldb);
529+ if (ret<0)
530+ goto out;
531+
532+ /* found the cell record - note the volume ID */
533+ bix -= vlocation->cache->layout.off_volume_cache;
534+ vlocation->vix.index = (ix + bix * (sizeof(*cvols)/sizeof(*cvol))) << 2;
535+
536+ _leave(" = 0 (bix=%u ix=%u vix=%hu)",bix,ix,vlocation->vix.index);
537+#endif
538+ return 0;
539+
540+} /* end afs_cache_update_vlocation() */
541+
542+/*****************************************************************************/
543+/*
544+ * search for a vnode record in the cache, and if one's not available then reap the
545+ * eldest not currently in use
546+ */
547+int afs_cache_lookup_vnode(afs_volume_t *volume, afs_vnode_t *vnode)
548+{
549+ BUG();
550+
551+#if 0
552+ struct afs_cache_vnode_index_block *cindexb;
553+ struct afs_cache_vnode_index cindex;
554+ struct buffer_head *bh;
555+ afs_cache_bix_t bix;
556+ unsigned rem, stop, ix, candidate, tmp;
557+ time_t cand_age;
558+ int ret;
559+
560+ _enter("{cix=%u vix=%u},{%u,%u,%u}",
561+ volume->cix,volume->vix.index,vnode->fid.vid,vnode->fid.vnode,vnode->fid.unique);
562+
563+ candidate = UINT_MAX;
564+ cand_age = ULONG_MAX;
565+ rem = volume->cache->layout.nvnodes;
566+
567+ for (bix=volume->cache->layout.off_vnode_index;
568+ bix<volume->cache->layout.off_vnode_cache;
569+ bix++
570+ ) {
571+ /* read the next block */
572+ bh = __bread(volume->cache->bdev,bix,PAGE_CACHE_SIZE);
573+ if (!bh) {
574+ kleave(" = -EIO (block %u)",bix);
575+ return -EIO;
576+ }
577+
578+ cindexb = (struct afs_cache_vnode_index_block*) bh->b_data;
579+
580+ /* and scan it */
581+ stop = min((size_t)rem,AFS_CACHE_VNODE_INDEX_PER_BLOCK);
582+ rem -= stop;
583+
584+ for (ix=0; ix<stop; ix++) {
585+ memcpy(&cindex,&cindexb->index[ix],sizeof(cindex));
586+
587+#if 0
588+ if (cindex.vnode>0)
589+ kdebug("FOUND[%u.%u]: vix %u vnode %u",
590+ bix,ix,cindex.volume_ix.index,cindex.vnode);
591+#endif
592+
593+ if (cindex.vnode==vnode->fid.vnode &&
594+ cindex.volume_ix.index==volume->vix.index)
595+ goto found;
596+
597+ if (candidate!=UINT_MAX && cindex.atime<cand_age) {
598+ /* TODO: don't recycle volumes currently in use */
599+ cand_age = cindex.atime;
600+ candidate = bix - volume->cache->layout.off_vnode_index;
601+ candidate = ix + candidate * AFS_CACHE_VNODE_INDEX_PER_BLOCK;
602+ }
603+ }
604+
605+ brelse(bh);
606+ }
607+
608+ /* TODO: recycle old entry if no spare slots available */
609+ if (volume->cache->layout.nvnodes>=volume->cache->layout.maxvnodes)
610+ BUG();
611+
612+ /* append new entry */
613+ vnode->nix = volume->cache->layout.nvnodes++;
614+
615+ cindex.vnode = vnode->fid.vnode;
616+ cindex.atime = xtime.tv_sec;
617+ cindex.volume_ix = volume->vix;
618+
619+ ix = vnode->nix;
620+ tmp = AFS_CACHE_VNODE_INDEX_PER_BLOCK;
621+ bix = ix / tmp + volume->cache->layout.off_vnode_index;
622+ ix %= tmp;
623+
624+ _debug("CACHE APPEND VNODE %u (bix=%u ix=%u)",vnode->nix,bix,ix);
625+ ret = afs_cache_update_region(volume->cache,
626+ bix,
627+ ix*sizeof(cindex),
628+ sizeof(cindex),
629+ &cindex);
630+ if (ret<0)
631+ goto out;
632+
633+ /* update the superblock */
634+ ret = afs_cache_update_region(volume->cache,
635+ 0,0,
636+ sizeof(volume->cache->layout),
637+ &volume->cache->layout);
638+
639+ /* TODO: handle failure by winding back cache->layout.nvnodes */
640+
641+ out:
642+ _leave(" = %d (bix=%u ix=%u nix=%u)",ret,bix,ix,vnode->nix);
643+ return ret;
644+
645+ found:
646+ brelse(bh);
647+
648+ cindex.atime = xtime.tv_sec;
649+
650+ /* update the on-disk cache with the latest news */
651+ _debug("UPDATE (bix=%u ix=%u)",bix,ix);
652+ ret = afs_cache_update_region(volume->cache,
653+ bix,
654+ ix*sizeof(cindex),
655+ sizeof(cindex),
656+ &cindex);
657+ if (ret<0)
658+ goto out;
659+
660+ /* found the cell record - note the volume ID */
661+ bix -= volume->cache->layout.off_vnode_index;
662+ vnode->nix = ix + bix * AFS_CACHE_VNODE_INDEX_PER_BLOCK;
663+
664+ _leave(" = 0 (bix=%u ix=%u nix=%u)",bix,ix,vnode->nix);
665+#endif
666+ return 0;
667+
668+} /* end afs_cache_lookup_vnode() */
669diff -urNp linux-5240/fs/afs/cache.h linux-5250/fs/afs/cache.h
670--- linux-5240/fs/afs/cache.h 1970-01-01 01:00:00.000000000 +0100
671+++ linux-5250/fs/afs/cache.h
672@@ -0,0 +1,48 @@
673+/* cache.h: AFS local cache management
674+ *
675+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
676+ * Written by David Howells (dhowells@redhat.com)
677+ *
678+ * This program is free software; you can redistribute it and/or
679+ * modify it under the terms of the GNU General Public License
680+ * as published by the Free Software Foundation; either version
681+ * 2 of the License, or (at your option) any later version.
682+ */
683+
684+#ifndef _LINUX_AFS_CACHE_H
685+#define _LINUX_AFS_CACHE_H
686+
687+#include <linux/fs.h>
688+#include "cache-layout.h"
689+
690+#ifdef __KERNEL__
691+
692+/*****************************************************************************/
693+/*
694+ * AFS cache management record
695+ */
696+struct afs_cache
697+{
698+ atomic_t usage; /* usage count */
699+ struct list_head link; /* link in cache list */
700+ kdev_t dev; /* device numbers */
701+ struct block_device *bdev; /* block device */
702+ struct file *bdfile; /* file attached to block device */
703+ struct rw_semaphore sem; /* access semaphore */
704+ struct afs_cache_super_block layout; /* layout description */
705+};
706+
707+extern int afs_cache_open(const char *name, afs_cache_t **_cache);
708+
709+#define afs_get_cache(C) do { atomic_inc(&(C)->usage); } while(0)
710+
711+extern void afs_put_cache(afs_cache_t *cache);
712+
713+extern int afs_cache_lookup_cell(afs_cache_t *cache, afs_cell_t *cell);
714+extern int afs_cache_lookup_vlocation(afs_vlocation_t *vlocation);
715+extern int afs_cache_update_vlocation(afs_vlocation_t *vlocation);
716+extern int afs_cache_lookup_vnode(afs_volume_t *volume, afs_vnode_t *vnode);
717+
718+#endif /* __KERNEL__ */
719+
720+#endif /* _LINUX_AFS_CACHE_H */
721diff -urNp linux-5240/fs/afs/cache-layout.h linux-5250/fs/afs/cache-layout.h
722--- linux-5240/fs/afs/cache-layout.h 1970-01-01 01:00:00.000000000 +0100
723+++ linux-5250/fs/afs/cache-layout.h
724@@ -0,0 +1,231 @@
725+/* cache-layout.h: AFS cache layout
726+ *
727+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
728+ * Written by David Howells (dhowells@redhat.com)
729+ *
730+ * This program is free software; you can redistribute it and/or
731+ * modify it under the terms of the GNU General Public License
732+ * as published by the Free Software Foundation; either version
733+ * 2 of the License, or (at your option) any later version.
734+ *
735+ *
736+ * The cache is stored on a block device and is laid out as follows:
737+ *
738+ * 0 +------------------------------------------------
739+ * |
740+ * | SuperBlock
741+ * |
742+ * 1 +------------------------------------------------
743+ * |
744+ * | Cell Cache (preloaded by mkafscache)
745+ * |
746+ * +------------------------------------------------
747+ * |
748+ * | Volume Cache Allocation BitMap (1 page)
749+ * |
750+ * +------------------------------------------------
751+ * |
752+ * | Volume Cache
753+ * |
754+ * +------------------------------------------------
755+ * |
756+ * | Vnode Cache Allocation BitMap
757+ * |
758+ * +------------------------------------------------
759+ * |
760+ * | Vnode Cache Index
761+ * |
762+ * +------------------------------------------------
763+ * |
764+ * | Vnode Cache
765+ * |
766+ * +------------------------------------------------
767+ * |
768+ * | Data Cache Allocation BitMap
769+ * |
770+ * +------------------------------------------------
771+ * |
772+ * | Data Cache
773+ * |
774+ * End +------------------------------------------------
775+ *
776+ */
777+
778+#ifndef _LINUX_AFS_CACHE_LAYOUT_H
779+#define _LINUX_AFS_CACHE_LAYOUT_H
780+
781+#include "types.h"
782+
783+typedef unsigned afs_cache_bix_t;
784+typedef unsigned short afs_cache_cellix_t;
785+
786+typedef struct { unsigned short index; } afs_cache_volix_t;
787+
788+/*****************************************************************************/
789+/*
790+ * cache superblock block layout
791+ */
792+struct afs_cache_super_block
793+{
794+ char magic[10]; /* magic number */
795+#define AFS_CACHE_SUPER_MAGIC "kafscache"
796+
797+ unsigned short endian; /* 0x1234 stored CPU-normal order */
798+#define AFS_CACHE_SUPER_ENDIAN 0x1234
799+
800+ unsigned version; /* format version */
801+#define AFS_CACHE_SUPER_VERSION 1
802+
803+ /* accounting */
804+ afs_cache_cellix_t ncells; /* number of cells cached */
805+ afs_cache_cellix_t maxcells; /* max number of cells cacheable */
806+ afs_cache_cellix_t thiscell; /* index of this cell in cache */
807+ unsigned short nvols; /* volume cache usage */
808+ unsigned short maxvols; /* maximum number of volumes cacheable */
809+ unsigned nvnodes; /* vnode cache usage */
810+ unsigned maxvnodes; /* maximum number of vnodes cacheable */
811+
812+ /* layout */
813+ unsigned bsize; /* cache block size */
814+ afs_cache_bix_t off_cell_cache; /* block offset of cell cache */
815+ afs_cache_bix_t off_volume_bitmap; /* block offset of volume alloc bitmap */
816+ afs_cache_bix_t off_volume_cache; /* block offset of volume cache */
817+ afs_cache_bix_t off_vnode_bitmap; /* block offset of vnode alloc bitmap */
818+ afs_cache_bix_t off_vnode_index; /* block offset of vnode index */
819+ afs_cache_bix_t off_vnode_cache; /* block offset of vnode cache */
820+ afs_cache_bix_t off_data_bitmap; /* block offset of data bitmap */
821+ afs_cache_bix_t off_data_cache; /* block offset of data cache */
822+ afs_cache_bix_t off_end; /* block offset of end of cache */
823+};
824+
825+/*****************************************************************************/
826+/*
827+ * cached cell info
828+ */
829+struct afs_cache_cell
830+{
831+ char name[64]; /* cell name (padded with NULs) */
832+ struct in_addr servers[16]; /* cached cell servers */
833+};
834+
835+struct afs_cache_cell_block
836+{
837+ struct afs_cache_cell entries[PAGE_SIZE/sizeof(struct afs_cache_cell)];
838+};
839+
840+/*****************************************************************************/
841+/*
842+ * cached volume info
843+ * - indexed by (afs_cache_volix_t/4)
844+ * - (afs_cache_volix_t%4) is 0 for R/W, 1 for R/O and 2 for Bak (3 is not used)
845+ */
846+struct afs_cache_volume
847+{
848+ char name[64]; /* volume name (padded with NULs) */
849+ afs_volid_t vid[3]; /* volume IDs for R/W, R/O and Bak volumes */
850+ unsigned char vidmask; /* voltype mask for vid[] */
851+ unsigned char _pad[1];
852+ unsigned short nservers; /* number of entries used in servers[] */
853+ struct in_addr servers[8]; /* fileserver addresses */
854+ unsigned char srvtmask[8]; /* voltype masks for servers[] */
855+#define AFS_CACHE_VOL_STM_RW 0x01 /* server holds a R/W version of the volume */
856+#define AFS_CACHE_VOL_STM_RO 0x02 /* server holds a R/O version of the volume */
857+#define AFS_CACHE_VOL_STM_BAK 0x04 /* server holds a backup version of the volume */
858+
859+ afs_cache_cellix_t cell_ix; /* cell cache index (MAX_UINT if unused) */
860+ time_t ctime; /* time at which cached */
861+};
862+
863+struct afs_cache_volume_block
864+{
865+ struct afs_cache_volume entries[PAGE_SIZE/sizeof(struct afs_cache_volume)];
866+};
867+
868+/*****************************************************************************/
869+/*
870+ * cached vnode index
871+ * - map on a 1:1 basis with the vnode index table
872+ */
873+struct afs_cache_vnode_index
874+{
875+ afs_vnodeid_t vnode; /* vnode ID */
876+ time_t atime; /* last time accessed */
877+ afs_cache_volix_t volume_ix; /* volume cache index */
878+} __attribute__((packed));
879+
880+#define AFS_CACHE_VNODE_INDEX_PER_BLOCK ((size_t)(PAGE_SIZE/sizeof(struct afs_cache_vnode_index)))
881+
882+struct afs_cache_vnode_index_block
883+{
884+ struct afs_cache_vnode_index index[AFS_CACHE_VNODE_INDEX_PER_BLOCK];
885+};
886+
887+/*****************************************************************************/
888+/*
889+ * cached vnode rights entry
890+ */
891+struct afs_cache_rights
892+{
893+ uid_t uid;
894+ unsigned access;
895+ unsigned short mode;
896+} __attribute__((packed));
897+
898+/*****************************************************************************/
899+/*
900+ * vnode (inode) metadata cache
901+ * - PAGE_SIZE in size
902+ */
903+struct afs_cache_vnode_block
904+{
905+ /* file ID */
906+ unsigned unique; /* FID unique */
907+
908+ /* file status */
909+ afs_file_type_t type; /* file type */
910+ unsigned nlink; /* link count */
911+ size_t size; /* file size */
912+ afs_dataversion_t version; /* current data version */
913+ unsigned author; /* author ID */
914+ unsigned owner; /* owner ID */
915+ unsigned anon_access; /* access rights for unauthenticated caller */
916+ unsigned short mode; /* UNIX mode */
917+ time_t mtime; /* last time server changed data */
918+ time_t cachetime; /* time at which cached */
919+
920+ /* file contents */
921+ afs_cache_bix_t pt0_bix; /* "page table 0" block index */
922+ afs_cache_bix_t pgd_bix; /* "page directory" block index */
923+
924+ /* access rights */
925+ size_t nrights; /* number of cached rights */
926+ struct afs_cache_rights rights[0]; /* cached access rights buffer */
927+};
928+
929+#define AFS_CACHE_VNODE_MAXRIGHTS \
930+ ((PAGE_SIZE - sizeof(struct afs_cache_vnode_block)) / sizeof(struct afs_cache_rights))
931+
932+/*****************************************************************************/
933+/*
934+ * vnode data "page directory" block
935+ * - first 1024 pages don't map through here
936+ * - PAGE_SIZE in size
937+ */
938+struct afs_cache_pgd_block
939+{
940+ unsigned _unused;
941+ afs_cache_bix_t pt_bix[1023]; /* "page table" block indices */
942+};
943+
944+/*****************************************************************************/
945+/*
946+ * vnode data "page table" block
947+ * - PAGE_SIZE in size
948+ */
949+struct afs_cache_pt_block
950+{
951+ afs_cache_bix_t page_bix[1024]; /* "page" block indices */
952+};
953+
954+
955+#endif /* _LINUX_AFS_CACHE_LAYOUT_H */
956diff -urNp linux-5240/fs/afs/callback.c linux-5250/fs/afs/callback.c
957--- linux-5240/fs/afs/callback.c 1970-01-01 01:00:00.000000000 +0100
958+++ linux-5250/fs/afs/callback.c
959@@ -0,0 +1,166 @@
960+/*
961+ * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
962+ *
963+ * This software may be freely redistributed under the terms of the
964+ * GNU General Public License.
965+ *
966+ * You should have received a copy of the GNU General Public License
967+ * along with this program; if not, write to the Free Software
968+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
969+ *
970+ * Authors: David Woodhouse <dwmw2@cambridge.redhat.com>
971+ * David Howells <dhowells@redhat.com>
972+ *
973+ */
974+
975+#include <linux/kernel.h>
976+#include <linux/module.h>
977+#include <linux/init.h>
978+#include "server.h"
979+#include "vnode.h"
980+#include "internal.h"
981+
982+/*****************************************************************************/
983+/*
984+ * allow the fileserver to request callback state (re-)initialisation
985+ */
986+int SRXAFSCM_InitCallBackState(afs_server_t *server)
987+{
988+ struct list_head callbacks;
989+
990+ _enter("%p",server);
991+
992+ INIT_LIST_HEAD(&callbacks);
993+
994+ /* transfer the callback list from the server to a temp holding area */
995+ spin_lock(&server->cb_lock);
996+
997+ list_add(&callbacks,&server->cb_promises);
998+ list_del_init(&server->cb_promises);
999+
1000+ /* munch our way through the list, grabbing the inode, dropping all the locks and regetting
1001+ * them in the right order
1002+ */
1003+ while (!list_empty(&callbacks)) {
1004+ struct inode *inode;
1005+ afs_vnode_t *vnode;
1006+
1007+ vnode = list_entry(callbacks.next,afs_vnode_t,cb_link);
1008+ list_del_init(&vnode->cb_link);
1009+
1010+ /* try and grab the inode - may fail */
1011+ inode = igrab(AFS_VNODE_TO_I(vnode));
1012+ if (inode) {
1013+ int release = 0;
1014+
1015+ spin_unlock(&server->cb_lock);
1016+ spin_lock(&vnode->lock);
1017+
1018+ if (cmpxchg(&vnode->cb_server,server,NULL)==server) {
1019+ afs_kafstimod_del_timer(&vnode->cb_timeout);
1020+ spin_lock(&afs_cb_hash_lock);
1021+ list_del_init(&vnode->cb_hash_link);
1022+ spin_unlock(&afs_cb_hash_lock);
1023+ release = 1;
1024+ }
1025+
1026+ spin_unlock(&vnode->lock);
1027+
1028+ iput(inode);
1029+ if (release) afs_put_server(server);
1030+
1031+ spin_lock(&server->cb_lock);
1032+ }
1033+ }
1034+
1035+ spin_unlock(&server->cb_lock);
1036+
1037+ _leave(" = 0");
1038+ return 0;
1039+} /* end SRXAFSCM_InitCallBackState() */
1040+
1041+/*****************************************************************************/
1042+/*
1043+ * allow the fileserver to break callback promises
1044+ */
1045+int SRXAFSCM_CallBack(afs_server_t *server, size_t count, afs_callback_t callbacks[])
1046+{
1047+ struct list_head *_p;
1048+
1049+ _enter("%p,%u,",server,count);
1050+
1051+ for (; count>0; callbacks++, count--) {
1052+ struct inode *inode = NULL;
1053+ afs_vnode_t *vnode = NULL;
1054+ int valid = 0;
1055+
1056+ _debug("- Fid { vl=%08x n=%u u=%u } CB { v=%u x=%u t=%u }",
1057+ callbacks->fid.vid,
1058+ callbacks->fid.vnode,
1059+ callbacks->fid.unique,
1060+ callbacks->version,
1061+ callbacks->expiry,
1062+ callbacks->type
1063+ );
1064+
1065+ /* find the inode for this fid */
1066+ spin_lock(&afs_cb_hash_lock);
1067+
1068+ list_for_each(_p,&afs_cb_hash(server,&callbacks->fid)) {
1069+ vnode = list_entry(_p,afs_vnode_t,cb_hash_link);
1070+
1071+ if (memcmp(&vnode->fid,&callbacks->fid,sizeof(afs_fid_t))!=0)
1072+ continue;
1073+
1074+ /* right vnode, but is it same server? */
1075+ if (vnode->cb_server!=server)
1076+ break; /* no */
1077+
1078+ /* try and nail the inode down */
1079+ inode = igrab(AFS_VNODE_TO_I(vnode));
1080+ break;
1081+ }
1082+
1083+ spin_unlock(&afs_cb_hash_lock);
1084+
1085+ if (inode) {
1086+ /* we've found the record for this vnode */
1087+ spin_lock(&vnode->lock);
1088+ if (cmpxchg(&vnode->cb_server,server,NULL)==server) {
1089+ /* the callback _is_ on the calling server */
1090+ valid = 1;
1091+
1092+ afs_kafstimod_del_timer(&vnode->cb_timeout);
1093+ vnode->flags |= AFS_VNODE_CHANGED;
1094+
1095+ spin_lock(&server->cb_lock);
1096+ list_del_init(&vnode->cb_link);
1097+ spin_unlock(&server->cb_lock);
1098+
1099+ spin_lock(&afs_cb_hash_lock);
1100+ list_del_init(&vnode->cb_hash_link);
1101+ spin_unlock(&afs_cb_hash_lock);
1102+ }
1103+ spin_unlock(&vnode->lock);
1104+
1105+ if (valid) {
1106+ invalidate_inode_pages(inode);
1107+ afs_put_server(server);
1108+ }
1109+ iput(inode);
1110+ }
1111+ }
1112+
1113+ _leave(" = 0");
1114+ return 0;
1115+} /* end SRXAFSCM_CallBack() */
1116+
1117+/*****************************************************************************/
1118+/*
1119+ * allow the fileserver to see if the cache manager is still alive
1120+ */
1121+int SRXAFSCM_Probe(afs_server_t *server)
1122+{
1123+ _debug("SRXAFSCM_Probe(%p)\n",server);
1124+ return 0;
1125+} /* end SRXAFSCM_Probe() */
1126diff -urNp linux-5240/fs/afs/cell.c linux-5250/fs/afs/cell.c
1127--- linux-5240/fs/afs/cell.c 1970-01-01 01:00:00.000000000 +0100
1128+++ linux-5250/fs/afs/cell.c
1129@@ -0,0 +1,452 @@
1130+/* cell.c: AFS cell and server record management
1131+ *
1132+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
1133+ * Written by David Howells (dhowells@redhat.com)
1134+ *
1135+ * This program is free software; you can redistribute it and/or
1136+ * modify it under the terms of the GNU General Public License
1137+ * as published by the Free Software Foundation; either version
1138+ * 2 of the License, or (at your option) any later version.
1139+ */
1140+
1141+#include <linux/module.h>
1142+#include <linux/sched.h>
1143+#include <linux/slab.h>
1144+#include <rxrpc/peer.h>
1145+#include <rxrpc/connection.h>
1146+#include "volume.h"
1147+#include "cell.h"
1148+#include "server.h"
1149+#include "transport.h"
1150+#include "cache.h"
1151+#include "vlclient.h"
1152+#include "kafstimod.h"
1153+#include "super.h"
1154+#include "internal.h"
1155+
1156+DECLARE_RWSEM(afs_proc_cells_sem);
1157+LIST_HEAD(afs_proc_cells);
1158+
1159+static struct list_head afs_cells = LIST_HEAD_INIT(afs_cells);
1160+static rwlock_t afs_cells_lock = RW_LOCK_UNLOCKED;
1161+static DECLARE_RWSEM(afs_cells_sem); /* add/remove serialisation */
1162+static afs_cell_t *afs_cell_root;
1163+
1164+static char *rootcell;
1165+
1166+MODULE_PARM(rootcell,"s");
1167+MODULE_PARM_DESC(rootcell,"root AFS cell name and VL server IP addr list");
1168+
1169+/*****************************************************************************/
1170+/*
1171+ * create a cell record
1172+ * - "name" is the name of the cell
1173+ * - "vllist" is a colon separated list of IP addresses in "a.b.c.d" format
1174+ */
1175+int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell)
1176+{
1177+ afs_cell_t *cell;
1178+ char *next;
1179+ int ret;
1180+
1181+ _enter("%s",name);
1182+
1183+ if (!name) BUG(); /* TODO: want to look up "this cell" in the cache */
1184+
1185+ down_write(&afs_cells_sem);
1186+
1187+ /* allocate and initialise a cell record */
1188+ cell = kmalloc(sizeof(afs_cell_t) + strlen(name) + 1,GFP_KERNEL);
1189+ if (!cell) {
1190+ _leave(" = -ENOMEM");
1191+ return -ENOMEM;
1192+ }
1193+
1194+ memset(cell,0,sizeof(afs_cell_t));
1195+ atomic_set(&cell->usage,0);
1196+
1197+ INIT_LIST_HEAD(&cell->link);
1198+
1199+ rwlock_init(&cell->sv_lock);
1200+ INIT_LIST_HEAD(&cell->sv_list);
1201+ INIT_LIST_HEAD(&cell->sv_graveyard);
1202+ spin_lock_init(&cell->sv_gylock);
1203+
1204+ init_rwsem(&cell->vl_sem);
1205+ INIT_LIST_HEAD(&cell->vl_list);
1206+ INIT_LIST_HEAD(&cell->vl_graveyard);
1207+ spin_lock_init(&cell->vl_gylock);
1208+
1209+ strcpy(cell->name,name);
1210+
1211+ /* fill in the VL server list from the rest of the string */
1212+ ret = -EINVAL;
1213+ do {
1214+ unsigned a, b, c, d;
1215+
1216+ next = strchr(vllist,':');
1217+ if (next) *next++ = 0;
1218+
1219+ if (sscanf(vllist,"%u.%u.%u.%u",&a,&b,&c,&d)!=4)
1220+ goto badaddr;
1221+
1222+ if (a>255 || b>255 || c>255 || d>255)
1223+ goto badaddr;
1224+
1225+ cell->vl_addrs[cell->vl_naddrs++].s_addr =
1226+ htonl((a<<24)|(b<<16)|(c<<8)|d);
1227+
1228+ if (cell->vl_naddrs>=16)
1229+ break;
1230+
1231+ } while(vllist=next, vllist);
1232+
1233+ /* add a proc dir for this cell */
1234+ ret = afs_proc_cell_setup(cell);
1235+ if (ret<0)
1236+ goto error;
1237+
1238+ /* add to the cell lists */
1239+ write_lock(&afs_cells_lock);
1240+ list_add_tail(&cell->link,&afs_cells);
1241+ write_unlock(&afs_cells_lock);
1242+
1243+ down_write(&afs_proc_cells_sem);
1244+ list_add_tail(&cell->proc_link,&afs_proc_cells);
1245+ up_write(&afs_proc_cells_sem);
1246+
1247+ *_cell = cell;
1248+ up_write(&afs_cells_sem);
1249+
1250+ _leave(" = 0 (%p)",cell);
1251+ return 0;
1252+
1253+ badaddr:
1254+ printk("kAFS: bad VL server IP address: '%s'\n",vllist);
1255+ error:
1256+ up_write(&afs_cells_sem);
1257+ kfree(afs_cell_root);
1258+ return ret;
1259+} /* end afs_cell_create() */
1260+
1261+/*****************************************************************************/
1262+/*
1263+ * initialise the cell database from module parameters
1264+ */
1265+int afs_cell_init(void)
1266+{
1267+ char *cp;
1268+ int ret;
1269+
1270+ _enter("");
1271+
1272+ if (!rootcell) {
1273+ printk("kAFS: no root cell specified\n");
1274+ return -EINVAL;
1275+ }
1276+
1277+ cp = strchr(rootcell,':');
1278+ if (!cp) {
1279+ printk("kAFS: no VL server IP addresses specified\n");
1280+ return -EINVAL;
1281+ }
1282+
1283+ /* allocate a cell record for the root cell */
1284+ *cp++ = 0;
1285+ ret = afs_cell_create(rootcell,cp,&afs_cell_root);
1286+ if (ret==0)
1287+ afs_get_cell(afs_cell_root);
1288+
1289+ _leave(" = %d",ret);
1290+ return ret;
1291+
1292+} /* end afs_cell_init() */
1293+
1294+/*****************************************************************************/
1295+/*
1296+ * lookup a cell record
1297+ */
1298+int afs_cell_lookup(afs_cache_t *cache, const char *name, afs_cell_t **_cell)
1299+{
1300+ struct list_head *_p;
1301+ afs_cell_t *cell;
1302+
1303+ _enter("\"%s\",",name?name:"*thiscell*");
1304+
1305+ cell = afs_cell_root;
1306+
1307+ if (name) {
1308+ /* if the cell was named, look for it in the cell record list */
1309+ cell = NULL;
1310+ read_lock(&afs_cells_lock);
1311+
1312+ list_for_each(_p,&afs_cells) {
1313+ cell = list_entry(_p,afs_cell_t,link);
1314+ if (strcmp(cell->name,name)==0)
1315+ break;
1316+ cell = NULL;
1317+ }
1318+
1319+ read_unlock(&afs_cells_lock);
1320+ }
1321+
1322+ if (cell)
1323+ afs_get_cell(cell);
1324+
1325+ *_cell = cell;
1326+ _leave(" = %d (%p)",cell?0:-ENOENT,cell);
1327+ return cell ? 0 : -ENOENT;
1328+
1329+} /* end afs_cell_lookup() */
1330+
1331+/*****************************************************************************/
1332+/*
1333+ * try and get a cell record
1334+ */
1335+afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell)
1336+{
1337+ afs_cell_t *cell;
1338+
1339+ write_lock(&afs_cells_lock);
1340+
1341+ cell = *_cell;
1342+ if (cell && !list_empty(&cell->link))
1343+ atomic_inc(&cell->usage);
1344+ else
1345+ cell = NULL;
1346+
1347+ write_unlock(&afs_cells_lock);
1348+
1349+ return cell;
1350+} /* end afs_get_cell_maybe() */
1351+
1352+/*****************************************************************************/
1353+/*
1354+ * destroy a cell record
1355+ */
1356+void afs_put_cell(afs_cell_t *cell)
1357+{
1358+ _enter("%p{%d,%s}",cell,atomic_read(&cell->usage),cell->name);
1359+
1360+ /* sanity check */
1361+ if (atomic_read(&cell->usage)<=0)
1362+ BUG();
1363+
1364+ /* to prevent a race, the decrement and the dequeue must be effectively atomic */
1365+ write_lock(&afs_cells_lock);
1366+
1367+ if (likely(!atomic_dec_and_test(&cell->usage))) {
1368+ write_unlock(&afs_cells_lock);
1369+ _leave("");
1370+ return;
1371+ }
1372+
1373+ write_unlock(&afs_cells_lock);
1374+
1375+ if (!list_empty(&cell->sv_list)) BUG();
1376+ if (!list_empty(&cell->sv_graveyard)) BUG();
1377+ if (!list_empty(&cell->vl_list)) BUG();
1378+ if (!list_empty(&cell->vl_graveyard)) BUG();
1379+
1380+ _leave(" [unused]");
1381+} /* end afs_put_cell() */
1382+
1383+/*****************************************************************************/
1384+/*
1385+ * destroy a cell record
1386+ */
1387+static void afs_cell_destroy(afs_cell_t *cell)
1388+{
1389+ _enter("%p{%d,%s}",cell,atomic_read(&cell->usage),cell->name);
1390+
1391+ /* to prevent a race, the decrement and the dequeue must be effectively atomic */
1392+ write_lock(&afs_cells_lock);
1393+
1394+ /* sanity check */
1395+ if (atomic_read(&cell->usage)!=0)
1396+ BUG();
1397+
1398+ list_del_init(&cell->link);
1399+
1400+ write_unlock(&afs_cells_lock);
1401+
1402+ down_write(&afs_cells_sem);
1403+
1404+ afs_proc_cell_remove(cell);
1405+
1406+ down_write(&afs_proc_cells_sem);
1407+ list_del_init(&afs_cell_root->proc_link);
1408+ up_write(&afs_proc_cells_sem);
1409+
1410+ up_write(&afs_cells_sem);
1411+
1412+ if (!list_empty(&cell->sv_list)) BUG();
1413+ if (!list_empty(&cell->sv_graveyard)) BUG();
1414+ if (!list_empty(&cell->vl_list)) BUG();
1415+ if (!list_empty(&cell->vl_graveyard)) BUG();
1416+
1417+ /* finish cleaning up the cell */
1418+ kfree(cell);
1419+
1420+ _leave(" [destroyed]");
1421+} /* end afs_cell_destroy() */
1422+
1423+/*****************************************************************************/
1424+/*
1425+ * lookup the server record corresponding to an Rx RPC peer
1426+ */
1427+int afs_server_find_by_peer(const struct rxrpc_peer *peer, afs_server_t **_server)
1428+{
1429+ struct list_head *_pc, *_ps;
1430+ afs_server_t *server;
1431+ afs_cell_t *cell;
1432+
1433+ _enter("%p{a=%08x},",peer,ntohl(peer->addr.s_addr));
1434+
1435+ /* search the cell list */
1436+ read_lock(&afs_cells_lock);
1437+
1438+ list_for_each(_pc,&afs_cells) {
1439+ cell = list_entry(_pc,afs_cell_t,link);
1440+
1441+ _debug("? cell %s",cell->name);
1442+
1443+ write_lock(&cell->sv_lock);
1444+
1445+ /* check the active list */
1446+ list_for_each(_ps,&cell->sv_list) {
1447+ server = list_entry(_ps,afs_server_t,link);
1448+
1449+ _debug("?? server %08x",ntohl(server->addr.s_addr));
1450+
1451+ if (memcmp(&server->addr,&peer->addr,sizeof(struct in_addr))==0)
1452+ goto found_server;
1453+ }
1454+
1455+ /* check the inactive list */
1456+ spin_lock(&cell->sv_gylock);
1457+ list_for_each(_ps,&cell->sv_graveyard) {
1458+ server = list_entry(_ps,afs_server_t,link);
1459+
1460+ _debug("?? dead server %08x",ntohl(server->addr.s_addr));
1461+
1462+ if (memcmp(&server->addr,&peer->addr,sizeof(struct in_addr))==0)
1463+ goto found_dead_server;
1464+ }
1465+ spin_unlock(&cell->sv_gylock);
1466+
1467+ write_unlock(&cell->sv_lock);
1468+ }
1469+ read_unlock(&afs_cells_lock);
1470+
1471+ _leave(" = -ENOENT");
1472+ return -ENOENT;
1473+
1474+ /* we found it in the graveyard - resurrect it */
1475+ found_dead_server:
1476+ list_del(&server->link);
1477+ list_add_tail(&server->link,&cell->sv_list);
1478+ afs_get_server(server);
1479+ afs_kafstimod_del_timer(&server->timeout);
1480+ spin_unlock(&cell->sv_gylock);
1481+ goto success;
1482+
1483+ /* we found it - increment its ref count and return it */
1484+ found_server:
1485+ afs_get_server(server);
1486+
1487+ success:
1488+ write_unlock(&cell->sv_lock);
1489+ read_unlock(&afs_cells_lock);
1490+
1491+ *_server = server;
1492+ _leave(" = 0 (s=%p c=%p)",server,cell);
1493+ return 0;
1494+
1495+} /* end afs_server_find_by_peer() */
1496+
1497+/*****************************************************************************/
1498+/*
1499+ * purge in-memory cell database on module unload
1500+ * - the timeout daemon is stopped before calling this
1501+ */
1502+void afs_cell_purge(void)
1503+{
1504+ afs_vlocation_t *vlocation;
1505+ afs_cell_t *cell;
1506+
1507+ _enter("");
1508+
1509+ if (afs_cell_root)
1510+ afs_put_cell(afs_cell_root);
1511+
1512+ while (!list_empty(&afs_cells)) {
1513+ cell = NULL;
1514+
1515+ /* remove the next cell from the front of the list */
1516+ write_lock(&afs_cells_lock);
1517+
1518+ if (!list_empty(&afs_cells)) {
1519+ cell = list_entry(afs_cells.next,afs_cell_t,link);
1520+ list_del_init(&cell->link);
1521+ }
1522+
1523+ write_unlock(&afs_cells_lock);
1524+
1525+ if (cell) {
1526+ _debug("PURGING CELL %s (%d)",cell->name,atomic_read(&cell->usage));
1527+
1528+ if (!list_empty(&cell->sv_list)) BUG();
1529+ if (!list_empty(&cell->vl_list)) BUG();
1530+
1531+ /* purge the cell's VL graveyard list */
1532+ _debug(" - clearing VL graveyard");
1533+
1534+ spin_lock(&cell->vl_gylock);
1535+
1536+ while (!list_empty(&cell->vl_graveyard)) {
1537+ vlocation = list_entry(cell->vl_graveyard.next,
1538+ afs_vlocation_t,link);
1539+ list_del_init(&vlocation->link);
1540+
1541+ afs_kafstimod_del_timer(&vlocation->timeout);
1542+
1543+ spin_unlock(&cell->vl_gylock);
1544+
1545+ afs_vlocation_do_timeout(vlocation);
1546+#warning race if move to use krxtimod instead of kafstimod
1547+
1548+ spin_lock(&cell->vl_gylock);
1549+ }
1550+
1551+ spin_unlock(&cell->vl_gylock);
1552+
1553+ /* purge the cell's server graveyard list */
1554+ _debug(" - clearing server graveyard");
1555+
1556+ spin_lock(&cell->sv_gylock);
1557+
1558+ while (!list_empty(&cell->sv_graveyard)) {
1559+ afs_server_t *server;
1560+
1561+ server = list_entry(cell->sv_graveyard.next,afs_server_t,link);
1562+ list_del_init(&server->link);
1563+
1564+ afs_kafstimod_del_timer(&server->timeout);
1565+
1566+ spin_unlock(&cell->sv_gylock);
1567+
1568+ afs_server_do_timeout(server);
1569+
1570+ spin_lock(&cell->sv_gylock);
1571+ }
1572+
1573+ spin_unlock(&cell->sv_gylock);
1574+
1575+ /* now the cell should be left with no references */
1576+ afs_cell_destroy(cell);
1577+ }
1578+ }
1579+
1580+ _leave("");
1581+} /* end afs_cell_purge() */
1582diff -urNp linux-5240/fs/afs/cell.h linux-5250/fs/afs/cell.h
1583--- linux-5240/fs/afs/cell.h 1970-01-01 01:00:00.000000000 +0100
1584+++ linux-5250/fs/afs/cell.h
1585@@ -0,0 +1,64 @@
1586+/* cell.h: AFS cell record
1587+ *
1588+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
1589+ * Written by David Howells (dhowells@redhat.com)
1590+ *
1591+ * This program is free software; you can redistribute it and/or
1592+ * modify it under the terms of the GNU General Public License
1593+ * as published by the Free Software Foundation; either version
1594+ * 2 of the License, or (at your option) any later version.
1595+ */
1596+
1597+#ifndef _LINUX_AFS_CELL_H
1598+#define _LINUX_AFS_CELL_H
1599+
1600+#include "types.h"
1601+#include "cache-layout.h"
1602+
1603+extern volatile int afs_cells_being_purged; /* T when cells are being purged by rmmod */
1604+
1605+/*****************************************************************************/
1606+/*
1607+ * AFS cell record
1608+ */
1609+struct afs_cell
1610+{
1611+ atomic_t usage;
1612+ struct list_head link; /* main cell list link */
1613+ struct list_head proc_link; /* /proc cell list link */
1614+ struct proc_dir_entry *proc_dir; /* /proc dir for this cell */
1615+ afs_cache_cellix_t cache_ix; /* cell cache index */
1616+
1617+ /* server record management */
1618+ rwlock_t sv_lock; /* active server list lock */
1619+ struct list_head sv_list; /* active server list */
1620+ struct list_head sv_graveyard; /* inactive server list */
1621+ spinlock_t sv_gylock; /* inactive server list lock */
1622+
1623+ /* volume location record management */
1624+ struct rw_semaphore vl_sem; /* volume management serialisation semaphore */
1625+ struct list_head vl_list; /* cell's active VL record list */
1626+ struct list_head vl_graveyard; /* cell's inactive VL record list */
1627+ spinlock_t vl_gylock; /* graveyard lock */
1628+ unsigned short vl_naddrs; /* number of VL servers in addr list */
1629+ unsigned short vl_curr_svix; /* current server index */
1630+ struct in_addr vl_addrs[16]; /* cell VL server addresses */
1631+
1632+ char name[0]; /* cell name - must go last */
1633+};
1634+
1635+extern int afs_cell_init(void);
1636+
1637+extern int afs_cell_create(const char *name, char *vllist, afs_cell_t **_cell);
1638+
1639+extern int afs_cell_lookup(afs_cache_t *cache, const char *name, afs_cell_t **_cell);
1640+
1641+#define afs_get_cell(C) do { atomic_inc(&(C)->usage); } while(0)
1642+
1643+extern afs_cell_t *afs_get_cell_maybe(afs_cell_t **_cell);
1644+
1645+extern void afs_put_cell(afs_cell_t *cell);
1646+
1647+extern void afs_cell_purge(void);
1648+
1649+#endif /* _LINUX_AFS_CELL_H */
1650diff -urNp linux-5240/fs/afs/cmservice.c linux-5250/fs/afs/cmservice.c
1651--- linux-5240/fs/afs/cmservice.c 1970-01-01 01:00:00.000000000 +0100
1652+++ linux-5250/fs/afs/cmservice.c
1653@@ -0,0 +1,639 @@
1654+/* cmservice.c: AFS Cache Manager Service
1655+ *
1656+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
1657+ * Written by David Howells (dhowells@redhat.com)
1658+ *
1659+ * This program is free software; you can redistribute it and/or
1660+ * modify it under the terms of the GNU General Public License
1661+ * as published by the Free Software Foundation; either version
1662+ * 2 of the License, or (at your option) any later version.
1663+ */
1664+
1665+#include <linux/version.h>
1666+#include <linux/module.h>
1667+#include <linux/init.h>
1668+#include <linux/sched.h>
1669+#include <linux/completion.h>
1670+#include "server.h"
1671+#include "cell.h"
1672+#include "transport.h"
1673+#include <rxrpc/rxrpc.h>
1674+#include <rxrpc/transport.h>
1675+#include <rxrpc/connection.h>
1676+#include <rxrpc/call.h>
1677+#include "cmservice.h"
1678+#include "internal.h"
1679+
1680+static unsigned afscm_usage; /* AFS cache manager usage count */
1681+static struct rw_semaphore afscm_sem; /* AFS cache manager start/stop semaphore */
1682+
1683+static int afscm_new_call(struct rxrpc_call *call);
1684+static void afscm_attention(struct rxrpc_call *call);
1685+static void afscm_error(struct rxrpc_call *call);
1686+static void afscm_aemap(struct rxrpc_call *call);
1687+
1688+static void _SRXAFSCM_CallBack(struct rxrpc_call *call);
1689+static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call);
1690+static void _SRXAFSCM_Probe(struct rxrpc_call *call);
1691+
1692+typedef void (*_SRXAFSCM_xxxx_t)(struct rxrpc_call *call);
1693+
1694+static const struct rxrpc_operation AFSCM_ops[] = {
1695+ {
1696+ id: 204,
1697+ asize: RXRPC_APP_MARK_EOF,
1698+ name: "CallBack",
1699+ user: _SRXAFSCM_CallBack,
1700+ },
1701+ {
1702+ id: 205,
1703+ asize: RXRPC_APP_MARK_EOF,
1704+ name: "InitCallBackState",
1705+ user: _SRXAFSCM_InitCallBackState,
1706+ },
1707+ {
1708+ id: 206,
1709+ asize: RXRPC_APP_MARK_EOF,
1710+ name: "Probe",
1711+ user: _SRXAFSCM_Probe,
1712+ },
1713+#if 0
1714+ {
1715+ id: 207,
1716+ asize: RXRPC_APP_MARK_EOF,
1717+ name: "GetLock",
1718+ user: _SRXAFSCM_GetLock,
1719+ },
1720+ {
1721+ id: 208,
1722+ asize: RXRPC_APP_MARK_EOF,
1723+ name: "GetCE",
1724+ user: _SRXAFSCM_GetCE,
1725+ },
1726+ {
1727+ id: 209,
1728+ asize: RXRPC_APP_MARK_EOF,
1729+ name: "GetXStatsVersion",
1730+ user: _SRXAFSCM_GetXStatsVersion,
1731+ },
1732+ {
1733+ id: 210,
1734+ asize: RXRPC_APP_MARK_EOF,
1735+ name: "GetXStats",
1736+ user: _SRXAFSCM_GetXStats,
1737+ }
1738+#endif
1739+};
1740+
1741+static struct rxrpc_service AFSCM_service = {
1742+ name: "AFS/CM",
1743+ owner: THIS_MODULE,
1744+ link: LIST_HEAD_INIT(AFSCM_service.link),
1745+ new_call: afscm_new_call,
1746+ service_id: 1,
1747+ attn_func: afscm_attention,
1748+ error_func: afscm_error,
1749+ aemap_func: afscm_aemap,
1750+ ops_begin: &AFSCM_ops[0],
1751+ ops_end: &AFSCM_ops[sizeof(AFSCM_ops)/sizeof(AFSCM_ops[0])],
1752+};
1753+
1754+static DECLARE_COMPLETION(kafscmd_alive);
1755+static DECLARE_COMPLETION(kafscmd_dead);
1756+static DECLARE_WAIT_QUEUE_HEAD(kafscmd_sleepq);
1757+static LIST_HEAD(kafscmd_attention_list);
1758+static LIST_HEAD(afscm_calls);
1759+static spinlock_t afscm_calls_lock = SPIN_LOCK_UNLOCKED;
1760+static spinlock_t kafscmd_attention_lock = SPIN_LOCK_UNLOCKED;
1761+static int kafscmd_die;
1762+
1763+/*****************************************************************************/
1764+/*
1765+ * AFS Cache Manager kernel thread
1766+ */
1767+static int kafscmd(void *arg)
1768+{
1769+ DECLARE_WAITQUEUE(myself,current);
1770+
1771+ struct rxrpc_call *call;
1772+ _SRXAFSCM_xxxx_t func;
1773+ int die;
1774+
1775+ printk("kAFS: Started kafscmd %d\n",current->pid);
1776+ strcpy(current->comm,"kafscmd");
1777+
1778+ daemonize();
1779+
1780+ complete(&kafscmd_alive);
1781+
1782+ /* only certain signals are of interest */
1783+ spin_lock_irq(&current->sigmask_lock);
1784+ siginitsetinv(&current->blocked,0);
1785+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,3)
1786+ recalc_sigpending();
1787+#else
1788+ recalc_sigpending(current);
1789+#endif
1790+ spin_unlock_irq(&current->sigmask_lock);
1791+
1792+ /* loop around looking for things to attend to */
1793+ do {
1794+ if (list_empty(&kafscmd_attention_list)) {
1795+ set_current_state(TASK_INTERRUPTIBLE);
1796+ add_wait_queue(&kafscmd_sleepq,&myself);
1797+
1798+ for (;;) {
1799+ set_current_state(TASK_INTERRUPTIBLE);
1800+ if (!list_empty(&kafscmd_attention_list) ||
1801+ signal_pending(current) ||
1802+ kafscmd_die)
1803+ break;
1804+
1805+ schedule();
1806+ }
1807+
1808+ remove_wait_queue(&kafscmd_sleepq,&myself);
1809+ set_current_state(TASK_RUNNING);
1810+ }
1811+
1812+ die = kafscmd_die;
1813+
1814+ /* dequeue the next call requiring attention */
1815+ call = NULL;
1816+ spin_lock(&kafscmd_attention_lock);
1817+
1818+ if (!list_empty(&kafscmd_attention_list)) {
1819+ call = list_entry(kafscmd_attention_list.next,
1820+ struct rxrpc_call,
1821+ app_attn_link);
1822+ list_del_init(&call->app_attn_link);
1823+ die = 0;
1824+ }
1825+
1826+ spin_unlock(&kafscmd_attention_lock);
1827+
1828+ if (call) {
1829+ /* act upon it */
1830+ _debug("@@@ Begin Attend Call %p",call);
1831+
1832+ func = call->app_user;
1833+ if (func)
1834+ func(call);
1835+
1836+ rxrpc_put_call(call);
1837+
1838+ _debug("@@@ End Attend Call %p",call);
1839+ }
1840+
1841+ } while(!die);
1842+
1843+ /* and that's all */
1844+ complete_and_exit(&kafscmd_dead,0);
1845+
1846+} /* end kafscmd() */
1847+
1848+/*****************************************************************************/
1849+/*
1850+ * handle a call coming in to the cache manager
1851+ * - if I want to keep the call, I must increment its usage count
1852+ * - the return value will be negated and passed back in an abort packet if non-zero
1853+ * - serialised by virtue of there only being one krxiod
1854+ */
1855+static int afscm_new_call(struct rxrpc_call *call)
1856+{
1857+ _enter("%p{cid=%u u=%d}",call,ntohl(call->call_id),atomic_read(&call->usage));
1858+
1859+ rxrpc_get_call(call);
1860+
1861+ /* add to my current call list */
1862+ spin_lock(&afscm_calls_lock);
1863+ list_add(&call->app_link,&afscm_calls);
1864+ spin_unlock(&afscm_calls_lock);
1865+
1866+ _leave(" = 0");
1867+ return 0;
1868+
1869+} /* end afscm_new_call() */
1870+
1871+/*****************************************************************************/
1872+/*
1873+ * queue on the kafscmd queue for attention
1874+ */
1875+static void afscm_attention(struct rxrpc_call *call)
1876+{
1877+ _enter("%p{cid=%u u=%d}",call,ntohl(call->call_id),atomic_read(&call->usage));
1878+
1879+ spin_lock(&kafscmd_attention_lock);
1880+
1881+ if (list_empty(&call->app_attn_link)) {
1882+ list_add_tail(&call->app_attn_link,&kafscmd_attention_list);
1883+ rxrpc_get_call(call);
1884+ }
1885+
1886+ spin_unlock(&kafscmd_attention_lock);
1887+
1888+ wake_up(&kafscmd_sleepq);
1889+
1890+ _leave(" {u=%d}",atomic_read(&call->usage));
1891+} /* end afscm_attention() */
1892+
1893+/*****************************************************************************/
1894+/*
1895+ * handle my call being aborted
1896+ * - clean up, dequeue and put my ref to the call
1897+ */
1898+static void afscm_error(struct rxrpc_call *call)
1899+{
1900+ int removed;
1901+
1902+ _enter("%p{est=%s ac=%u er=%d}",
1903+ call,
1904+ rxrpc_call_error_states[call->app_err_state],
1905+ call->app_abort_code,
1906+ call->app_errno);
1907+
1908+ spin_lock(&kafscmd_attention_lock);
1909+
1910+ if (list_empty(&call->app_attn_link)) {
1911+ list_add_tail(&call->app_attn_link,&kafscmd_attention_list);
1912+ rxrpc_get_call(call);
1913+ }
1914+
1915+ spin_unlock(&kafscmd_attention_lock);
1916+
1917+ removed = 0;
1918+ spin_lock(&afscm_calls_lock);
1919+ if (!list_empty(&call->app_link)) {
1920+ list_del_init(&call->app_link);
1921+ removed = 1;
1922+ }
1923+ spin_unlock(&afscm_calls_lock);
1924+
1925+ if (removed)
1926+ rxrpc_put_call(call);
1927+
1928+ wake_up(&kafscmd_sleepq);
1929+
1930+ _leave("");
1931+} /* end afscm_error() */
1932+
1933+/*****************************************************************************/
1934+/*
1935+ * map afs abort codes to/from Linux error codes
1936+ * - called with call->lock held
1937+ */
1938+static void afscm_aemap(struct rxrpc_call *call)
1939+{
1940+ switch (call->app_err_state) {
1941+ case RXRPC_ESTATE_LOCAL_ABORT:
1942+ call->app_abort_code = -call->app_errno;
1943+ break;
1944+ case RXRPC_ESTATE_PEER_ABORT:
1945+ call->app_errno = -ECONNABORTED;
1946+ break;
1947+ default:
1948+ break;
1949+ }
1950+} /* end afscm_aemap() */
1951+
1952+/*****************************************************************************/
1953+/*
1954+ * start the cache manager service if not already started
1955+ */
1956+int afscm_start(void)
1957+{
1958+ int ret;
1959+
1960+ down_write(&afscm_sem);
1961+ if (!afscm_usage) {
1962+ ret = kernel_thread(kafscmd,NULL,0);
1963+ if (ret<0)
1964+ goto out;
1965+
1966+ wait_for_completion(&kafscmd_alive);
1967+
1968+ ret = rxrpc_add_service(afs_transport,&AFSCM_service);
1969+ if (ret<0)
1970+ goto kill;
1971+ }
1972+
1973+ afscm_usage++;
1974+ up_write(&afscm_sem);
1975+
1976+ return 0;
1977+
1978+ kill:
1979+ kafscmd_die = 1;
1980+ wake_up(&kafscmd_sleepq);
1981+ wait_for_completion(&kafscmd_dead);
1982+
1983+ out:
1984+ up_write(&afscm_sem);
1985+ return ret;
1986+
1987+} /* end afscm_start() */
1988+
1989+/*****************************************************************************/
1990+/*
1991+ * stop the cache manager service
1992+ */
1993+void afscm_stop(void)
1994+{
1995+ struct rxrpc_call *call;
1996+
1997+ down_write(&afscm_sem);
1998+
1999+ if (afscm_usage==0) BUG();
2000+ afscm_usage--;
2001+
2002+ if (afscm_usage==0) {
2003+ /* don't want more incoming calls */
2004+ rxrpc_del_service(afs_transport,&AFSCM_service);
2005+
2006+ /* abort any calls I've still got open (the afscm_error() will dequeue them) */
2007+ spin_lock(&afscm_calls_lock);
2008+ while (!list_empty(&afscm_calls)) {
2009+ call = list_entry(afscm_calls.next,struct rxrpc_call,app_link);
2010+ list_del_init(&call->app_link);
2011+ rxrpc_get_call(call);
2012+ spin_unlock(&afscm_calls_lock);
2013+
2014+ rxrpc_call_abort(call,-ESRCH); /* abort, dequeue and put */
2015+
2016+ rxrpc_put_call(call);
2017+
2018+ spin_lock(&afscm_calls_lock);
2019+ }
2020+ spin_unlock(&afscm_calls_lock);
2021+
2022+ /* get rid of my daemon */
2023+ kafscmd_die = 1;
2024+ wake_up(&kafscmd_sleepq);
2025+ wait_for_completion(&kafscmd_dead);
2026+
2027+ /* dispose of any calls waiting for attention */
2028+ spin_lock(&kafscmd_attention_lock);
2029+ while (!list_empty(&kafscmd_attention_list)) {
2030+ call = list_entry(kafscmd_attention_list.next,
2031+ struct rxrpc_call,
2032+ app_attn_link);
2033+
2034+ list_del_init(&call->app_attn_link);
2035+ spin_unlock(&kafscmd_attention_lock);
2036+
2037+ rxrpc_put_call(call);
2038+
2039+ spin_lock(&kafscmd_attention_lock);
2040+ }
2041+ spin_unlock(&kafscmd_attention_lock);
2042+ }
2043+
2044+ up_write(&afscm_sem);
2045+
2046+} /* end afscm_stop() */
2047+
2048+/*****************************************************************************/
2049+/*
2050+ * handle the fileserver breaking a set of callbacks
2051+ */
2052+static void _SRXAFSCM_CallBack(struct rxrpc_call *call)
2053+{
2054+ afs_server_t *server;
2055+ size_t count, qty, tmp;
2056+ int ret = 0, removed;
2057+
2058+ _enter("%p{acs=%s}",call,rxrpc_call_states[call->app_call_state]);
2059+
2060+ server = afs_server_get_from_peer(call->conn->peer);
2061+
2062+ switch (call->app_call_state) {
2063+ /* we've received the last packet
2064+ * - drain all the data from the call and send the reply
2065+ */
2066+ case RXRPC_CSTATE_SRVR_GOT_ARGS:
2067+ ret = -EBADMSG;
2068+ qty = call->app_ready_qty;
2069+ if (qty<8 || qty>50*(6*4)+8)
2070+ break;
2071+
2072+ {
2073+ afs_callback_t *cb, *pcb;
2074+ int loop;
2075+ u32 *fp, *bp;
2076+
2077+ fp = rxrpc_call_alloc_scratch(call,qty);
2078+
2079+ /* drag the entire argument block out to the scratch space */
2080+ ret = rxrpc_call_read_data(call,fp,qty,0);
2081+ if (ret<0)
2082+ break;
2083+
2084+ /* and unmarshall the parameter block */
2085+ ret = -EBADMSG;
2086+ count = ntohl(*fp++);
2087+ if (count>AFSCBMAX ||
2088+ (count*(3*4)+8 != qty && count*(6*4)+8 != qty))
2089+ break;
2090+
2091+ bp = fp + count*3;
2092+ tmp = ntohl(*bp++);
2093+ if (tmp>0 && tmp!=count)
2094+ break;
2095+ if (tmp==0)
2096+ bp = NULL;
2097+
2098+ pcb = cb = rxrpc_call_alloc_scratch_s(call,afs_callback_t);
2099+
2100+ for (loop=count-1; loop>=0; loop--) {
2101+ pcb->fid.vid = ntohl(*fp++);
2102+ pcb->fid.vnode = ntohl(*fp++);
2103+ pcb->fid.unique = ntohl(*fp++);
2104+ if (bp) {
2105+ pcb->version = ntohl(*bp++);
2106+ pcb->expiry = ntohl(*bp++);
2107+ pcb->type = ntohl(*bp++);
2108+ }
2109+ else {
2110+ pcb->version = 0;
2111+ pcb->expiry = 0;
2112+ pcb->type = AFSCM_CB_UNTYPED;
2113+ }
2114+ pcb++;
2115+ }
2116+
2117+ /* invoke the actual service routine */
2118+ ret = SRXAFSCM_CallBack(server,count,cb);
2119+ if (ret<0)
2120+ break;
2121+ }
2122+
2123+ /* send the reply */
2124+ ret = rxrpc_call_write_data(call,0,NULL,RXRPC_LAST_PACKET,GFP_KERNEL,0,&count);
2125+ if (ret<0)
2126+ break;
2127+ break;
2128+
2129+ /* operation complete */
2130+ case RXRPC_CSTATE_COMPLETE:
2131+ call->app_user = NULL;
2132+ removed = 0;
2133+ spin_lock(&afscm_calls_lock);
2134+ if (!list_empty(&call->app_link)) {
2135+ list_del_init(&call->app_link);
2136+ removed = 1;
2137+ }
2138+ spin_unlock(&afscm_calls_lock);
2139+
2140+ if (removed)
2141+ rxrpc_put_call(call);
2142+ break;
2143+
2144+ /* operation terminated on error */
2145+ case RXRPC_CSTATE_ERROR:
2146+ call->app_user = NULL;
2147+ break;
2148+
2149+ default:
2150+ break;
2151+ }
2152+
2153+ if (ret<0)
2154+ rxrpc_call_abort(call,ret);
2155+
2156+ if (server) afs_put_server(server);
2157+
2158+ _leave(" = %d",ret);
2159+
2160+} /* end _SRXAFSCM_CallBack() */
2161+
2162+/*****************************************************************************/
2163+/*
2164+ * handle the fileserver asking us to initialise our callback state
2165+ */
2166+static void _SRXAFSCM_InitCallBackState(struct rxrpc_call *call)
2167+{
2168+ afs_server_t *server;
2169+ size_t count;
2170+ int ret = 0, removed;
2171+
2172+ _enter("%p{acs=%s}",call,rxrpc_call_states[call->app_call_state]);
2173+
2174+ server = afs_server_get_from_peer(call->conn->peer);
2175+
2176+ switch (call->app_call_state) {
2177+ /* we've received the last packet - drain all the data from the call */
2178+ case RXRPC_CSTATE_SRVR_GOT_ARGS:
2179+ /* shouldn't be any args */
2180+ ret = -EBADMSG;
2181+ break;
2182+
2183+ /* send the reply when asked for it */
2184+ case RXRPC_CSTATE_SRVR_SND_REPLY:
2185+ /* invoke the actual service routine */
2186+ ret = SRXAFSCM_InitCallBackState(server);
2187+ if (ret<0)
2188+ break;
2189+
2190+ ret = rxrpc_call_write_data(call,0,NULL,RXRPC_LAST_PACKET,GFP_KERNEL,0,&count);
2191+ if (ret<0)
2192+ break;
2193+ break;
2194+
2195+ /* operation complete */
2196+ case RXRPC_CSTATE_COMPLETE:
2197+ call->app_user = NULL;
2198+ removed = 0;
2199+ spin_lock(&afscm_calls_lock);
2200+ if (!list_empty(&call->app_link)) {
2201+ list_del_init(&call->app_link);
2202+ removed = 1;
2203+ }
2204+ spin_unlock(&afscm_calls_lock);
2205+
2206+ if (removed)
2207+ rxrpc_put_call(call);
2208+ break;
2209+
2210+ /* operation terminated on error */
2211+ case RXRPC_CSTATE_ERROR:
2212+ call->app_user = NULL;
2213+ break;
2214+
2215+ default:
2216+ break;
2217+ }
2218+
2219+ if (ret<0)
2220+ rxrpc_call_abort(call,ret);
2221+
2222+ if (server) afs_put_server(server);
2223+
2224+ _leave(" = %d",ret);
2225+
2226+} /* end _SRXAFSCM_InitCallBackState() */
2227+
2228+/*****************************************************************************/
2229+/*
2230+ * handle a probe from a fileserver
2231+ */
2232+static void _SRXAFSCM_Probe(struct rxrpc_call *call)
2233+{
2234+ afs_server_t *server;
2235+ size_t count;
2236+ int ret = 0, removed;
2237+
2238+ _enter("%p{acs=%s}",call,rxrpc_call_states[call->app_call_state]);
2239+
2240+ server = afs_server_get_from_peer(call->conn->peer);
2241+
2242+ switch (call->app_call_state) {
2243+ /* we've received the last packet - drain all the data from the call */
2244+ case RXRPC_CSTATE_SRVR_GOT_ARGS:
2245+ /* shouldn't be any args */
2246+ ret = -EBADMSG;
2247+ break;
2248+
2249+ /* send the reply when asked for it */
2250+ case RXRPC_CSTATE_SRVR_SND_REPLY:
2251+ /* invoke the actual service routine */
2252+ ret = SRXAFSCM_Probe(server);
2253+ if (ret<0)
2254+ break;
2255+
2256+ ret = rxrpc_call_write_data(call,0,NULL,RXRPC_LAST_PACKET,GFP_KERNEL,0,&count);
2257+ if (ret<0)
2258+ break;
2259+ break;
2260+
2261+ /* operation complete */
2262+ case RXRPC_CSTATE_COMPLETE:
2263+ call->app_user = NULL;
2264+ removed = 0;
2265+ spin_lock(&afscm_calls_lock);
2266+ if (!list_empty(&call->app_link)) {
2267+ list_del_init(&call->app_link);
2268+ removed = 1;
2269+ }
2270+ spin_unlock(&afscm_calls_lock);
2271+
2272+ if (removed)
2273+ rxrpc_put_call(call);
2274+ break;
2275+
2276+ /* operation terminated on error */
2277+ case RXRPC_CSTATE_ERROR:
2278+ call->app_user = NULL;
2279+ break;
2280+
2281+ default:
2282+ break;
2283+ }
2284+
2285+ if (ret<0)
2286+ rxrpc_call_abort(call,ret);
2287+
2288+ if (server) afs_put_server(server);
2289+
2290+ _leave(" = %d",ret);
2291+
2292+} /* end _SRXAFSCM_Probe() */
2293diff -urNp linux-5240/fs/afs/cmservice.h linux-5250/fs/afs/cmservice.h
2294--- linux-5240/fs/afs/cmservice.h 1970-01-01 01:00:00.000000000 +0100
2295+++ linux-5250/fs/afs/cmservice.h
2296@@ -0,0 +1,27 @@
2297+/* cmservice.h: AFS Cache Manager Service declarations
2298+ *
2299+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
2300+ * Written by David Howells (dhowells@redhat.com)
2301+ *
2302+ * This program is free software; you can redistribute it and/or
2303+ * modify it under the terms of the GNU General Public License
2304+ * as published by the Free Software Foundation; either version
2305+ * 2 of the License, or (at your option) any later version.
2306+ */
2307+
2308+#ifndef _LINUX_AFS_CMSERVICE_H
2309+#define _LINUX_AFS_CMSERVICE_H
2310+
2311+#include <rxrpc/transport.h>
2312+#include "types.h"
2313+
2314+/* cache manager start/stop */
2315+extern int afscm_start(void);
2316+extern void afscm_stop(void);
2317+
2318+/* cache manager server functions */
2319+extern int SRXAFSCM_InitCallBackState(afs_server_t *server);
2320+extern int SRXAFSCM_CallBack(afs_server_t *server, size_t count, afs_callback_t callbacks[]);
2321+extern int SRXAFSCM_Probe(afs_server_t *server);
2322+
2323+#endif /* _LINUX_AFS_CMSERVICE_H */
2324diff -urNp linux-5240/fs/afs/dir.c linux-5250/fs/afs/dir.c
2325--- linux-5240/fs/afs/dir.c 1970-01-01 01:00:00.000000000 +0100
2326+++ linux-5250/fs/afs/dir.c
2327@@ -0,0 +1,640 @@
2328+/* dir.c: AFS filesystem directory handling
2329+ *
2330+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
2331+ * Written by David Howells (dhowells@redhat.com)
2332+ *
2333+ * This program is free software; you can redistribute it and/or
2334+ * modify it under the terms of the GNU General Public License
2335+ * as published by the Free Software Foundation; either version
2336+ * 2 of the License, or (at your option) any later version.
2337+ */
2338+
2339+#include <linux/kernel.h>
2340+#include <linux/module.h>
2341+#include <linux/init.h>
2342+#include <linux/sched.h>
2343+#include <linux/slab.h>
2344+#include <linux/fs.h>
2345+#include <linux/pagemap.h>
2346+#include <linux/smp_lock.h>
2347+#include "vnode.h"
2348+#include "volume.h"
2349+#include <rxrpc/call.h>
2350+#include "super.h"
2351+#include "internal.h"
2352+
2353+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry);
2354+static int afs_dir_open(struct inode *inode, struct file *file);
2355+static int afs_dir_readdir(struct file *file, void *dirent, filldir_t filldir);
2356+static int afs_d_revalidate(struct dentry *dentry, int flags);
2357+static int afs_d_delete(struct dentry *dentry);
2358+static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos,
2359+ ino_t ino, unsigned dtype);
2360+
2361+struct file_operations afs_dir_file_operations = {
2362+ open: afs_dir_open,
2363+ readdir: afs_dir_readdir,
2364+};
2365+
2366+struct inode_operations afs_dir_inode_operations = {
2367+ lookup: afs_dir_lookup,
2368+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2369+ getattr: afs_inode_getattr,
2370+#else
2371+ revalidate: afs_inode_revalidate,
2372+#endif
2373+// create: afs_dir_create,
2374+// link: afs_dir_link,
2375+// unlink: afs_dir_unlink,
2376+// symlink: afs_dir_symlink,
2377+// mkdir: afs_dir_mkdir,
2378+// rmdir: afs_dir_rmdir,
2379+// mknod: afs_dir_mknod,
2380+// rename: afs_dir_rename,
2381+};
2382+
2383+static struct dentry_operations afs_fs_dentry_operations = {
2384+ d_revalidate: afs_d_revalidate,
2385+ d_delete: afs_d_delete,
2386+};
2387+
2388+#define AFS_DIR_HASHTBL_SIZE 128
2389+#define AFS_DIR_DIRENT_SIZE 32
2390+#define AFS_DIRENT_PER_BLOCK 64
2391+
2392+typedef struct afs_dirent {
2393+ u8 valid;
2394+ u8 unused[1];
2395+ u16 hash_next;
2396+ u32 vnode;
2397+ u32 unique;
2398+ u8 name[16];
2399+ u8 overflow[4]; /* if any char of the name (inc NUL) reaches here, consume
2400+ * the next dirent too */
2401+ u8 extended_name[32];
2402+} afs_dirent_t;
2403+
2404+/* AFS directory page header (one at the beginning of every 2048-byte chunk) */
2405+typedef struct afs_dir_pagehdr {
2406+ u16 npages;
2407+ u16 magic;
2408+#define AFS_DIR_MAGIC htons(1234)
2409+ u8 nentries;
2410+ u8 bitmap[8];
2411+ u8 pad[19];
2412+} afs_dir_pagehdr_t;
2413+
2414+/* directory block layout */
2415+typedef union afs_dir_block {
2416+
2417+ afs_dir_pagehdr_t pagehdr;
2418+
2419+ struct {
2420+ afs_dir_pagehdr_t pagehdr;
2421+ u8 alloc_ctrs[128];
2422+ u16 hashtable[AFS_DIR_HASHTBL_SIZE]; /* dir hash table */
2423+ } hdr;
2424+
2425+ afs_dirent_t dirents[AFS_DIRENT_PER_BLOCK];
2426+} afs_dir_block_t;
2427+
2428+/* layout on a linux VM page */
2429+typedef struct afs_dir_page {
2430+ afs_dir_block_t blocks[PAGE_SIZE/sizeof(afs_dir_block_t)];
2431+} afs_dir_page_t;
2432+
2433+struct afs_dir_lookup_cookie {
2434+ afs_fid_t fid;
2435+ const char *name;
2436+ size_t nlen;
2437+ int found;
2438+};
2439+
2440+/*****************************************************************************/
2441+/*
2442+ * check that a directory page is valid
2443+ */
2444+static inline void afs_dir_check_page(struct inode *dir, struct page *page)
2445+{
2446+ afs_dir_page_t *dbuf;
2447+ loff_t latter;
2448+ int tmp, qty;
2449+
2450+#if 0
2451+ /* check the page count */
2452+ qty = desc.size/sizeof(dbuf->blocks[0]);
2453+ if (qty==0)
2454+ goto error;
2455+
2456+ if (page->index==0 && qty!=ntohs(dbuf->blocks[0].pagehdr.npages)) {
2457+ printk("kAFS: %s(%lu): wrong number of dir blocks %d!=%hu\n",
2458+ __FUNCTION__,dir->i_ino,qty,ntohs(dbuf->blocks[0].pagehdr.npages));
2459+ goto error;
2460+ }
2461+#endif
2462+
2463+ /* determine how many magic numbers there should be in this page */
2464+ latter = dir->i_size - (page->index << PAGE_CACHE_SHIFT);
2465+ if (latter >= PAGE_SIZE)
2466+ qty = PAGE_SIZE;
2467+ else
2468+ qty = latter;
2469+ qty /= sizeof(afs_dir_block_t);
2470+
2471+ /* check them */
2472+ dbuf = page_address(page);
2473+ for (tmp=0; tmp<qty; tmp++) {
2474+ if (dbuf->blocks[tmp].pagehdr.magic != AFS_DIR_MAGIC) {
2475+ printk("kAFS: %s(%lu): bad magic %d/%d is %04hx\n",
2476+ __FUNCTION__,dir->i_ino,tmp,
2477+ qty,ntohs(dbuf->blocks[tmp].pagehdr.magic));
2478+ goto error;
2479+ }
2480+ }
2481+
2482+ SetPageChecked(page);
2483+ return;
2484+
2485+ error:
2486+ SetPageChecked(page);
2487+ SetPageError(page);
2488+
2489+} /* end afs_dir_check_page() */
2490+
2491+/*****************************************************************************/
2492+/*
2493+ * discard a page cached in the pagecache
2494+ */
2495+static inline void afs_dir_put_page(struct page *page)
2496+{
2497+ kunmap(page);
2498+ page_cache_release(page);
2499+
2500+} /* end afs_dir_put_page() */
2501+
2502+/*****************************************************************************/
2503+/*
2504+ * get a page into the pagecache
2505+ */
2506+static struct page *afs_dir_get_page(struct inode *dir, unsigned long index)
2507+{
2508+ struct page *page;
2509+
2510+ _enter("{%lu},%lu",dir->i_ino,index);
2511+
2512+ page = read_cache_page(dir->i_mapping,index,
2513+ (filler_t*)dir->i_mapping->a_ops->readpage,NULL);
2514+ if (!IS_ERR(page)) {
2515+ wait_on_page_locked(page);
2516+ kmap(page);
2517+ if (!PageUptodate(page))
2518+ goto fail;
2519+ if (!PageChecked(page))
2520+ afs_dir_check_page(dir,page);
2521+ if (PageError(page))
2522+ goto fail;
2523+ }
2524+ return page;
2525+
2526+ fail:
2527+ afs_dir_put_page(page);
2528+ return ERR_PTR(-EIO);
2529+} /* end afs_dir_get_page() */
2530+
2531+/*****************************************************************************/
2532+/*
2533+ * open an AFS directory file
2534+ */
2535+static int afs_dir_open(struct inode *inode, struct file *file)
2536+{
2537+ _enter("{%lu}",inode->i_ino);
2538+
2539+ if (sizeof(afs_dir_block_t) != 2048) BUG();
2540+ if (sizeof(afs_dirent_t) != 32) BUG();
2541+
2542+ if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED)
2543+ return -ENOENT;
2544+
2545+ _leave(" = 0");
2546+ return 0;
2547+
2548+} /* end afs_dir_open() */
2549+
2550+/*****************************************************************************/
2551+/*
2552+ * deal with one block in an AFS directory
2553+ */
2554+static int afs_dir_iterate_block(unsigned *fpos,
2555+ afs_dir_block_t *block,
2556+ unsigned blkoff,
2557+ void *cookie,
2558+ filldir_t filldir)
2559+{
2560+ afs_dirent_t *dire;
2561+ unsigned offset, next, curr;
2562+ size_t nlen;
2563+ int tmp, ret;
2564+
2565+ _enter("%u,%x,%p,,",*fpos,blkoff,block);
2566+
2567+ curr = (*fpos - blkoff) / sizeof(afs_dirent_t);
2568+
2569+ /* walk through the block, an entry at a time */
2570+ for (offset = AFS_DIRENT_PER_BLOCK - block->pagehdr.nentries;
2571+ offset < AFS_DIRENT_PER_BLOCK;
2572+ offset = next
2573+ ) {
2574+ next = offset + 1;
2575+
2576+ /* skip entries marked unused in the bitmap */
2577+ if (!(block->pagehdr.bitmap[offset/8] & (1 << (offset % 8)))) {
2578+ _debug("ENT[%u.%u]: unused\n",blkoff/sizeof(afs_dir_block_t),offset);
2579+ if (offset>=curr)
2580+ *fpos = blkoff + next * sizeof(afs_dirent_t);
2581+ continue;
2582+ }
2583+
2584+ /* got a valid entry */
2585+ dire = &block->dirents[offset];
2586+ nlen = strnlen(dire->name,sizeof(*block) - offset*sizeof(afs_dirent_t));
2587+
2588+ _debug("ENT[%u.%u]: %s %u \"%.*s\"\n",
2589+ blkoff/sizeof(afs_dir_block_t),offset,
2590+ offset<curr ? "skip" : "fill",
2591+ nlen,nlen,dire->name);
2592+
2593+ /* work out where the next possible entry is */
2594+ for (tmp=nlen; tmp>15; tmp-=sizeof(afs_dirent_t)) {
2595+ if (next>=AFS_DIRENT_PER_BLOCK) {
2596+ _debug("ENT[%u.%u]:"
2597+ " %u travelled beyond end dir block (len %u/%u)\n",
2598+ blkoff/sizeof(afs_dir_block_t),offset,next,tmp,nlen);
2599+ return -EIO;
2600+ }
2601+ if (!(block->pagehdr.bitmap[next/8] & (1 << (next % 8)))) {
2602+ _debug("ENT[%u.%u]: %u unmarked extension (len %u/%u)\n",
2603+ blkoff/sizeof(afs_dir_block_t),offset,next,tmp,nlen);
2604+ return -EIO;
2605+ }
2606+
2607+ _debug("ENT[%u.%u]: ext %u/%u\n",
2608+ blkoff/sizeof(afs_dir_block_t),next,tmp,nlen);
2609+ next++;
2610+ }
2611+
2612+ /* skip if starts before the current position */
2613+ if (offset<curr)
2614+ continue;
2615+
2616+ /* found the next entry */
2617+ ret = filldir(cookie,
2618+ dire->name,
2619+ nlen,
2620+ blkoff + offset * sizeof(afs_dirent_t),
2621+ ntohl(dire->vnode),
2622+ filldir==afs_dir_lookup_filldir ? dire->unique : DT_UNKNOWN);
2623+ if (ret<0) {
2624+ _leave(" = 0 [full]");
2625+ return 0;
2626+ }
2627+
2628+ *fpos = blkoff + next * sizeof(afs_dirent_t);
2629+ }
2630+
2631+ _leave(" = 1 [more]");
2632+ return 1;
2633+} /* end afs_dir_iterate_block() */
2634+
2635+/*****************************************************************************/
2636+/*
2637+ * read an AFS directory
2638+ */
2639+static int afs_dir_iterate(struct inode *dir, unsigned *fpos, void *cookie, filldir_t filldir)
2640+{
2641+ afs_dir_block_t *dblock;
2642+ afs_dir_page_t *dbuf;
2643+ struct page *page;
2644+ unsigned blkoff, limit;
2645+ int ret;
2646+
2647+ _enter("{%lu},%u,,",dir->i_ino,*fpos);
2648+
2649+ if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {
2650+ _leave(" = -ESTALE");
2651+ return -ESTALE;
2652+ }
2653+
2654+ /* round the file position up to the next entry boundary */
2655+ *fpos += sizeof(afs_dirent_t) - 1;
2656+ *fpos &= ~(sizeof(afs_dirent_t) - 1);
2657+
2658+ /* walk through the blocks in sequence */
2659+ ret = 0;
2660+ while (*fpos < dir->i_size) {
2661+ blkoff = *fpos & ~(sizeof(afs_dir_block_t) - 1);
2662+
2663+ /* fetch the appropriate page from the directory */
2664+ page = afs_dir_get_page(dir,blkoff/PAGE_SIZE);
2665+ if (IS_ERR(page)) {
2666+ ret = PTR_ERR(page);
2667+ break;
2668+ }
2669+
2670+ limit = blkoff & ~(PAGE_SIZE-1);
2671+
2672+ dbuf = page_address(page);
2673+
2674+ /* deal with the individual blocks stashed on this page */
2675+ do {
2676+ dblock = &dbuf->blocks[(blkoff % PAGE_SIZE) / sizeof(afs_dir_block_t)];
2677+ ret = afs_dir_iterate_block(fpos,dblock,blkoff,cookie,filldir);
2678+ if (ret!=1) {
2679+ afs_dir_put_page(page);
2680+ goto out;
2681+ }
2682+
2683+ blkoff += sizeof(afs_dir_block_t);
2684+
2685+ } while (*fpos < dir->i_size && blkoff < limit);
2686+
2687+ afs_dir_put_page(page);
2688+ ret = 0;
2689+ }
2690+
2691+ out:
2692+ _leave(" = %d",ret);
2693+ return ret;
2694+} /* end afs_dir_iterate() */
2695+
2696+/*****************************************************************************/
2697+/*
2698+ * read an AFS directory
2699+ */
2700+static int afs_dir_readdir(struct file *file, void *cookie, filldir_t filldir)
2701+{
2702+ unsigned fpos;
2703+ int ret;
2704+
2705+ _enter("{%Ld,{%lu}}",file->f_pos,file->f_dentry->d_inode->i_ino);
2706+
2707+ fpos = file->f_pos;
2708+ ret = afs_dir_iterate(file->f_dentry->d_inode,&fpos,cookie,filldir);
2709+ file->f_pos = fpos;
2710+
2711+ _leave(" = %d",ret);
2712+ return ret;
2713+} /* end afs_dir_readdir() */
2714+
2715+/*****************************************************************************/
2716+/*
2717+ * search the directory for a name
2718+ * - if afs_dir_iterate_block() spots this function, it'll pass the FID uniquifier through dtype
2719+ */
2720+static int afs_dir_lookup_filldir(void *_cookie, const char *name, int nlen, loff_t fpos,
2721+ ino_t ino, unsigned dtype)
2722+{
2723+ struct afs_dir_lookup_cookie *cookie = _cookie;
2724+
2725+ _enter("{%s,%u},%s,%u,,%lu,%u",cookie->name,cookie->nlen,name,nlen,ino,ntohl(dtype));
2726+
2727+ if (cookie->nlen != nlen || memcmp(cookie->name,name,nlen)!=0) {
2728+ _leave(" = 0 [no]");
2729+ return 0;
2730+ }
2731+
2732+ cookie->fid.vnode = ino;
2733+ cookie->fid.unique = ntohl(dtype);
2734+ cookie->found = 1;
2735+
2736+ _leave(" = -1 [found]");
2737+ return -1;
2738+} /* end afs_dir_lookup_filldir() */
2739+
2740+/*****************************************************************************/
2741+/*
2742+ * look up an entry in a directory
2743+ */
2744+static struct dentry *afs_dir_lookup(struct inode *dir, struct dentry *dentry)
2745+{
2746+ struct afs_dir_lookup_cookie cookie;
2747+ struct afs_super_info *as;
2748+ struct inode *inode;
2749+ afs_vnode_t *vnode;
2750+ unsigned fpos;
2751+ int ret;
2752+
2753+ _enter("{%lu},{%s}",dir->i_ino,dentry->d_name.name);
2754+
2755+ /* insanity checks first */
2756+ if (sizeof(afs_dir_block_t) != 2048) BUG();
2757+ if (sizeof(afs_dirent_t) != 32) BUG();
2758+
2759+ if (dentry->d_name.len > 255) {
2760+ _leave(" = -ENAMETOOLONG");
2761+ return ERR_PTR(-ENAMETOOLONG);
2762+ }
2763+
2764+ vnode = AFS_FS_I(dir);
2765+ if (vnode->flags & AFS_VNODE_DELETED) {
2766+ _leave(" = -ESTALE");
2767+ return ERR_PTR(-ESTALE);
2768+ }
2769+
2770+ as = dir->i_sb->u.generic_sbp;
2771+
2772+ /* search the directory */
2773+ cookie.name = dentry->d_name.name;
2774+ cookie.nlen = dentry->d_name.len;
2775+ cookie.fid.vid = as->volume->vid;
2776+ cookie.found = 0;
2777+
2778+ fpos = 0;
2779+ ret = afs_dir_iterate(dir,&fpos,&cookie,afs_dir_lookup_filldir);
2780+ if (ret<0) {
2781+ _leave(" = %d",ret);
2782+ return ERR_PTR(ret);
2783+ }
2784+
2785+ ret = -ENOENT;
2786+ if (!cookie.found) {
2787+ _leave(" = %d",ret);
2788+ return ERR_PTR(ret);
2789+ }
2790+
2791+ /* instantiate the dentry */
2792+ ret = afs_iget(dir->i_sb,&cookie.fid,&inode);
2793+ if (ret<0) {
2794+ _leave(" = %d",ret);
2795+ return ERR_PTR(ret);
2796+ }
2797+
2798+ dentry->d_op = &afs_fs_dentry_operations;
2799+ dentry->d_fsdata = (void*) (unsigned) vnode->status.version;
2800+
2801+ d_add(dentry,inode);
2802+ _leave(" = 0 { vn=%u u=%u } -> { ino=%lu v=%lu }",
2803+ cookie.fid.vnode,
2804+ cookie.fid.unique,
2805+ dentry->d_inode->i_ino,
2806+ dentry->d_inode->i_version);
2807+
2808+ return NULL;
2809+} /* end afs_dir_lookup() */
2810+
2811+/*****************************************************************************/
2812+/*
2813+ * check that a dentry lookup hit has found a valid entry
2814+ * - NOTE! the hit can be a negative hit too, so we can't assume we have an inode
2815+ * (derived from nfs_lookup_revalidate)
2816+ */
2817+static int afs_d_revalidate(struct dentry *dentry, int flags)
2818+{
2819+ struct afs_dir_lookup_cookie cookie;
2820+ struct dentry *parent;
2821+ struct inode *inode, *dir;
2822+ unsigned fpos;
2823+ int ret;
2824+
2825+ _enter("%s,%x",dentry->d_name.name,flags);
2826+
2827+ /* lock down the parent dentry so we can peer at it */
2828+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
2829+ read_lock(&dparent_lock);
2830+ parent = dget(dentry->d_parent);
2831+ read_unlock(&dparent_lock);
2832+#else
2833+ lock_kernel();
2834+ parent = dget(dentry->d_parent);
2835+ unlock_kernel();
2836+#endif
2837+
2838+ dir = parent->d_inode;
2839+ inode = dentry->d_inode;
2840+
2841+ /* handle a negative inode */
2842+ if (!inode)
2843+ goto out_bad;
2844+
2845+ /* handle a bad inode */
2846+ if (is_bad_inode(inode)) {
2847+ printk("kAFS: afs_d_revalidate: %s/%s has bad inode\n",
2848+ dentry->d_parent->d_name.name,dentry->d_name.name);
2849+ goto out_bad;
2850+ }
2851+
2852+ /* force a full look up if the parent directory changed since last the server was consulted
2853+ * - otherwise this inode must still exist, even if the inode details themselves have
2854+ * changed
2855+ */
2856+ if (AFS_FS_I(dir)->flags & AFS_VNODE_CHANGED)
2857+ afs_vnode_fetch_status(AFS_FS_I(dir));
2858+
2859+ if (AFS_FS_I(dir)->flags & AFS_VNODE_DELETED) {
2860+ _debug("%s: parent dir deleted",dentry->d_name.name);
2861+ goto out_bad;
2862+ }
2863+
2864+ if (AFS_FS_I(inode)->flags & AFS_VNODE_DELETED) {
2865+ _debug("%s: file already deleted",dentry->d_name.name);
2866+ goto out_bad;
2867+ }
2868+
2869+ if ((unsigned)dentry->d_fsdata != (unsigned)AFS_FS_I(dir)->status.version) {
2870+ _debug("%s: parent changed %u -> %u",
2871+ dentry->d_name.name,
2872+ (unsigned)dentry->d_fsdata,
2873+ (unsigned)AFS_FS_I(dir)->status.version);
2874+
2875+ /* search the directory for this vnode */
2876+ cookie.name = dentry->d_name.name;
2877+ cookie.nlen = dentry->d_name.len;
2878+ cookie.fid.vid = AFS_FS_I(inode)->volume->vid;
2879+ cookie.found = 0;
2880+
2881+ fpos = 0;
2882+ ret = afs_dir_iterate(dir,&fpos,&cookie,afs_dir_lookup_filldir);
2883+ if (ret<0) {
2884+ _debug("failed to iterate dir %s: %d",parent->d_name.name,ret);
2885+ goto out_bad;
2886+ }
2887+
2888+ if (!cookie.found) {
2889+ _debug("%s: dirent not found",dentry->d_name.name);
2890+ goto not_found;
2891+ }
2892+
2893+ /* if the vnode ID has changed, then the dirent points to a different file */
2894+ if (cookie.fid.vnode!=AFS_FS_I(inode)->fid.vnode) {
2895+ _debug("%s: dirent changed",dentry->d_name.name);
2896+ goto not_found;
2897+ }
2898+
2899+ /* if the vnode ID uniqifier has changed, then the file has been deleted */
2900+ if (cookie.fid.unique!=AFS_FS_I(inode)->fid.unique) {
2901+ _debug("%s: file deleted (uq %u -> %u I:%lu)",
2902+ dentry->d_name.name,
2903+ cookie.fid.unique,
2904+ AFS_FS_I(inode)->fid.unique,
2905+ inode->i_version);
2906+ spin_lock(&AFS_FS_I(inode)->lock);
2907+ AFS_FS_I(inode)->flags |= AFS_VNODE_DELETED;
2908+ spin_unlock(&AFS_FS_I(inode)->lock);
2909+ invalidate_inode_pages(inode);
2910+ goto out_bad;
2911+ }
2912+
2913+ dentry->d_fsdata = (void*) (unsigned) AFS_FS_I(dir)->status.version;
2914+ }
2915+
2916+ out_valid:
2917+ dput(parent);
2918+ _leave(" = 1 [valid]");
2919+ return 1;
2920+
2921+ /* the dirent, if it exists, now points to a different vnode */
2922+ not_found:
2923+ dentry->d_flags |= DCACHE_NFSFS_RENAMED;
2924+
2925+ out_bad:
2926+ if (inode) {
2927+ /* don't unhash if we have submounts */
2928+ if (have_submounts(dentry))
2929+ goto out_valid;
2930+ }
2931+
2932+ shrink_dcache_parent(dentry);
2933+
2934+ _debug("dropping dentry %s/%s",dentry->d_parent->d_name.name,dentry->d_name.name);
2935+ d_drop(dentry);
2936+
2937+ dput(parent);
2938+
2939+ _leave(" = 0 [bad]");
2940+ return 0;
2941+} /* end afs_d_revalidate() */
2942+
2943+/*****************************************************************************/
2944+/*
2945+ * allow the VFS to enquire as to whether a dentry should be unhashed (mustn't sleep)
2946+ * - called from dput() when d_count is going to 0.
2947+ * - return 1 to request dentry be unhashed, 0 otherwise
2948+ */
2949+static int afs_d_delete(struct dentry *dentry)
2950+{
2951+ _enter("%s",dentry->d_name.name);
2952+
2953+ if (dentry->d_flags & DCACHE_NFSFS_RENAMED)
2954+ return 1;
2955+
2956+ if (dentry->d_inode) {
2957+ if (AFS_FS_I(dentry->d_inode)->flags & AFS_VNODE_DELETED)
2958+ goto zap;
2959+ }
2960+
2961+ _leave(" = 0 [keep]");
2962+ return 0;
2963+
2964+ zap:
2965+ _leave(" = 1 [zap]");
2966+ return 1;
2967+} /* end afs_d_delete() */
2968diff -urNp linux-5240/fs/afs/errors.h linux-5250/fs/afs/errors.h
2969--- linux-5240/fs/afs/errors.h 1970-01-01 01:00:00.000000000 +0100
2970+++ linux-5250/fs/afs/errors.h
2971@@ -0,0 +1,34 @@
2972+/* errors.h: AFS abort/error codes
2973+ *
2974+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
2975+ * Written by David Howells (dhowells@redhat.com)
2976+ *
2977+ * This program is free software; you can redistribute it and/or
2978+ * modify it under the terms of the GNU General Public License
2979+ * as published by the Free Software Foundation; either version
2980+ * 2 of the License, or (at your option) any later version.
2981+ */
2982+
2983+#ifndef _H_DB712916_5113_11D6_9A6D_0002B3163499
2984+#define _H_DB712916_5113_11D6_9A6D_0002B3163499
2985+
2986+#include "types.h"
2987+
2988+/* file server abort codes */
2989+typedef enum {
2990+ VSALVAGE = 101, /* volume needs salvaging */
2991+ VNOVNODE = 102, /* no such file/dir (vnode) */
2992+ VNOVOL = 103, /* no such volume or volume unavailable */
2993+ VVOLEXISTS = 104, /* volume name already exists */
2994+ VNOSERVICE = 105, /* volume not currently in service */
2995+ VOFFLINE = 106, /* volume is currently offline (more info available [VVL-spec]) */
2996+ VONLINE = 107, /* volume is already online */
2997+ VDISKFULL = 108, /* disk partition is full */
2998+ VOVERQUOTA = 109, /* volume's maximum quota exceeded */
2999+ VBUSY = 110, /* volume is temporarily unavailable */
3000+ VMOVED = 111, /* volume moved to new server - ask this FS where */
3001+} afs_rxfs_abort_t;
3002+
3003+extern int afs_abort_to_error(int abortcode);
3004+
3005+#endif /* _H_DB712916_5113_11D6_9A6D_0002B3163499 */
3006diff -urNp linux-5240/fs/afs/file.c linux-5250/fs/afs/file.c
3007--- linux-5240/fs/afs/file.c 1970-01-01 01:00:00.000000000 +0100
3008+++ linux-5250/fs/afs/file.c
3009@@ -0,0 +1,143 @@
3010+/* file.c: AFS filesystem file handling
3011+ *
3012+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
3013+ * Written by David Howells (dhowells@redhat.com)
3014+ *
3015+ * This program is free software; you can redistribute it and/or
3016+ * modify it under the terms of the GNU General Public License
3017+ * as published by the Free Software Foundation; either version
3018+ * 2 of the License, or (at your option) any later version.
3019+ */
3020+
3021+#include <linux/kernel.h>
3022+#include <linux/module.h>
3023+#include <linux/init.h>
3024+#include <linux/sched.h>
3025+#include <linux/slab.h>
3026+#include <linux/fs.h>
3027+#include <linux/pagemap.h>
3028+#include "volume.h"
3029+#include "vnode.h"
3030+#include <rxrpc/call.h>
3031+#include "internal.h"
3032+
3033+//static int afs_file_open(struct inode *inode, struct file *file);
3034+//static int afs_file_release(struct inode *inode, struct file *file);
3035+
3036+static int afs_file_readpage(struct file *file, struct page *page);
3037+
3038+//static ssize_t afs_file_read(struct file *file, char *buf, size_t size, loff_t *off);
3039+
3040+static ssize_t afs_file_write(struct file *file, const char *buf, size_t size, loff_t *off);
3041+
3042+struct inode_operations afs_file_inode_operations = {
3043+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
3044+ getattr: afs_inode_getattr,
3045+#else
3046+ revalidate: afs_inode_revalidate,
3047+#endif
3048+};
3049+
3050+struct file_operations afs_file_file_operations = {
3051+// open: afs_file_open,
3052+// release: afs_file_release,
3053+ read: generic_file_read, //afs_file_read,
3054+ write: afs_file_write,
3055+ mmap: generic_file_mmap,
3056+// fsync: afs_file_fsync,
3057+};
3058+
3059+struct address_space_operations afs_fs_aops = {
3060+ readpage: afs_file_readpage,
3061+};
3062+
3063+/*****************************************************************************/
3064+/*
3065+ * AFS file read
3066+ */
3067+#if 0
3068+static ssize_t afs_file_read(struct file *file, char *buf, size_t size, loff_t *off)
3069+{
3070+ struct afs_inode_info *ai;
3071+
3072+ ai = AFS_FS_I(file->f_dentry->d_inode);
3073+ if (ai->flags & AFS_INODE_DELETED)
3074+ return -ESTALE;
3075+
3076+ return -EIO;
3077+} /* end afs_file_read() */
3078+#endif
3079+
3080+/*****************************************************************************/
3081+/*
3082+ * AFS file write
3083+ */
3084+static ssize_t afs_file_write(struct file *file, const char *buf, size_t size, loff_t *off)
3085+{
3086+ afs_vnode_t *vnode;
3087+
3088+ vnode = AFS_FS_I(file->f_dentry->d_inode);
3089+ if (vnode->flags & AFS_VNODE_DELETED)
3090+ return -ESTALE;
3091+
3092+ return -EIO;
3093+} /* end afs_file_write() */
3094+
3095+/*****************************************************************************/
3096+/*
3097+ * AFS read page from file (or symlink)
3098+ */
3099+static int afs_file_readpage(struct file *file, struct page *page)
3100+{
3101+ struct afs_rxfs_fetch_descriptor desc;
3102+ struct inode *inode;
3103+ afs_vnode_t *vnode;
3104+ int ret;
3105+
3106+ inode = page->mapping->host;
3107+
3108+ _enter("{%lu},{%lu}",inode->i_ino,page->index);
3109+
3110+ vnode = AFS_FS_I(inode);
3111+
3112+ if (!PageLocked(page))
3113+ PAGE_BUG(page);
3114+
3115+ ret = -ESTALE;
3116+ if (vnode->flags & AFS_VNODE_DELETED)
3117+ goto error;
3118+
3119+ /* work out how much to get and from where */
3120+ desc.fid = vnode->fid;
3121+ desc.offset = page->index << PAGE_CACHE_SHIFT;
3122+ desc.size = min((size_t)(inode->i_size - desc.offset),(size_t)PAGE_SIZE);
3123+ desc.buffer = kmap(page);
3124+
3125+ clear_page(desc.buffer);
3126+
3127+ /* read the contents of the file from the server into the page */
3128+ ret = afs_vnode_fetch_data(vnode,&desc);
3129+ kunmap(page);
3130+ if (ret<0) {
3131+ if (ret==-ENOENT) {
3132+ _debug("got NOENT from server - marking file deleted and stale");
3133+ vnode->flags |= AFS_VNODE_DELETED;
3134+ ret = -ESTALE;
3135+ }
3136+ goto error;
3137+ }
3138+
3139+ SetPageUptodate(page);
3140+ unlock_page(page);
3141+
3142+ _leave(" = 0");
3143+ return 0;
3144+
3145+ error:
3146+ SetPageError(page);
3147+ unlock_page(page);
3148+
3149+ _leave(" = %d",ret);
3150+ return ret;
3151+
3152+} /* end afs_file_readpage() */
3153diff -urNp linux-5240/fs/afs/fsclient.c linux-5250/fs/afs/fsclient.c
3154--- linux-5240/fs/afs/fsclient.c 1970-01-01 01:00:00.000000000 +0100
3155+++ linux-5250/fs/afs/fsclient.c
3156@@ -0,0 +1,816 @@
3157+/* fsclient.c: AFS File Server client stubs
3158+ *
3159+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
3160+ * Written by David Howells (dhowells@redhat.com)
3161+ *
3162+ * This program is free software; you can redistribute it and/or
3163+ * modify it under the terms of the GNU General Public License
3164+ * as published by the Free Software Foundation; either version
3165+ * 2 of the License, or (at your option) any later version.
3166+ */
3167+
3168+#include <linux/init.h>
3169+#include <linux/sched.h>
3170+#include <rxrpc/rxrpc.h>
3171+#include <rxrpc/transport.h>
3172+#include <rxrpc/connection.h>
3173+#include <rxrpc/call.h>
3174+#include "fsclient.h"
3175+#include "cmservice.h"
3176+#include "vnode.h"
3177+#include "server.h"
3178+#include "errors.h"
3179+#include "internal.h"
3180+
3181+#define FSFETCHSTATUS 132 /* AFS Fetch file status */
3182+#define FSFETCHDATA 130 /* AFS Fetch file data */
3183+#define FSGIVEUPCALLBACKS 147 /* AFS Discard server callback promises */
3184+#define FSGETVOLUMEINFO 148 /* AFS Get root volume information */
3185+#define FSGETROOTVOLUME 151 /* AFS Get root volume name */
3186+#define FSLOOKUP 161 /* AFS lookup file in directory */
3187+
3188+/*****************************************************************************/
3189+/*
3190+ * map afs abort codes to/from Linux error codes
3191+ * - called with call->lock held
3192+ */
3193+static void afs_rxfs_aemap(struct rxrpc_call *call)
3194+{
3195+ switch (call->app_err_state) {
3196+ case RXRPC_ESTATE_LOCAL_ABORT:
3197+ call->app_abort_code = -call->app_errno;
3198+ break;
3199+ case RXRPC_ESTATE_PEER_ABORT:
3200+ call->app_errno = afs_abort_to_error(call->app_abort_code);
3201+ break;
3202+ default:
3203+ break;
3204+ }
3205+} /* end afs_rxfs_aemap() */
3206+
3207+/*****************************************************************************/
3208+/*
3209+ * get the root volume name from a fileserver
3210+ * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
3211+ */
3212+#if 0
3213+int afs_rxfs_get_root_volume(afs_server_t *server, char *buf, size_t *buflen)
3214+{
3215+ DECLARE_WAITQUEUE(myself,current);
3216+
3217+ struct rxrpc_connection *conn;
3218+ struct rxrpc_call *call;
3219+ struct iovec piov[2];
3220+ size_t sent;
3221+ int ret;
3222+ u32 param[1];
3223+
3224+ kenter("%p,%p,%u",server,buf,*buflen);
3225+
3226+ /* get hold of the fileserver connection */
3227+ ret = afs_server_get_fsconn(server,&conn);
3228+ if (ret<0)
3229+ goto out;
3230+
3231+ /* create a call through that connection */
3232+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxfs_aemap,&call);
3233+ if (ret<0) {
3234+ printk("kAFS: Unable to create call: %d\n",ret);
3235+ goto out_put_conn;
3236+ }
3237+ call->app_opcode = FSGETROOTVOLUME;
3238+
3239+ /* we want to get event notifications from the call */
3240+ add_wait_queue(&call->waitq,&myself);
3241+
3242+ /* marshall the parameters */
3243+ param[0] = htonl(FSGETROOTVOLUME);
3244+
3245+ piov[0].iov_len = sizeof(param);
3246+ piov[0].iov_base = param;
3247+
3248+ /* send the parameters to the server */
3249+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3250+ if (ret<0)
3251+ goto abort;
3252+
3253+ /* wait for the reply to completely arrive */
3254+ for (;;) {
3255+ set_current_state(TASK_INTERRUPTIBLE);
3256+ if (call->app_call_state!=RXRPC_CSTATE_CLNT_RCV_REPLY ||
3257+ signal_pending(current))
3258+ break;
3259+ schedule();
3260+ }
3261+ set_current_state(TASK_RUNNING);
3262+
3263+ ret = -EINTR;
3264+ if (signal_pending(current))
3265+ goto abort;
3266+
3267+ switch (call->app_call_state) {
3268+ case RXRPC_CSTATE_ERROR:
3269+ ret = call->app_errno;
3270+ kdebug("Got Error: %d",ret);
3271+ goto out_unwait;
3272+
3273+ case RXRPC_CSTATE_CLNT_GOT_REPLY:
3274+ /* read the reply */
3275+ kdebug("Got Reply: qty=%d",call->app_ready_qty);
3276+
3277+ ret = -EBADMSG;
3278+ if (call->app_ready_qty <= 4)
3279+ goto abort;
3280+
3281+ ret = rxrpc_call_read_data(call,NULL,call->app_ready_qty,0);
3282+ if (ret<0)
3283+ goto abort;
3284+
3285+#if 0
3286+ /* unmarshall the reply */
3287+ bp = buffer;
3288+ for (loop=0; loop<65; loop++)
3289+ entry->name[loop] = ntohl(*bp++);
3290+ entry->name[64] = 0;
3291+
3292+ entry->type = ntohl(*bp++);
3293+ entry->num_servers = ntohl(*bp++);
3294+
3295+ for (loop=0; loop<8; loop++)
3296+ entry->servers[loop].addr.s_addr = *bp++;
3297+
3298+ for (loop=0; loop<8; loop++)
3299+ entry->servers[loop].partition = ntohl(*bp++);
3300+
3301+ for (loop=0; loop<8; loop++)
3302+ entry->servers[loop].flags = ntohl(*bp++);
3303+
3304+ for (loop=0; loop<3; loop++)
3305+ entry->volume_ids[loop] = ntohl(*bp++);
3306+
3307+ entry->clone_id = ntohl(*bp++);
3308+ entry->flags = ntohl(*bp);
3309+#endif
3310+
3311+ /* success */
3312+ ret = 0;
3313+ goto out_unwait;
3314+
3315+ default:
3316+ BUG();
3317+ }
3318+
3319+ abort:
3320+ set_current_state(TASK_UNINTERRUPTIBLE);
3321+ rxrpc_call_abort(call,ret);
3322+ schedule();
3323+ out_unwait:
3324+ set_current_state(TASK_RUNNING);
3325+ remove_wait_queue(&call->waitq,&myself);
3326+ rxrpc_put_call(call);
3327+ out_put_conn:
3328+ afs_server_release_fsconn(server,conn);
3329+ out:
3330+ kleave("");
3331+ return ret;
3332+} /* end afs_rxfs_get_root_volume() */
3333+#endif
3334+
3335+/*****************************************************************************/
3336+/*
3337+ * get information about a volume
3338+ */
3339+#if 0
3340+int afs_rxfs_get_volume_info(afs_server_t *server,
3341+ const char *name,
3342+ afs_volume_info_t *vinfo)
3343+{
3344+ DECLARE_WAITQUEUE(myself,current);
3345+
3346+ struct rxrpc_connection *conn;
3347+ struct rxrpc_call *call;
3348+ struct iovec piov[3];
3349+ size_t sent;
3350+ int ret;
3351+ u32 param[2], *bp, zero;
3352+
3353+ _enter("%p,%s,%p",server,name,vinfo);
3354+
3355+ /* get hold of the fileserver connection */
3356+ ret = afs_server_get_fsconn(server,&conn);
3357+ if (ret<0)
3358+ goto out;
3359+
3360+ /* create a call through that connection */
3361+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxfs_aemap,&call);
3362+ if (ret<0) {
3363+ printk("kAFS: Unable to create call: %d\n",ret);
3364+ goto out_put_conn;
3365+ }
3366+ call->app_opcode = FSGETVOLUMEINFO;
3367+
3368+ /* we want to get event notifications from the call */
3369+ add_wait_queue(&call->waitq,&myself);
3370+
3371+ /* marshall the parameters */
3372+ piov[1].iov_len = strlen(name);
3373+ piov[1].iov_base = (char*)name;
3374+
3375+ zero = 0;
3376+ piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
3377+ piov[2].iov_base = &zero;
3378+
3379+ param[0] = htonl(FSGETVOLUMEINFO);
3380+ param[1] = htonl(piov[1].iov_len);
3381+
3382+ piov[0].iov_len = sizeof(param);
3383+ piov[0].iov_base = param;
3384+
3385+ /* send the parameters to the server */
3386+ ret = rxrpc_call_write_data(call,3,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3387+ if (ret<0)
3388+ goto abort;
3389+
3390+ /* wait for the reply to completely arrive */
3391+ bp = rxrpc_call_alloc_scratch(call,64);
3392+
3393+ ret = rxrpc_call_read_data(call,bp,64,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
3394+ if (ret<0) {
3395+ if (ret==-ECONNABORTED) {
3396+ ret = call->app_errno;
3397+ goto out_unwait;
3398+ }
3399+ goto abort;
3400+ }
3401+
3402+ /* unmarshall the reply */
3403+ vinfo->vid = ntohl(*bp++);
3404+ vinfo->type = ntohl(*bp++);
3405+
3406+ vinfo->type_vids[0] = ntohl(*bp++);
3407+ vinfo->type_vids[1] = ntohl(*bp++);
3408+ vinfo->type_vids[2] = ntohl(*bp++);
3409+ vinfo->type_vids[3] = ntohl(*bp++);
3410+ vinfo->type_vids[4] = ntohl(*bp++);
3411+
3412+ vinfo->nservers = ntohl(*bp++);
3413+ vinfo->servers[0].addr.s_addr = *bp++;
3414+ vinfo->servers[1].addr.s_addr = *bp++;
3415+ vinfo->servers[2].addr.s_addr = *bp++;
3416+ vinfo->servers[3].addr.s_addr = *bp++;
3417+ vinfo->servers[4].addr.s_addr = *bp++;
3418+ vinfo->servers[5].addr.s_addr = *bp++;
3419+ vinfo->servers[6].addr.s_addr = *bp++;
3420+ vinfo->servers[7].addr.s_addr = *bp++;
3421+
3422+ ret = -EBADMSG;
3423+ if (vinfo->nservers>8)
3424+ goto abort;
3425+
3426+ /* success */
3427+ ret = 0;
3428+
3429+ out_unwait:
3430+ set_current_state(TASK_RUNNING);
3431+ remove_wait_queue(&call->waitq,&myself);
3432+ rxrpc_put_call(call);
3433+ out_put_conn:
3434+ afs_server_release_fsconn(server,conn);
3435+ out:
3436+ _leave("");
3437+ return ret;
3438+
3439+ abort:
3440+ set_current_state(TASK_UNINTERRUPTIBLE);
3441+ rxrpc_call_abort(call,ret);
3442+ schedule();
3443+ goto out_unwait;
3444+
3445+} /* end afs_rxfs_get_volume_info() */
3446+#endif
3447+
3448+/*****************************************************************************/
3449+/*
3450+ * fetch the status information for a file
3451+ */
3452+int afs_rxfs_fetch_file_status(afs_server_t *server,
3453+ afs_vnode_t *vnode,
3454+ afs_volsync_t *volsync)
3455+{
3456+ DECLARE_WAITQUEUE(myself,current);
3457+
3458+ struct afs_server_callslot callslot;
3459+ struct rxrpc_call *call;
3460+ struct iovec piov[1];
3461+ size_t sent;
3462+ int ret;
3463+ u32 *bp;
3464+
3465+ _enter("%p,{%u,%u,%u}",server,vnode->fid.vid,vnode->fid.vnode,vnode->fid.unique);
3466+
3467+ /* get hold of the fileserver connection */
3468+ ret = afs_server_request_callslot(server,&callslot);
3469+ if (ret<0)
3470+ goto out;
3471+
3472+ /* create a call through that connection */
3473+ ret = rxrpc_create_call(callslot.conn,NULL,NULL,afs_rxfs_aemap,&call);
3474+ if (ret<0) {
3475+ printk("kAFS: Unable to create call: %d\n",ret);
3476+ goto out_put_conn;
3477+ }
3478+ call->app_opcode = FSFETCHSTATUS;
3479+
3480+ /* we want to get event notifications from the call */
3481+ add_wait_queue(&call->waitq,&myself);
3482+
3483+ /* marshall the parameters */
3484+ bp = rxrpc_call_alloc_scratch(call,16);
3485+ bp[0] = htonl(FSFETCHSTATUS);
3486+ bp[1] = htonl(vnode->fid.vid);
3487+ bp[2] = htonl(vnode->fid.vnode);
3488+ bp[3] = htonl(vnode->fid.unique);
3489+
3490+ piov[0].iov_len = 16;
3491+ piov[0].iov_base = bp;
3492+
3493+ /* send the parameters to the server */
3494+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3495+ if (ret<0)
3496+ goto abort;
3497+
3498+ /* wait for the reply to completely arrive */
3499+ bp = rxrpc_call_alloc_scratch(call,120);
3500+
3501+ ret = rxrpc_call_read_data(call,bp,120,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
3502+ if (ret<0) {
3503+ if (ret==-ECONNABORTED) {
3504+ ret = call->app_errno;
3505+ goto out_unwait;
3506+ }
3507+ goto abort;
3508+ }
3509+
3510+ /* unmarshall the reply */
3511+ vnode->status.if_version = ntohl(*bp++);
3512+ vnode->status.type = ntohl(*bp++);
3513+ vnode->status.nlink = ntohl(*bp++);
3514+ vnode->status.size = ntohl(*bp++);
3515+ vnode->status.version = ntohl(*bp++);
3516+ vnode->status.author = ntohl(*bp++);
3517+ vnode->status.owner = ntohl(*bp++);
3518+ vnode->status.caller_access = ntohl(*bp++);
3519+ vnode->status.anon_access = ntohl(*bp++);
3520+ vnode->status.mode = ntohl(*bp++);
3521+ vnode->status.parent.vid = vnode->fid.vid;
3522+ vnode->status.parent.vnode = ntohl(*bp++);
3523+ vnode->status.parent.unique = ntohl(*bp++);
3524+ bp++; /* seg size */
3525+ vnode->status.mtime_client = ntohl(*bp++);
3526+ vnode->status.mtime_server = ntohl(*bp++);
3527+ bp++; /* group */
3528+ bp++; /* sync counter */
3529+ vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
3530+ bp++; /* spare2 */
3531+ bp++; /* spare3 */
3532+ bp++; /* spare4 */
3533+
3534+ vnode->cb_version = ntohl(*bp++);
3535+ vnode->cb_expiry = ntohl(*bp++);
3536+ vnode->cb_type = ntohl(*bp++);
3537+
3538+ if (volsync) {
3539+ volsync->creation = ntohl(*bp++);
3540+ bp++; /* spare2 */
3541+ bp++; /* spare3 */
3542+ bp++; /* spare4 */
3543+ bp++; /* spare5 */
3544+ bp++; /* spare6 */
3545+ }
3546+
3547+ /* success */
3548+ ret = 0;
3549+
3550+ out_unwait:
3551+ set_current_state(TASK_RUNNING);
3552+ remove_wait_queue(&call->waitq,&myself);
3553+ rxrpc_put_call(call);
3554+ out_put_conn:
3555+ afs_server_release_callslot(server,&callslot);
3556+ out:
3557+ _leave("");
3558+ return ret;
3559+
3560+ abort:
3561+ set_current_state(TASK_UNINTERRUPTIBLE);
3562+ rxrpc_call_abort(call,ret);
3563+ schedule();
3564+ goto out_unwait;
3565+} /* end afs_rxfs_fetch_file_status() */
3566+
3567+/*****************************************************************************/
3568+/*
3569+ * fetch the contents of a file or directory
3570+ */
3571+int afs_rxfs_fetch_file_data(afs_server_t *server,
3572+ afs_vnode_t *vnode,
3573+ struct afs_rxfs_fetch_descriptor *desc,
3574+ afs_volsync_t *volsync)
3575+{
3576+ DECLARE_WAITQUEUE(myself,current);
3577+
3578+ struct afs_server_callslot callslot;
3579+ struct rxrpc_call *call;
3580+ struct iovec piov[1];
3581+ size_t sent;
3582+ int ret;
3583+ u32 *bp;
3584+
3585+ _enter("%p,{fid={%u,%u,%u},sz=%u,of=%lu}",
3586+ server,
3587+ desc->fid.vid,
3588+ desc->fid.vnode,
3589+ desc->fid.unique,
3590+ desc->size,
3591+ desc->offset);
3592+
3593+ /* get hold of the fileserver connection */
3594+ ret = afs_server_request_callslot(server,&callslot);
3595+ if (ret<0)
3596+ goto out;
3597+
3598+ /* create a call through that connection */
3599+ ret = rxrpc_create_call(callslot.conn,NULL,NULL,afs_rxfs_aemap,&call);
3600+ if (ret<0) {
3601+ printk("kAFS: Unable to create call: %d\n",ret);
3602+ goto out_put_conn;
3603+ }
3604+ call->app_opcode = FSFETCHDATA;
3605+
3606+ /* we want to get event notifications from the call */
3607+ add_wait_queue(&call->waitq,&myself);
3608+
3609+ /* marshall the parameters */
3610+ bp = rxrpc_call_alloc_scratch(call,24);
3611+ bp[0] = htonl(FSFETCHDATA);
3612+ bp[1] = htonl(desc->fid.vid);
3613+ bp[2] = htonl(desc->fid.vnode);
3614+ bp[3] = htonl(desc->fid.unique);
3615+ bp[4] = htonl(desc->offset);
3616+ bp[5] = htonl(desc->size);
3617+
3618+ piov[0].iov_len = 24;
3619+ piov[0].iov_base = bp;
3620+
3621+ /* send the parameters to the server */
3622+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3623+ if (ret<0)
3624+ goto abort;
3625+
3626+ /* wait for the data count to arrive */
3627+ ret = rxrpc_call_read_data(call,bp,4,RXRPC_CALL_READ_BLOCK);
3628+ if (ret<0)
3629+ goto read_failed;
3630+
3631+ desc->actual = ntohl(bp[0]);
3632+ if (desc->actual!=desc->size) {
3633+ ret = -EBADMSG;
3634+ goto abort;
3635+ }
3636+
3637+ /* call the app to read the actual data */
3638+ rxrpc_call_reset_scratch(call);
3639+
3640+ ret = rxrpc_call_read_data(call,desc->buffer,desc->actual,RXRPC_CALL_READ_BLOCK);
3641+ if (ret<0)
3642+ goto read_failed;
3643+
3644+ /* wait for the rest of the reply to completely arrive */
3645+ rxrpc_call_reset_scratch(call);
3646+ bp = rxrpc_call_alloc_scratch(call,120);
3647+
3648+ ret = rxrpc_call_read_data(call,bp,120,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
3649+ if (ret<0)
3650+ goto read_failed;
3651+
3652+ /* unmarshall the reply */
3653+ vnode->status.if_version = ntohl(*bp++);
3654+ vnode->status.type = ntohl(*bp++);
3655+ vnode->status.nlink = ntohl(*bp++);
3656+ vnode->status.size = ntohl(*bp++);
3657+ vnode->status.version = ntohl(*bp++);
3658+ vnode->status.author = ntohl(*bp++);
3659+ vnode->status.owner = ntohl(*bp++);
3660+ vnode->status.caller_access = ntohl(*bp++);
3661+ vnode->status.anon_access = ntohl(*bp++);
3662+ vnode->status.mode = ntohl(*bp++);
3663+ vnode->status.parent.vid = desc->fid.vid;
3664+ vnode->status.parent.vnode = ntohl(*bp++);
3665+ vnode->status.parent.unique = ntohl(*bp++);
3666+ bp++; /* seg size */
3667+ vnode->status.mtime_client = ntohl(*bp++);
3668+ vnode->status.mtime_server = ntohl(*bp++);
3669+ bp++; /* group */
3670+ bp++; /* sync counter */
3671+ vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
3672+ bp++; /* spare2 */
3673+ bp++; /* spare3 */
3674+ bp++; /* spare4 */
3675+
3676+ vnode->cb_version = ntohl(*bp++);
3677+ vnode->cb_expiry = ntohl(*bp++);
3678+ vnode->cb_type = ntohl(*bp++);
3679+
3680+ if (volsync) {
3681+ volsync->creation = ntohl(*bp++);
3682+ bp++; /* spare2 */
3683+ bp++; /* spare3 */
3684+ bp++; /* spare4 */
3685+ bp++; /* spare5 */
3686+ bp++; /* spare6 */
3687+ }
3688+
3689+ /* success */
3690+ ret = 0;
3691+
3692+ out_unwait:
3693+ set_current_state(TASK_RUNNING);
3694+ remove_wait_queue(&call->waitq,&myself);
3695+ rxrpc_put_call(call);
3696+ out_put_conn:
3697+ afs_server_release_callslot(server,&callslot);
3698+ out:
3699+ _leave(" = %d",ret);
3700+ return ret;
3701+
3702+ read_failed:
3703+ if (ret==-ECONNABORTED) {
3704+ ret = call->app_errno;
3705+ goto out_unwait;
3706+ }
3707+
3708+ abort:
3709+ set_current_state(TASK_UNINTERRUPTIBLE);
3710+ rxrpc_call_abort(call,ret);
3711+ schedule();
3712+ goto out_unwait;
3713+
3714+} /* end afs_rxfs_fetch_file_data() */
3715+
3716+/*****************************************************************************/
3717+/*
3718+ * ask the AFS fileserver to discard a callback request on a file
3719+ */
3720+int afs_rxfs_give_up_callback(afs_server_t *server, afs_vnode_t *vnode)
3721+{
3722+ DECLARE_WAITQUEUE(myself,current);
3723+
3724+ struct afs_server_callslot callslot;
3725+ struct rxrpc_call *call;
3726+ struct iovec piov[1];
3727+ size_t sent;
3728+ int ret;
3729+ u32 *bp;
3730+
3731+ _enter("%p,{%u,%u,%u}",server,vnode->fid.vid,vnode->fid.vnode,vnode->fid.unique);
3732+
3733+ /* get hold of the fileserver connection */
3734+ ret = afs_server_request_callslot(server,&callslot);
3735+ if (ret<0)
3736+ goto out;
3737+
3738+ /* create a call through that connection */
3739+ ret = rxrpc_create_call(callslot.conn,NULL,NULL,afs_rxfs_aemap,&call);
3740+ if (ret<0) {
3741+ printk("kAFS: Unable to create call: %d\n",ret);
3742+ goto out_put_conn;
3743+ }
3744+ call->app_opcode = FSGIVEUPCALLBACKS;
3745+
3746+ /* we want to get event notifications from the call */
3747+ add_wait_queue(&call->waitq,&myself);
3748+
3749+ /* marshall the parameters */
3750+ bp = rxrpc_call_alloc_scratch(call,(1+4+4)*4);
3751+
3752+ piov[0].iov_len = (1+4+4)*4;
3753+ piov[0].iov_base = bp;
3754+
3755+ *bp++ = htonl(FSGIVEUPCALLBACKS);
3756+ *bp++ = htonl(1);
3757+ *bp++ = htonl(vnode->fid.vid);
3758+ *bp++ = htonl(vnode->fid.vnode);
3759+ *bp++ = htonl(vnode->fid.unique);
3760+ *bp++ = htonl(1);
3761+ *bp++ = htonl(vnode->cb_version);
3762+ *bp++ = htonl(vnode->cb_expiry);
3763+ *bp++ = htonl(vnode->cb_type);
3764+
3765+ /* send the parameters to the server */
3766+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3767+ if (ret<0)
3768+ goto abort;
3769+
3770+ /* wait for the reply to completely arrive */
3771+ for (;;) {
3772+ set_current_state(TASK_INTERRUPTIBLE);
3773+ if (call->app_call_state!=RXRPC_CSTATE_CLNT_RCV_REPLY ||
3774+ signal_pending(current))
3775+ break;
3776+ schedule();
3777+ }
3778+ set_current_state(TASK_RUNNING);
3779+
3780+ ret = -EINTR;
3781+ if (signal_pending(current))
3782+ goto abort;
3783+
3784+ switch (call->app_call_state) {
3785+ case RXRPC_CSTATE_ERROR:
3786+ ret = call->app_errno;
3787+ goto out_unwait;
3788+
3789+ case RXRPC_CSTATE_CLNT_GOT_REPLY:
3790+ ret = 0;
3791+ goto out_unwait;
3792+
3793+ default:
3794+ BUG();
3795+ }
3796+
3797+ out_unwait:
3798+ set_current_state(TASK_RUNNING);
3799+ remove_wait_queue(&call->waitq,&myself);
3800+ rxrpc_put_call(call);
3801+ out_put_conn:
3802+ afs_server_release_callslot(server,&callslot);
3803+ out:
3804+ _leave("");
3805+ return ret;
3806+
3807+ abort:
3808+ set_current_state(TASK_UNINTERRUPTIBLE);
3809+ rxrpc_call_abort(call,ret);
3810+ schedule();
3811+ goto out_unwait;
3812+} /* end afs_rxfs_give_up_callback() */
3813+
3814+/*****************************************************************************/
3815+/*
3816+ * look a filename up in a directory
3817+ * - this operation doesn't seem to work correctly in OpenAFS server 1.2.2
3818+ */
3819+#if 0
3820+int afs_rxfs_lookup(afs_server_t *server,
3821+ afs_vnode_t *dir,
3822+ const char *filename,
3823+ afs_vnode_t *vnode,
3824+ afs_volsync_t *volsync)
3825+{
3826+ DECLARE_WAITQUEUE(myself,current);
3827+
3828+ struct rxrpc_connection *conn;
3829+ struct rxrpc_call *call;
3830+ struct iovec piov[3];
3831+ size_t sent;
3832+ int ret;
3833+ u32 *bp, zero;
3834+
3835+ kenter("%p,{%u,%u,%u},%s",server,fid->vid,fid->vnode,fid->unique,filename);
3836+
3837+ /* get hold of the fileserver connection */
3838+ ret = afs_server_get_fsconn(server,&conn);
3839+ if (ret<0)
3840+ goto out;
3841+
3842+ /* create a call through that connection */
3843+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxfs_aemap,&call);
3844+ if (ret<0) {
3845+ printk("kAFS: Unable to create call: %d\n",ret);
3846+ goto out_put_conn;
3847+ }
3848+ call->app_opcode = FSLOOKUP;
3849+
3850+ /* we want to get event notifications from the call */
3851+ add_wait_queue(&call->waitq,&myself);
3852+
3853+ /* marshall the parameters */
3854+ bp = rxrpc_call_alloc_scratch(call,20);
3855+
3856+ zero = 0;
3857+
3858+ piov[0].iov_len = 20;
3859+ piov[0].iov_base = bp;
3860+ piov[1].iov_len = strlen(filename);
3861+ piov[1].iov_base = (char*) filename;
3862+ piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
3863+ piov[2].iov_base = &zero;
3864+
3865+ *bp++ = htonl(FSLOOKUP);
3866+ *bp++ = htonl(dirfid->vid);
3867+ *bp++ = htonl(dirfid->vnode);
3868+ *bp++ = htonl(dirfid->unique);
3869+ *bp++ = htonl(piov[1].iov_len);
3870+
3871+ /* send the parameters to the server */
3872+ ret = rxrpc_call_write_data(call,3,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
3873+ if (ret<0)
3874+ goto abort;
3875+
3876+ /* wait for the reply to completely arrive */
3877+ bp = rxrpc_call_alloc_scratch(call,220);
3878+
3879+ ret = rxrpc_call_read_data(call,bp,220,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
3880+ if (ret<0) {
3881+ if (ret==-ECONNABORTED) {
3882+ ret = call->app_errno;
3883+ goto out_unwait;
3884+ }
3885+ goto abort;
3886+ }
3887+
3888+ /* unmarshall the reply */
3889+ fid->vid = ntohl(*bp++);
3890+ fid->vnode = ntohl(*bp++);
3891+ fid->unique = ntohl(*bp++);
3892+
3893+ vnode->status.if_version = ntohl(*bp++);
3894+ vnode->status.type = ntohl(*bp++);
3895+ vnode->status.nlink = ntohl(*bp++);
3896+ vnode->status.size = ntohl(*bp++);
3897+ vnode->status.version = ntohl(*bp++);
3898+ vnode->status.author = ntohl(*bp++);
3899+ vnode->status.owner = ntohl(*bp++);
3900+ vnode->status.caller_access = ntohl(*bp++);
3901+ vnode->status.anon_access = ntohl(*bp++);
3902+ vnode->status.mode = ntohl(*bp++);
3903+ vnode->status.parent.vid = dirfid->vid;
3904+ vnode->status.parent.vnode = ntohl(*bp++);
3905+ vnode->status.parent.unique = ntohl(*bp++);
3906+ bp++; /* seg size */
3907+ vnode->status.mtime_client = ntohl(*bp++);
3908+ vnode->status.mtime_server = ntohl(*bp++);
3909+ bp++; /* group */
3910+ bp++; /* sync counter */
3911+ vnode->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
3912+ bp++; /* spare2 */
3913+ bp++; /* spare3 */
3914+ bp++; /* spare4 */
3915+
3916+ dir->status.if_version = ntohl(*bp++);
3917+ dir->status.type = ntohl(*bp++);
3918+ dir->status.nlink = ntohl(*bp++);
3919+ dir->status.size = ntohl(*bp++);
3920+ dir->status.version = ntohl(*bp++);
3921+ dir->status.author = ntohl(*bp++);
3922+ dir->status.owner = ntohl(*bp++);
3923+ dir->status.caller_access = ntohl(*bp++);
3924+ dir->status.anon_access = ntohl(*bp++);
3925+ dir->status.mode = ntohl(*bp++);
3926+ dir->status.parent.vid = dirfid->vid;
3927+ dir->status.parent.vnode = ntohl(*bp++);
3928+ dir->status.parent.unique = ntohl(*bp++);
3929+ bp++; /* seg size */
3930+ dir->status.mtime_client = ntohl(*bp++);
3931+ dir->status.mtime_server = ntohl(*bp++);
3932+ bp++; /* group */
3933+ bp++; /* sync counter */
3934+ dir->status.version |= ((unsigned long long) ntohl(*bp++)) << 32;
3935+ bp++; /* spare2 */
3936+ bp++; /* spare3 */
3937+ bp++; /* spare4 */
3938+
3939+ callback->fid = *fid;
3940+ callback->version = ntohl(*bp++);
3941+ callback->expiry = ntohl(*bp++);
3942+ callback->type = ntohl(*bp++);
3943+
3944+ if (volsync) {
3945+ volsync->creation = ntohl(*bp++);
3946+ bp++; /* spare2 */
3947+ bp++; /* spare3 */
3948+ bp++; /* spare4 */
3949+ bp++; /* spare5 */
3950+ bp++; /* spare6 */
3951+ }
3952+
3953+ /* success */
3954+ ret = 0;
3955+
3956+ out_unwait:
3957+ set_current_state(TASK_RUNNING);
3958+ remove_wait_queue(&call->waitq,&myself);
3959+ rxrpc_put_call(call);
3960+ out_put_conn:
3961+ afs_server_release_fsconn(server,conn);
3962+ out:
3963+ kleave("");
3964+ return ret;
3965+
3966+ abort:
3967+ set_current_state(TASK_UNINTERRUPTIBLE);
3968+ rxrpc_call_abort(call,ret);
3969+ schedule();
3970+ goto out_unwait;
3971+} /* end afs_rxfs_lookup() */
3972+#endif
3973diff -urNp linux-5240/fs/afs/fsclient.h linux-5250/fs/afs/fsclient.h
3974--- linux-5240/fs/afs/fsclient.h 1970-01-01 01:00:00.000000000 +0100
3975+++ linux-5250/fs/afs/fsclient.h
3976@@ -0,0 +1,53 @@
3977+/* fsclient.h: AFS File Server client stub declarations
3978+ *
3979+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
3980+ * Written by David Howells (dhowells@redhat.com)
3981+ *
3982+ * This program is free software; you can redistribute it and/or
3983+ * modify it under the terms of the GNU General Public License
3984+ * as published by the Free Software Foundation; either version
3985+ * 2 of the License, or (at your option) any later version.
3986+ */
3987+
3988+#ifndef _LINUX_AFS_FSCLIENT_H
3989+#define _LINUX_AFS_FSCLIENT_H
3990+
3991+#include "server.h"
3992+
3993+extern int afs_rxfs_get_volume_info(afs_server_t *server,
3994+ const char *name,
3995+ afs_volume_info_t *vinfo);
3996+
3997+extern int afs_rxfs_fetch_file_status(afs_server_t *server,
3998+ afs_vnode_t *vnode,
3999+ afs_volsync_t *volsync);
4000+
4001+struct afs_rxfs_fetch_descriptor {
4002+ afs_fid_t fid; /* file ID to fetch */
4003+ size_t size; /* total number of bytes to fetch */
4004+ off_t offset; /* offset in file to start from */
4005+ void *buffer; /* read buffer */
4006+ size_t actual; /* actual size sent back by server */
4007+};
4008+
4009+extern int afs_rxfs_fetch_file_data(afs_server_t *server,
4010+ afs_vnode_t *vnode,
4011+ struct afs_rxfs_fetch_descriptor *desc,
4012+ afs_volsync_t *volsync);
4013+
4014+extern int afs_rxfs_give_up_callback(afs_server_t *server, afs_vnode_t *vnode);
4015+
4016+/* this doesn't appear to work in OpenAFS server */
4017+extern int afs_rxfs_lookup(afs_server_t *server,
4018+ afs_vnode_t *dir,
4019+ const char *filename,
4020+ afs_vnode_t *vnode,
4021+ afs_volsync_t *volsync);
4022+
4023+/* this is apparently mis-implemented in OpenAFS server */
4024+extern int afs_rxfs_get_root_volume(afs_server_t *server,
4025+ char *buf,
4026+ size_t *buflen);
4027+
4028+
4029+#endif /* _LINUX_AFS_FSCLIENT_H */
4030diff -urNp linux-5240/fs/afs/inode.c linux-5250/fs/afs/inode.c
4031--- linux-5240/fs/afs/inode.c 1970-01-01 01:00:00.000000000 +0100
4032+++ linux-5250/fs/afs/inode.c
4033@@ -0,0 +1,412 @@
4034+/*
4035+ * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
4036+ *
4037+ * This software may be freely redistributed under the terms of the
4038+ * GNU General Public License.
4039+ *
4040+ * You should have received a copy of the GNU General Public License
4041+ * along with this program; if not, write to the Free Software
4042+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
4043+ *
4044+ * Authors: David Woodhouse <dwmw2@cambridge.redhat.com>
4045+ * David Howells <dhowells@redhat.com>
4046+ *
4047+ */
4048+
4049+#include <linux/kernel.h>
4050+#include <linux/module.h>
4051+#include <linux/init.h>
4052+#include <linux/sched.h>
4053+#include <linux/slab.h>
4054+#include <linux/fs.h>
4055+#include <linux/pagemap.h>
4056+#include "volume.h"
4057+#include "vnode.h"
4058+#include "cache.h"
4059+#include "super.h"
4060+#include "internal.h"
4061+
4062+struct afs_iget_data {
4063+ afs_fid_t fid;
4064+ afs_volume_t *volume; /* volume on which resides */
4065+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4066+ afs_vnode_t *new_vnode; /* new vnode record */
4067+#endif
4068+};
4069+
4070+/*****************************************************************************/
4071+/*
4072+ * map the AFS file status to the inode member variables
4073+ */
4074+static int afs_inode_map_status(afs_vnode_t *vnode)
4075+{
4076+ struct inode *inode = AFS_VNODE_TO_I(vnode);
4077+
4078+ _debug("FS: ft=%d lk=%d sz=%u ver=%Lu mod=%hu",
4079+ vnode->status.type,
4080+ vnode->status.nlink,
4081+ vnode->status.size,
4082+ vnode->status.version,
4083+ vnode->status.mode);
4084+
4085+ switch (vnode->status.type) {
4086+ case AFS_FTYPE_FILE:
4087+ inode->i_mode = S_IFREG | vnode->status.mode;
4088+ inode->i_op = &afs_file_inode_operations;
4089+ inode->i_fop = &afs_file_file_operations;
4090+ break;
4091+ case AFS_FTYPE_DIR:
4092+ inode->i_mode = S_IFDIR | vnode->status.mode;
4093+ inode->i_op = &afs_dir_inode_operations;
4094+ inode->i_fop = &afs_dir_file_operations;
4095+ break;
4096+ case AFS_FTYPE_SYMLINK:
4097+ inode->i_mode = S_IFLNK | vnode->status.mode;
4098+ inode->i_op = &page_symlink_inode_operations;
4099+ break;
4100+ default:
4101+ printk("kAFS: AFS vnode with undefined type\n");
4102+ return -EBADMSG;
4103+ }
4104+
4105+ inode->i_nlink = vnode->status.nlink;
4106+ inode->i_uid = vnode->status.owner;
4107+ inode->i_gid = 0;
4108+ inode->i_rdev = NODEV;
4109+ inode->i_size = vnode->status.size;
4110+ inode->i_atime = inode->i_mtime = inode->i_ctime = vnode->status.mtime_server;
4111+ inode->i_blksize = PAGE_CACHE_SIZE;
4112+ inode->i_blocks = 0;
4113+ inode->i_version = vnode->fid.unique;
4114+ inode->i_mapping->a_ops = &afs_fs_aops;
4115+
4116+ /* check to see whether a symbolic link is really a mountpoint */
4117+ if (vnode->status.type==AFS_FTYPE_SYMLINK) {
4118+ afs_mntpt_check_symlink(vnode);
4119+
4120+ if (vnode->flags & AFS_VNODE_MOUNTPOINT) {
4121+ inode->i_mode = S_IFDIR | vnode->status.mode;
4122+ inode->i_op = &afs_mntpt_inode_operations;
4123+ inode->i_fop = &afs_mntpt_file_operations;
4124+ }
4125+ }
4126+
4127+ return 0;
4128+} /* end afs_inode_map_status() */
4129+
4130+/*****************************************************************************/
4131+/*
4132+ * attempt to fetch the status of an inode, coelescing multiple simultaneous fetches
4133+ */
4134+int afs_inode_fetch_status(struct inode *inode)
4135+{
4136+ afs_vnode_t *vnode;
4137+ int ret;
4138+
4139+ vnode = AFS_FS_I(inode);
4140+
4141+ ret = afs_vnode_fetch_status(vnode);
4142+
4143+ if (ret==0)
4144+ ret = afs_inode_map_status(vnode);
4145+
4146+ return ret;
4147+
4148+} /* end afs_inode_fetch_status() */
4149+
4150+/*****************************************************************************/
4151+/*
4152+ * iget5() comparator
4153+ */
4154+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4155+static int afs_iget5_test(struct inode *inode, void *opaque)
4156+{
4157+ struct afs_iget_data *data = opaque;
4158+
4159+ /* only match inodes with the same version number */
4160+ return inode->i_ino==data->fid.vnode && inode->i_version==data->fid.unique;
4161+} /* end afs_iget5_test() */
4162+#endif
4163+
4164+/*****************************************************************************/
4165+/*
4166+ * iget5() inode initialiser
4167+ */
4168+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4169+static int afs_iget5_set(struct inode *inode, void *opaque)
4170+{
4171+ struct afs_iget_data *data = opaque;
4172+ afs_vnode_t *vnode = AFS_FS_I(inode);
4173+
4174+ inode->i_ino = data->fid.vnode;
4175+ inode->i_version = data->fid.unique;
4176+ vnode->fid = data->fid;
4177+ vnode->volume = data->volume;
4178+
4179+ return 0;
4180+} /* end afs_iget5_set() */
4181+#endif
4182+
4183+/*****************************************************************************/
4184+/*
4185+ * iget4() comparator
4186+ */
4187+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4188+static int afs_iget4_test(struct inode *inode, ino_t ino, void *opaque)
4189+{
4190+ struct afs_iget_data *data = opaque;
4191+
4192+ /* only match inodes with the same version number */
4193+ return inode->i_ino==data->fid.vnode && inode->i_version==data->fid.unique;
4194+} /* end afs_iget4_test() */
4195+#endif
4196+
4197+/*****************************************************************************/
4198+/*
4199+ * read an inode (2.4 only)
4200+ */
4201+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4202+void afs_read_inode2(struct inode *inode, void *opaque)
4203+{
4204+ struct afs_iget_data *data = opaque;
4205+ afs_vnode_t *vnode;
4206+ int ret;
4207+
4208+ kenter(",{{%u,%u,%u},%p}",data->fid.vid,data->fid.vnode,data->fid.unique,data->volume);
4209+
4210+ if (inode->u.generic_ip) BUG();
4211+
4212+ /* attach a pre-allocated vnode record */
4213+ inode->u.generic_ip = vnode = data->new_vnode;
4214+ data->new_vnode = NULL;
4215+
4216+ memset(vnode,0,sizeof(*vnode));
4217+ vnode->inode = inode;
4218+ init_waitqueue_head(&vnode->update_waitq);
4219+ spin_lock_init(&vnode->lock);
4220+ INIT_LIST_HEAD(&vnode->cb_link);
4221+ INIT_LIST_HEAD(&vnode->cb_hash_link);
4222+ afs_timer_init(&vnode->cb_timeout,&afs_vnode_cb_timed_out_ops);
4223+ vnode->flags |= AFS_VNODE_CHANGED;
4224+ vnode->volume = data->volume;
4225+ vnode->fid = data->fid;
4226+
4227+ /* ask the server for a status check */
4228+ ret = afs_vnode_fetch_status(vnode);
4229+ if (ret<0) {
4230+ make_bad_inode(inode);
4231+ kleave(" [bad inode]");
4232+ return;
4233+ }
4234+
4235+ ret = afs_inode_map_status(vnode);
4236+ if (ret<0) {
4237+ make_bad_inode(inode);
4238+ kleave(" [bad inode]");
4239+ return;
4240+ }
4241+
4242+ kleave("");
4243+ return;
4244+} /* end afs_read_inode2() */
4245+#endif
4246+
4247+/*****************************************************************************/
4248+/*
4249+ * inode retrieval
4250+ */
4251+inline int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inode)
4252+{
4253+ struct afs_iget_data data = { fid: *fid };
4254+ struct afs_super_info *as;
4255+ struct inode *inode;
4256+ afs_vnode_t *vnode;
4257+ int ret;
4258+
4259+ kenter(",{%u,%u,%u},,",fid->vid,fid->vnode,fid->unique);
4260+
4261+ as = sb->u.generic_sbp;
4262+ data.volume = as->volume;
4263+
4264+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4265+ inode = iget5_locked(sb,fid->vnode,afs_iget5_test,afs_iget5_set,&data);
4266+ if (!inode) {
4267+ _leave(" = -ENOMEM");
4268+ return -ENOMEM;
4269+ }
4270+
4271+ vnode = AFS_FS_I(inode);
4272+
4273+ /* deal with an existing inode */
4274+ if (!(inode->i_state & I_NEW)) {
4275+ ret = afs_vnode_fetch_status(vnode);
4276+ if (ret==0)
4277+ *_inode = inode;
4278+ else
4279+ iput(inode);
4280+ _leave(" = %d",ret);
4281+ return ret;
4282+ }
4283+
4284+ /* okay... it's a new inode */
4285+ vnode->flags |= AFS_VNODE_CHANGED;
4286+ ret = afs_inode_fetch_status(inode);
4287+ if (ret<0)
4288+ goto bad_inode;
4289+
4290+#if 0
4291+ /* find a cache entry for it */
4292+ ret = afs_cache_lookup_vnode(as->volume,vnode);
4293+ if (ret<0)
4294+ goto bad_inode;
4295+#endif
4296+
4297+ /* success */
4298+ unlock_new_inode(inode);
4299+
4300+ *_inode = inode;
4301+ _leave(" = 0 [CB { v=%u x=%lu t=%u nix=%u }]",
4302+ vnode->cb_version,
4303+ vnode->cb_timeout.timo_jif,
4304+ vnode->cb_type,
4305+ vnode->nix
4306+ );
4307+ return 0;
4308+
4309+ /* failure */
4310+ bad_inode:
4311+ make_bad_inode(inode);
4312+ unlock_new_inode(inode);
4313+ iput(inode);
4314+
4315+ _leave(" = %d [bad]",ret);
4316+ return ret;
4317+
4318+#else
4319+
4320+ /* pre-allocate a vnode record so that afs_read_inode2() doesn't have to return an inode
4321+ * without one attached
4322+ */
4323+ data.new_vnode = kmalloc(sizeof(afs_vnode_t),GFP_KERNEL);
4324+ if (!data.new_vnode) {
4325+ kleave(" = -ENOMEM");
4326+ return -ENOMEM;
4327+ }
4328+
4329+ inode = iget4(sb,fid->vnode,afs_iget4_test,&data);
4330+ if (data.new_vnode) kfree(data.new_vnode);
4331+ if (!inode) {
4332+ kleave(" = -ENOMEM");
4333+ return -ENOMEM;
4334+ }
4335+
4336+ vnode = AFS_FS_I(inode);
4337+ *_inode = inode;
4338+ kleave(" = 0 [CB { v=%u x=%lu t=%u nix=%u }]",
4339+ vnode->cb_version,
4340+ vnode->cb_timeout.timo_jif,
4341+ vnode->cb_type,
4342+ vnode->nix
4343+ );
4344+ return 0;
4345+#endif
4346+} /* end afs_iget() */
4347+
4348+/*****************************************************************************/
4349+/*
4350+ * read the attributes of an inode
4351+ */
4352+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4353+int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
4354+{
4355+ struct inode *inode;
4356+ afs_vnode_t *vnode;
4357+ int ret;
4358+
4359+ inode = dentry->d_inode;
4360+
4361+ _enter("{ ino=%lu v=%lu }",inode->i_ino,inode->i_version);
4362+
4363+ vnode = AFS_FS_I(inode);
4364+
4365+ ret = afs_inode_fetch_status(inode);
4366+ if (ret==-ENOENT) {
4367+ _leave(" = %d [%d %p]",ret,atomic_read(&dentry->d_count),dentry->d_inode);
4368+ return ret;
4369+ }
4370+ else if (ret<0) {
4371+ make_bad_inode(inode);
4372+ _leave(" = %d",ret);
4373+ return ret;
4374+ }
4375+
4376+ /* transfer attributes from the inode structure to the stat structure */
4377+ generic_fillattr(inode,stat);
4378+
4379+ _leave(" = 0 CB { v=%u x=%u t=%u }",
4380+ vnode->callback.version,
4381+ vnode->callback.expiry,
4382+ vnode->callback.type);
4383+
4384+ return 0;
4385+} /* end afs_inode_getattr() */
4386+#endif
4387+
4388+/*****************************************************************************/
4389+/*
4390+ * revalidate the inode
4391+ */
4392+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
4393+int afs_inode_revalidate(struct dentry *dentry)
4394+{
4395+ struct inode *inode;
4396+ afs_vnode_t *vnode;
4397+ int ret;
4398+
4399+ inode = dentry->d_inode;
4400+
4401+ _enter("{ ino=%lu v=%lu }",inode->i_ino,inode->i_version);
4402+
4403+ vnode = AFS_FS_I(inode);
4404+
4405+ ret = afs_inode_fetch_status(inode);
4406+ if (ret==-ENOENT) {
4407+ _leave(" = %d [%d %p]",ret,atomic_read(&dentry->d_count),dentry->d_inode);
4408+ return ret;
4409+ }
4410+ else if (ret<0) {
4411+ make_bad_inode(inode);
4412+ _leave(" = %d",ret);
4413+ return ret;
4414+ }
4415+
4416+ _leave(" = 0 CB { v=%u x=%u t=%u }",
4417+ vnode->cb_version,
4418+ vnode->cb_expiry,
4419+ vnode->cb_type);
4420+
4421+ return 0;
4422+} /* end afs_inode_revalidate() */
4423+#endif
4424+
4425+/*****************************************************************************/
4426+/*
4427+ * clear an AFS inode
4428+ */
4429+void afs_clear_inode(struct inode *inode)
4430+{
4431+ afs_vnode_t *vnode;
4432+
4433+ vnode = AFS_FS_I(inode);
4434+
4435+ _enter("(ino=%lu { v=%u x=%u t=%u })",
4436+ inode->i_ino,
4437+ vnode->cb_version,
4438+ vnode->cb_expiry,
4439+ vnode->cb_type
4440+ );
4441+
4442+ afs_vnode_give_up_callback(vnode);
4443+
4444+ _leave("");
4445+} /* end afs_clear_inode() */
4446diff -urNp linux-5240/fs/afs/internal.h linux-5250/fs/afs/internal.h
4447--- linux-5240/fs/afs/internal.h 1970-01-01 01:00:00.000000000 +0100
4448+++ linux-5250/fs/afs/internal.h
4449@@ -0,0 +1,115 @@
4450+/* internal.h: internal AFS stuff
4451+ *
4452+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4453+ * Written by David Howells (dhowells@redhat.com)
4454+ *
4455+ * This program is free software; you can redistribute it and/or
4456+ * modify it under the terms of the GNU General Public License
4457+ * as published by the Free Software Foundation; either version
4458+ * 2 of the License, or (at your option) any later version.
4459+ */
4460+
4461+#ifndef AFS_INTERNAL_H
4462+#define AFS_INTERNAL_H
4463+
4464+#include <linux/version.h>
4465+#include <linux/compiler.h>
4466+#include <linux/kernel.h>
4467+#include <linux/fs.h>
4468+
4469+/*
4470+ * debug tracing
4471+ */
4472+#define kenter(FMT,...) printk("==> %s("FMT")\n",__FUNCTION__,##__VA_ARGS__)
4473+#define kleave(FMT,...) printk("<== %s()"FMT"\n",__FUNCTION__,##__VA_ARGS__)
4474+#define kdebug(FMT,...) printk(FMT"\n",##__VA_ARGS__)
4475+#define kproto(FMT,...) printk("### "FMT"\n",##__VA_ARGS__)
4476+#define knet(FMT,...) printk(FMT"\n",##__VA_ARGS__)
4477+
4478+#if 0
4479+#define _enter(FMT,...) kenter(FMT,##__VA_ARGS__)
4480+#define _leave(FMT,...) kleave(FMT,##__VA_ARGS__)
4481+#define _debug(FMT,...) kdebug(FMT,##__VA_ARGS__)
4482+#define _proto(FMT,...) kproto(FMT,##__VA_ARGS__)
4483+#define _net(FMT,...) knet(FMT,##__VA_ARGS__)
4484+#else
4485+#define _enter(FMT,...) do { } while(0)
4486+#define _leave(FMT,...) do { } while(0)
4487+#define _debug(FMT,...) do { } while(0)
4488+#define _proto(FMT,...) do { } while(0)
4489+#define _net(FMT,...) do { } while(0)
4490+#endif
4491+
4492+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,5,0)
4493+#define wait_on_page_locked wait_on_page
4494+#define PageUptodate Page_Uptodate
4495+
4496+static inline struct proc_dir_entry *PDE(const struct inode *inode)
4497+{
4498+ return (struct proc_dir_entry *)inode->u.generic_ip;
4499+}
4500+#endif
4501+
4502+/*
4503+ * cell.c
4504+ */
4505+extern struct rw_semaphore afs_proc_cells_sem;
4506+extern struct list_head afs_proc_cells;
4507+
4508+/*
4509+ * dir.c
4510+ */
4511+extern struct inode_operations afs_dir_inode_operations;
4512+extern struct file_operations afs_dir_file_operations;
4513+
4514+/*
4515+ * file.c
4516+ */
4517+extern struct address_space_operations afs_fs_aops;
4518+extern struct inode_operations afs_file_inode_operations;
4519+extern struct file_operations afs_file_file_operations;
4520+
4521+/*
4522+ * inode.c
4523+ */
4524+extern int afs_iget(struct super_block *sb, afs_fid_t *fid, struct inode **_inode);
4525+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
4526+extern int afs_inode_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
4527+#else
4528+extern void afs_read_inode2(struct inode *inode, void *opaque);
4529+extern int afs_inode_revalidate(struct dentry *dentry);
4530+#endif
4531+extern void afs_clear_inode(struct inode *inode);
4532+
4533+/*
4534+ * mntpt.c
4535+ */
4536+extern struct inode_operations afs_mntpt_inode_operations;
4537+extern struct file_operations afs_mntpt_file_operations;
4538+
4539+extern int afs_mntpt_check_symlink(afs_vnode_t *vnode);
4540+
4541+/*
4542+ * super.c
4543+ */
4544+extern int afs_fs_init(void);
4545+extern void afs_fs_exit(void);
4546+
4547+#define AFS_CB_HASH_COUNT (PAGE_SIZE/sizeof(struct list_head))
4548+
4549+extern struct list_head afs_cb_hash_tbl[];
4550+extern spinlock_t afs_cb_hash_lock;
4551+
4552+#define afs_cb_hash(SRV,FID) \
4553+ afs_cb_hash_tbl[((unsigned)(SRV) + (FID)->vid + (FID)->vnode + (FID)->unique) % \
4554+ AFS_CB_HASH_COUNT]
4555+
4556+/*
4557+ * proc.c
4558+ */
4559+extern int afs_proc_init(void);
4560+extern void afs_proc_cleanup(void);
4561+extern int afs_proc_cell_setup(afs_cell_t *cell);
4562+extern void afs_proc_cell_remove(afs_cell_t *cell);
4563+
4564+#endif /* AFS_INTERNAL_H */
4565diff -urNp linux-5240/fs/afs/kafsasyncd.c linux-5250/fs/afs/kafsasyncd.c
4566--- linux-5240/fs/afs/kafsasyncd.c 1970-01-01 01:00:00.000000000 +0100
4567+++ linux-5250/fs/afs/kafsasyncd.c
4568@@ -0,0 +1,266 @@
4569+/* kafsasyncd.c: AFS asynchronous operation daemon
4570+ *
4571+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4572+ * Written by David Howells (dhowells@redhat.com)
4573+ *
4574+ * This program is free software; you can redistribute it and/or
4575+ * modify it under the terms of the GNU General Public License
4576+ * as published by the Free Software Foundation; either version
4577+ * 2 of the License, or (at your option) any later version.
4578+ *
4579+ *
4580+ * The AFS async daemon is used to the following:
4581+ * - probe "dead" servers to see whether they've come back to life yet.
4582+ * - probe "live" servers that we haven't talked to for a while to see if they are better
4583+ * candidates for serving than what we're currently using
4584+ * - poll volume location servers to keep up to date volume location lists
4585+ */
4586+
4587+#include <linux/version.h>
4588+#include <linux/module.h>
4589+#include <linux/init.h>
4590+#include <linux/sched.h>
4591+#include <linux/completion.h>
4592+#include "cell.h"
4593+#include "server.h"
4594+#include "volume.h"
4595+#include "kafsasyncd.h"
4596+#include "kafstimod.h"
4597+#include <rxrpc/call.h>
4598+#include <asm/errno.h>
4599+#include "internal.h"
4600+
4601+static DECLARE_COMPLETION(kafsasyncd_alive);
4602+static DECLARE_COMPLETION(kafsasyncd_dead);
4603+static DECLARE_WAIT_QUEUE_HEAD(kafsasyncd_sleepq);
4604+static struct task_struct *kafsasyncd_task;
4605+static int kafsasyncd_die;
4606+
4607+static int kafsasyncd(void *arg);
4608+
4609+static LIST_HEAD(kafsasyncd_async_attnq);
4610+static LIST_HEAD(kafsasyncd_async_busyq);
4611+static spinlock_t kafsasyncd_async_lock = SPIN_LOCK_UNLOCKED;
4612+
4613+static void kafsasyncd_null_call_attn_func(struct rxrpc_call *call)
4614+{
4615+}
4616+
4617+static void kafsasyncd_null_call_error_func(struct rxrpc_call *call)
4618+{
4619+}
4620+
4621+/*****************************************************************************/
4622+/*
4623+ * start the async daemon
4624+ */
4625+int afs_kafsasyncd_start(void)
4626+{
4627+ int ret;
4628+
4629+ ret = kernel_thread(kafsasyncd,NULL,0);
4630+ if (ret<0)
4631+ return ret;
4632+
4633+ wait_for_completion(&kafsasyncd_alive);
4634+
4635+ return ret;
4636+} /* end afs_kafsasyncd_start() */
4637+
4638+/*****************************************************************************/
4639+/*
4640+ * stop the async daemon
4641+ */
4642+void afs_kafsasyncd_stop(void)
4643+{
4644+ /* get rid of my daemon */
4645+ kafsasyncd_die = 1;
4646+ wake_up(&kafsasyncd_sleepq);
4647+ wait_for_completion(&kafsasyncd_dead);
4648+
4649+} /* end afs_kafsasyncd_stop() */
4650+
4651+/*****************************************************************************/
4652+/*
4653+ * probing daemon
4654+ */
4655+static int kafsasyncd(void *arg)
4656+{
4657+ DECLARE_WAITQUEUE(myself,current);
4658+
4659+ struct list_head *_p;
4660+ int die;
4661+
4662+ kafsasyncd_task = current;
4663+
4664+ printk("kAFS: Started kafsasyncd %d\n",current->pid);
4665+ strcpy(current->comm,"kafsasyncd");
4666+
4667+ daemonize();
4668+
4669+ complete(&kafsasyncd_alive);
4670+
4671+ /* only certain signals are of interest */
4672+ spin_lock_irq(&current->sigmask_lock);
4673+ siginitsetinv(&current->blocked,0);
4674+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,3)
4675+ recalc_sigpending();
4676+#else
4677+ recalc_sigpending(current);
4678+#endif
4679+ spin_unlock_irq(&current->sigmask_lock);
4680+
4681+ /* loop around looking for things to attend to */
4682+ do {
4683+ set_current_state(TASK_INTERRUPTIBLE);
4684+ add_wait_queue(&kafsasyncd_sleepq,&myself);
4685+
4686+ for (;;) {
4687+ if (!list_empty(&kafsasyncd_async_attnq) ||
4688+ signal_pending(current) ||
4689+ kafsasyncd_die)
4690+ break;
4691+
4692+ schedule();
4693+ set_current_state(TASK_INTERRUPTIBLE);
4694+ }
4695+
4696+ remove_wait_queue(&kafsasyncd_sleepq,&myself);
4697+ set_current_state(TASK_RUNNING);
4698+
4699+ /* discard pending signals */
4700+ while (signal_pending(current)) {
4701+ siginfo_t sinfo;
4702+
4703+ spin_lock_irq(&current->sigmask_lock);
4704+ dequeue_signal(&current->blocked,&sinfo);
4705+ spin_unlock_irq(&current->sigmask_lock);
4706+ }
4707+
4708+ die = kafsasyncd_die;
4709+
4710+ /* deal with the next asynchronous operation requiring attention */
4711+ if (!list_empty(&kafsasyncd_async_attnq)) {
4712+ struct afs_async_op *op;
4713+
4714+ _debug("@@@ Begin Asynchronous Operation");
4715+
4716+ op = NULL;
4717+ spin_lock(&kafsasyncd_async_lock);
4718+
4719+ if (!list_empty(&kafsasyncd_async_attnq)) {
4720+ op = list_entry(kafsasyncd_async_attnq.next,afs_async_op_t,link);
4721+ list_del(&op->link);
4722+ list_add_tail(&op->link,&kafsasyncd_async_busyq);
4723+ }
4724+
4725+ spin_unlock(&kafsasyncd_async_lock);
4726+
4727+ _debug("@@@ Operation %p {%p}\n",op,op?op->ops:NULL);
4728+
4729+ if (op)
4730+ op->ops->attend(op);
4731+
4732+ _debug("@@@ End Asynchronous Operation");
4733+ }
4734+
4735+ } while(!die);
4736+
4737+ /* need to kill all outstanding asynchronous operations before exiting */
4738+ kafsasyncd_task = NULL;
4739+ spin_lock(&kafsasyncd_async_lock);
4740+
4741+ /* fold the busy and attention queues together */
4742+ list_splice(&kafsasyncd_async_busyq,&kafsasyncd_async_attnq);
4743+ list_del_init(&kafsasyncd_async_busyq);
4744+
4745+ /* dequeue kafsasyncd from all their wait queues */
4746+ list_for_each(_p,&kafsasyncd_async_attnq) {
4747+ afs_async_op_t *op = list_entry(_p,afs_async_op_t,link);
4748+
4749+ op->call->app_attn_func = kafsasyncd_null_call_attn_func;
4750+ op->call->app_error_func = kafsasyncd_null_call_error_func;
4751+ remove_wait_queue(&op->call->waitq,&op->waiter);
4752+ }
4753+
4754+ spin_unlock(&kafsasyncd_async_lock);
4755+
4756+ /* abort all the operations */
4757+ while (!list_empty(&kafsasyncd_async_attnq)) {
4758+ afs_async_op_t *op = list_entry(_p,afs_async_op_t,link);
4759+ list_del_init(&op->link);
4760+
4761+ rxrpc_call_abort(op->call,-EIO);
4762+ rxrpc_put_call(op->call);
4763+ op->call = NULL;
4764+
4765+ op->ops->discard(op);
4766+ }
4767+
4768+ /* and that's all */
4769+ _leave("");
4770+ complete_and_exit(&kafsasyncd_dead,0);
4771+
4772+} /* end kafsasyncd() */
4773+
4774+/*****************************************************************************/
4775+/*
4776+ * begin an operation
4777+ * - place operation on busy queue
4778+ */
4779+void afs_kafsasyncd_begin_op(afs_async_op_t *op)
4780+{
4781+ _enter("");
4782+
4783+ spin_lock(&kafsasyncd_async_lock);
4784+
4785+ init_waitqueue_entry(&op->waiter,kafsasyncd_task);
4786+
4787+ list_del(&op->link);
4788+ list_add_tail(&op->link,&kafsasyncd_async_busyq);
4789+
4790+ spin_unlock(&kafsasyncd_async_lock);
4791+
4792+ _leave("");
4793+} /* end afs_kafsasyncd_begin_op() */
4794+
4795+/*****************************************************************************/
4796+/*
4797+ * request attention for an operation
4798+ * - move to attention queue
4799+ */
4800+void afs_kafsasyncd_attend_op(afs_async_op_t *op)
4801+{
4802+ _enter("");
4803+
4804+ spin_lock(&kafsasyncd_async_lock);
4805+
4806+ list_del(&op->link);
4807+ list_add_tail(&op->link,&kafsasyncd_async_attnq);
4808+
4809+ spin_unlock(&kafsasyncd_async_lock);
4810+
4811+ wake_up(&kafsasyncd_sleepq);
4812+
4813+ _leave("");
4814+} /* end afs_kafsasyncd_attend_op() */
4815+
4816+/*****************************************************************************/
4817+/*
4818+ * terminate an operation
4819+ * - remove from either queue
4820+ */
4821+void afs_kafsasyncd_terminate_op(afs_async_op_t *op)
4822+{
4823+ _enter("");
4824+
4825+ spin_lock(&kafsasyncd_async_lock);
4826+
4827+ list_del_init(&op->link);
4828+
4829+ spin_unlock(&kafsasyncd_async_lock);
4830+
4831+ wake_up(&kafsasyncd_sleepq);
4832+
4833+ _leave("");
4834+} /* end afs_kafsasyncd_terminate_op() */
4835diff -urNp linux-5240/fs/afs/kafsasyncd.h linux-5250/fs/afs/kafsasyncd.h
4836--- linux-5240/fs/afs/kafsasyncd.h 1970-01-01 01:00:00.000000000 +0100
4837+++ linux-5250/fs/afs/kafsasyncd.h
4838@@ -0,0 +1,49 @@
4839+/* kafsasyncd.h: AFS asynchronous operation daemon
4840+ *
4841+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4842+ * Written by David Howells (dhowells@redhat.com)
4843+ *
4844+ * This program is free software; you can redistribute it and/or
4845+ * modify it under the terms of the GNU General Public License
4846+ * as published by the Free Software Foundation; either version
4847+ * 2 of the License, or (at your option) any later version.
4848+ */
4849+
4850+#ifndef _LINUX_AFS_KAFSASYNCD_H
4851+#define _LINUX_AFS_KAFSASYNCD_H
4852+
4853+#include "types.h"
4854+
4855+struct afs_async_op_ops {
4856+ void (*attend)(afs_async_op_t *op);
4857+ void (*discard)(afs_async_op_t *op);
4858+};
4859+
4860+/*****************************************************************************/
4861+/*
4862+ * asynchronous operation record
4863+ */
4864+struct afs_async_op
4865+{
4866+ struct list_head link;
4867+ afs_server_t *server; /* server being contacted */
4868+ struct rxrpc_call *call; /* RxRPC call performing op */
4869+ wait_queue_t waiter; /* wait queue for kafsasyncd */
4870+ const struct afs_async_op_ops *ops; /* operations */
4871+};
4872+
4873+static inline void afs_async_op_init(afs_async_op_t *op, const struct afs_async_op_ops *ops)
4874+{
4875+ INIT_LIST_HEAD(&op->link);
4876+ op->call = NULL;
4877+ op->ops = ops;
4878+}
4879+
4880+extern int afs_kafsasyncd_start(void);
4881+extern void afs_kafsasyncd_stop(void);
4882+
4883+extern void afs_kafsasyncd_begin_op(afs_async_op_t *op);
4884+extern void afs_kafsasyncd_attend_op(afs_async_op_t *op);
4885+extern void afs_kafsasyncd_terminate_op(afs_async_op_t *op);
4886+
4887+#endif /* _LINUX_AFS_KAFSASYNCD_H */
4888diff -urNp linux-5240/fs/afs/kafstimod.c linux-5250/fs/afs/kafstimod.c
4889--- linux-5240/fs/afs/kafstimod.c 1970-01-01 01:00:00.000000000 +0100
4890+++ linux-5250/fs/afs/kafstimod.c
4891@@ -0,0 +1,217 @@
4892+/* kafstimod.c: AFS timeout daemon
4893+ *
4894+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
4895+ * Written by David Howells (dhowells@redhat.com)
4896+ *
4897+ * This program is free software; you can redistribute it and/or
4898+ * modify it under the terms of the GNU General Public License
4899+ * as published by the Free Software Foundation; either version
4900+ * 2 of the License, or (at your option) any later version.
4901+ */
4902+
4903+#include <linux/version.h>
4904+#include <linux/module.h>
4905+#include <linux/init.h>
4906+#include <linux/sched.h>
4907+#include <linux/completion.h>
4908+#include "cell.h"
4909+#include "volume.h"
4910+#include "kafstimod.h"
4911+#include <asm/errno.h>
4912+#include "internal.h"
4913+
4914+static DECLARE_COMPLETION(kafstimod_alive);
4915+static DECLARE_COMPLETION(kafstimod_dead);
4916+static DECLARE_WAIT_QUEUE_HEAD(kafstimod_sleepq);
4917+static int kafstimod_die;
4918+
4919+static LIST_HEAD(kafstimod_list);
4920+static spinlock_t kafstimod_lock = SPIN_LOCK_UNLOCKED;
4921+
4922+static int kafstimod(void *arg);
4923+
4924+/*****************************************************************************/
4925+/*
4926+ * start the timeout daemon
4927+ */
4928+int afs_kafstimod_start(void)
4929+{
4930+ int ret;
4931+
4932+ ret = kernel_thread(kafstimod,NULL,0);
4933+ if (ret<0)
4934+ return ret;
4935+
4936+ wait_for_completion(&kafstimod_alive);
4937+
4938+ return ret;
4939+} /* end afs_kafstimod_start() */
4940+
4941+/*****************************************************************************/
4942+/*
4943+ * stop the timeout daemon
4944+ */
4945+void afs_kafstimod_stop(void)
4946+{
4947+ /* get rid of my daemon */
4948+ kafstimod_die = 1;
4949+ wake_up(&kafstimod_sleepq);
4950+ wait_for_completion(&kafstimod_dead);
4951+
4952+} /* end afs_kafstimod_stop() */
4953+
4954+/*****************************************************************************/
4955+/*
4956+ * timeout processing daemon
4957+ */
4958+static int kafstimod(void *arg)
4959+{
4960+ DECLARE_WAITQUEUE(myself,current);
4961+
4962+ afs_timer_t *timer;
4963+
4964+ printk("kAFS: Started kafstimod %d\n",current->pid);
4965+ strcpy(current->comm,"kafstimod");
4966+
4967+ daemonize();
4968+
4969+ complete(&kafstimod_alive);
4970+
4971+ /* only certain signals are of interest */
4972+ spin_lock_irq(&current->sigmask_lock);
4973+ siginitsetinv(&current->blocked,0);
4974+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,3)
4975+ recalc_sigpending();
4976+#else
4977+ recalc_sigpending(current);
4978+#endif
4979+ spin_unlock_irq(&current->sigmask_lock);
4980+
4981+ /* loop around looking for things to attend to */
4982+ loop:
4983+ set_current_state(TASK_INTERRUPTIBLE);
4984+ add_wait_queue(&kafstimod_sleepq,&myself);
4985+
4986+ for (;;) {
4987+ unsigned long jif;
4988+ signed long timeout;
4989+
4990+ /* deal with the server being asked to die */
4991+ if (kafstimod_die) {
4992+ remove_wait_queue(&kafstimod_sleepq,&myself);
4993+ _leave("");
4994+ complete_and_exit(&kafstimod_dead,0);
4995+ }
4996+
4997+ /* discard pending signals */
4998+ while (signal_pending(current)) {
4999+ siginfo_t sinfo;
5000+
5001+ spin_lock_irq(&current->sigmask_lock);
5002+ dequeue_signal(&current->blocked,&sinfo);
5003+ spin_unlock_irq(&current->sigmask_lock);
5004+ }
5005+
5006+ /* work out the time to elapse before the next event */
5007+ spin_lock(&kafstimod_lock);
5008+ if (list_empty(&kafstimod_list)) {
5009+ timeout = MAX_SCHEDULE_TIMEOUT;
5010+ }
5011+ else {
5012+ timer = list_entry(kafstimod_list.next,afs_timer_t,link);
5013+ timeout = timer->timo_jif;
5014+ jif = jiffies;
5015+
5016+ if (time_before_eq(timeout,jif))
5017+ goto immediate;
5018+
5019+ else {
5020+ timeout = (long)timeout - (long)jiffies;
5021+ }
5022+ }
5023+ spin_unlock(&kafstimod_lock);
5024+
5025+ schedule_timeout(timeout);
5026+
5027+ set_current_state(TASK_INTERRUPTIBLE);
5028+ }
5029+
5030+ /* the thing on the front of the queue needs processing
5031+ * - we come here with the lock held and timer pointing to the expired entry
5032+ */
5033+ immediate:
5034+ remove_wait_queue(&kafstimod_sleepq,&myself);
5035+ set_current_state(TASK_RUNNING);
5036+
5037+ _debug("@@@ Begin Timeout of %p",timer);
5038+
5039+ /* dequeue the timer */
5040+ list_del_init(&timer->link);
5041+ spin_unlock(&kafstimod_lock);
5042+
5043+ /* call the timeout function */
5044+ timer->ops->timed_out(timer);
5045+
5046+ _debug("@@@ End Timeout");
5047+ goto loop;
5048+
5049+} /* end kafstimod() */
5050+
5051+/*****************************************************************************/
5052+/*
5053+ * (re-)queue a timer
5054+ */
5055+void afs_kafstimod_add_timer(afs_timer_t *timer, unsigned long timeout)
5056+{
5057+ struct list_head *_p;
5058+ afs_timer_t *ptimer;
5059+
5060+ _enter("%p,%lu",timer,timeout);
5061+
5062+ spin_lock(&kafstimod_lock);
5063+
5064+ list_del(&timer->link);
5065+
5066+ /* the timer was deferred or reset - put it back in the queue at the right place */
5067+ timer->timo_jif = jiffies + timeout;
5068+
5069+ list_for_each(_p,&kafstimod_list) {
5070+ ptimer = list_entry(_p,afs_timer_t,link);
5071+ if (time_before(timer->timo_jif,ptimer->timo_jif))
5072+ break;
5073+ }
5074+
5075+ list_add_tail(&timer->link,_p); /* insert before stopping point */
5076+
5077+ spin_unlock(&kafstimod_lock);
5078+
5079+ wake_up(&kafstimod_sleepq);
5080+
5081+ _leave("");
5082+} /* end afs_kafstimod_queue_vlocation() */
5083+
5084+/*****************************************************************************/
5085+/*
5086+ * dequeue a timer
5087+ * - returns 0 if the timer was deleted or -ENOENT if it wasn't queued
5088+ */
5089+int afs_kafstimod_del_timer(afs_timer_t *timer)
5090+{
5091+ int ret = 0;
5092+
5093+ _enter("%p",timer);
5094+
5095+ spin_lock(&kafstimod_lock);
5096+
5097+ if (list_empty(&timer->link))
5098+ ret = -ENOENT;
5099+ else
5100+ list_del_init(&timer->link);
5101+
5102+ spin_unlock(&kafstimod_lock);
5103+
5104+ wake_up(&kafstimod_sleepq);
5105+
5106+ _leave(" = %d",ret);
5107+ return ret;
5108+} /* end afs_kafstimod_del_timer() */
5109diff -urNp linux-5240/fs/afs/kafstimod.h linux-5250/fs/afs/kafstimod.h
5110--- linux-5240/fs/afs/kafstimod.h 1970-01-01 01:00:00.000000000 +0100
5111+++ linux-5250/fs/afs/kafstimod.h
5112@@ -0,0 +1,45 @@
5113+/* kafstimod.h: AFS timeout daemon
5114+ *
5115+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5116+ * Written by David Howells (dhowells@redhat.com)
5117+ *
5118+ * This program is free software; you can redistribute it and/or
5119+ * modify it under the terms of the GNU General Public License
5120+ * as published by the Free Software Foundation; either version
5121+ * 2 of the License, or (at your option) any later version.
5122+ */
5123+
5124+#ifndef _LINUX_AFS_KAFSTIMOD_H
5125+#define _LINUX_AFS_KAFSTIMOD_H
5126+
5127+#include "types.h"
5128+
5129+struct afs_timer_ops {
5130+ /* called when the front of the timer queue has timed out */
5131+ void (*timed_out)(struct afs_timer *timer);
5132+};
5133+
5134+/*****************************************************************************/
5135+/*
5136+ * AFS timer/timeout record
5137+ */
5138+struct afs_timer
5139+{
5140+ struct list_head link; /* link in timer queue */
5141+ unsigned long timo_jif; /* timeout time */
5142+ const struct afs_timer_ops *ops; /* timeout expiry function */
5143+};
5144+
5145+static inline void afs_timer_init(afs_timer_t *timer, const struct afs_timer_ops *ops)
5146+{
5147+ INIT_LIST_HEAD(&timer->link);
5148+ timer->ops = ops;
5149+}
5150+
5151+extern int afs_kafstimod_start(void);
5152+extern void afs_kafstimod_stop(void);
5153+
5154+extern void afs_kafstimod_add_timer(afs_timer_t *timer, unsigned long timeout);
5155+extern int afs_kafstimod_del_timer(afs_timer_t *timer);
5156+
5157+#endif /* _LINUX_AFS_KAFSTIMOD_H */
5158diff -urNp linux-5240/fs/afs/main.c linux-5250/fs/afs/main.c
5159--- linux-5240/fs/afs/main.c 1970-01-01 01:00:00.000000000 +0100
5160+++ linux-5250/fs/afs/main.c
5161@@ -0,0 +1,193 @@
5162+/* main.c: AFS client file system
5163+ *
5164+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5165+ * Written by David Howells (dhowells@redhat.com)
5166+ *
5167+ * This program is free software; you can redistribute it and/or
5168+ * modify it under the terms of the GNU General Public License
5169+ * as published by the Free Software Foundation; either version
5170+ * 2 of the License, or (at your option) any later version.
5171+ */
5172+
5173+#include <linux/module.h>
5174+#include <linux/init.h>
5175+#include <linux/sched.h>
5176+#include <linux/completion.h>
5177+#include <rxrpc/rxrpc.h>
5178+#include <rxrpc/transport.h>
5179+#include <rxrpc/call.h>
5180+#include <rxrpc/peer.h>
5181+#include "cell.h"
5182+#include "server.h"
5183+#include "fsclient.h"
5184+#include "cmservice.h"
5185+#include "kafstimod.h"
5186+#include "kafsasyncd.h"
5187+#include "internal.h"
5188+
5189+struct rxrpc_transport *afs_transport;
5190+
5191+static int afs_init(void);
5192+static void afs_exit(void);
5193+static int afs_adding_peer(struct rxrpc_peer *peer);
5194+static void afs_discarding_peer(struct rxrpc_peer *peer);
5195+
5196+module_init(afs_init);
5197+module_exit(afs_exit);
5198+
5199+MODULE_DESCRIPTION("AFS Client File System");
5200+MODULE_AUTHOR("Red Hat, Inc.");
5201+MODULE_LICENSE("GPL");
5202+
5203+static struct rxrpc_peer_ops afs_peer_ops = {
5204+ adding: afs_adding_peer,
5205+ discarding: afs_discarding_peer,
5206+};
5207+
5208+struct list_head afs_cb_hash_tbl[AFS_CB_HASH_COUNT];
5209+spinlock_t afs_cb_hash_lock = SPIN_LOCK_UNLOCKED;
5210+
5211+/*****************************************************************************/
5212+/*
5213+ * initialise the AFS client FS module
5214+ */
5215+static int afs_init(void)
5216+{
5217+ int loop, ret;
5218+
5219+ printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 registering.\n");
5220+
5221+ /* initialise the callback hash table */
5222+ spin_lock_init(&afs_cb_hash_lock);
5223+ for (loop=AFS_CB_HASH_COUNT-1; loop>=0; loop--)
5224+ INIT_LIST_HEAD(&afs_cb_hash_tbl[loop]);
5225+
5226+ /* register the /proc stuff */
5227+ ret = afs_proc_init();
5228+ if (ret<0)
5229+ return ret;
5230+
5231+ /* initialise the cell DB */
5232+ ret = afs_cell_init();
5233+ if (ret<0)
5234+ goto error;
5235+
5236+ /* start the timeout daemon */
5237+ ret = afs_kafstimod_start();
5238+ if (ret<0)
5239+ goto error;
5240+
5241+ /* start the async operation daemon */
5242+ ret = afs_kafsasyncd_start();
5243+ if (ret<0)
5244+ goto error_kafstimod;
5245+
5246+ /* create the RxRPC transport */
5247+ ret = rxrpc_create_transport(7001,&afs_transport);
5248+ if (ret<0)
5249+ goto error_kafsasyncd;
5250+
5251+ afs_transport->peer_ops = &afs_peer_ops;
5252+
5253+ /* register the filesystems */
5254+ ret = afs_fs_init();
5255+ if (ret<0)
5256+ goto error_transport;
5257+
5258+ return ret;
5259+
5260+ error_transport:
5261+ rxrpc_put_transport(afs_transport);
5262+ error_kafsasyncd:
5263+ afs_kafsasyncd_stop();
5264+ error_kafstimod:
5265+ afs_kafstimod_stop();
5266+ error:
5267+ afs_cell_purge();
5268+ afs_proc_cleanup();
5269+ printk(KERN_ERR "kAFS: failed to register: %d\n",ret);
5270+ return ret;
5271+} /* end afs_init() */
5272+
5273+/*****************************************************************************/
5274+/*
5275+ * clean up on module removal
5276+ */
5277+static void afs_exit(void)
5278+{
5279+ printk(KERN_INFO "kAFS: Red Hat AFS client v0.1 unregistering.\n");
5280+
5281+ afs_fs_exit();
5282+ rxrpc_put_transport(afs_transport);
5283+ afs_kafstimod_stop();
5284+ afs_kafsasyncd_stop();
5285+ afs_cell_purge();
5286+ afs_proc_cleanup();
5287+
5288+} /* end afs_exit() */
5289+
5290+/*****************************************************************************/
5291+/*
5292+ * notification that new peer record is being added
5293+ * - called from krxsecd
5294+ * - return an error to induce an abort
5295+ * - mustn't sleep (caller holds an rwlock)
5296+ */
5297+static int afs_adding_peer(struct rxrpc_peer *peer)
5298+{
5299+ afs_server_t *server;
5300+ int ret;
5301+
5302+ _debug("kAFS: Adding new peer %08x\n",ntohl(peer->addr.s_addr));
5303+
5304+ /* determine which server the peer resides in (if any) */
5305+ ret = afs_server_find_by_peer(peer,&server);
5306+ if (ret<0)
5307+ return ret; /* none that we recognise, so abort */
5308+
5309+ _debug("Server %p{u=%d}\n",server,atomic_read(&server->usage));
5310+
5311+ _debug("Cell %p{u=%d}\n",server->cell,atomic_read(&server->cell->usage));
5312+
5313+ /* cross-point the structs under a global lock */
5314+ spin_lock(&afs_server_peer_lock);
5315+ peer->user = server;
5316+ server->peer = peer;
5317+ spin_unlock(&afs_server_peer_lock);
5318+
5319+ afs_put_server(server);
5320+
5321+ return 0;
5322+} /* end afs_adding_peer() */
5323+
5324+/*****************************************************************************/
5325+/*
5326+ * notification that a peer record is being discarded
5327+ * - called from krxiod or krxsecd
5328+ */
5329+static void afs_discarding_peer(struct rxrpc_peer *peer)
5330+{
5331+ afs_server_t *server;
5332+
5333+ _enter("%p",peer);
5334+
5335+ _debug("Discarding peer %08x (rtt=%lu.%lumS)\n",
5336+ ntohl(peer->addr.s_addr),
5337+ peer->rtt/1000,
5338+ peer->rtt%1000);
5339+
5340+ /* uncross-point the structs under a global lock */
5341+ spin_lock(&afs_server_peer_lock);
5342+ server = peer->user;
5343+ if (server) {
5344+ peer->user = NULL;
5345+ server->peer = NULL;
5346+
5347+ //_debug("Server %p{u=%d}\n",server,atomic_read(&server->usage));
5348+ //_debug("Cell %p{u=%d}\n",server->cell,atomic_read(&server->cell->usage));
5349+ }
5350+ spin_unlock(&afs_server_peer_lock);
5351+
5352+ _leave("");
5353+
5354+} /* end afs_discarding_peer() */
5355diff -urNp linux-5240/fs/afs/Makefile linux-5250/fs/afs/Makefile
5356--- linux-5240/fs/afs/Makefile 1970-01-01 01:00:00.000000000 +0100
5357+++ linux-5250/fs/afs/Makefile
5358@@ -0,0 +1,34 @@
5359+#
5360+# Makefile for Red Hat Linux AFS client.
5361+#
5362+
5363+kafs-objs := \
5364+ callback.o \
5365+ cell.o \
5366+ cmservice.o \
5367+ dir.o \
5368+ file.o \
5369+ fsclient.o \
5370+ inode.o \
5371+ kafsasyncd.o \
5372+ kafstimod.o \
5373+ main.o \
5374+ misc.o \
5375+ mntpt.o \
5376+ proc.o \
5377+ server.o \
5378+ super.o \
5379+ vlclient.o \
5380+ vlocation.o \
5381+ vnode.o \
5382+ volume.o
5383+
5384+# cache.o
5385+
5386+obj-m := kafs.o
5387+
5388+# superfluous for 2.5, but needed for 2.4..
5389+kafs.o: $(kafs-objs)
5390+ $(LD) -r -o kafs.o $(kafs-objs)
5391+
5392+include $(TOPDIR)/Rules.make
5393diff -urNp linux-5240/fs/afs/misc.c linux-5250/fs/afs/misc.c
5394--- linux-5240/fs/afs/misc.c 1970-01-01 01:00:00.000000000 +0100
5395+++ linux-5250/fs/afs/misc.c
5396@@ -0,0 +1,39 @@
5397+/* misc.c: miscellaneous bits
5398+ *
5399+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5400+ * Written by David Howells (dhowells@redhat.com)
5401+ *
5402+ * This program is free software; you can redistribute it and/or
5403+ * modify it under the terms of the GNU General Public License
5404+ * as published by the Free Software Foundation; either version
5405+ * 2 of the License, or (at your option) any later version.
5406+ */
5407+
5408+#include <linux/kernel.h>
5409+#include <linux/module.h>
5410+#include <linux/errno.h>
5411+#include "errors.h"
5412+#include "internal.h"
5413+
5414+/*****************************************************************************/
5415+/*
5416+ * convert an AFS abort code to a Linux error number
5417+ */
5418+int afs_abort_to_error(int abortcode)
5419+{
5420+ switch (abortcode) {
5421+ case VSALVAGE: return -EIO;
5422+ case VNOVNODE: return -ENOENT;
5423+ case VNOVOL: return -ENXIO;
5424+ case VVOLEXISTS: return -EEXIST;
5425+ case VNOSERVICE: return -EIO;
5426+ case VOFFLINE: return -ENOENT;
5427+ case VONLINE: return -EEXIST;
5428+ case VDISKFULL: return -ENOSPC;
5429+ case VOVERQUOTA: return -EDQUOT;
5430+ case VBUSY: return -EBUSY;
5431+ case VMOVED: return -ENXIO;
5432+ default: return -EIO;
5433+ }
5434+
5435+} /* end afs_abort_to_error() */
5436diff -urNp linux-5240/fs/afs/mntpt.c linux-5250/fs/afs/mntpt.c
5437--- linux-5240/fs/afs/mntpt.c 1970-01-01 01:00:00.000000000 +0100
5438+++ linux-5250/fs/afs/mntpt.c
5439@@ -0,0 +1,114 @@
5440+/* mntpt.c: mountpoint management
5441+ *
5442+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5443+ * Written by David Howells (dhowells@redhat.com)
5444+ *
5445+ * This program is free software; you can redistribute it and/or
5446+ * modify it under the terms of the GNU General Public License
5447+ * as published by the Free Software Foundation; either version
5448+ * 2 of the License, or (at your option) any later version.
5449+ */
5450+
5451+#include <linux/kernel.h>
5452+#include <linux/module.h>
5453+#include <linux/init.h>
5454+#include <linux/sched.h>
5455+#include <linux/slab.h>
5456+#include <linux/fs.h>
5457+#include <linux/pagemap.h>
5458+#include "volume.h"
5459+#include "vnode.h"
5460+#include "cache.h"
5461+#include "internal.h"
5462+
5463+
5464+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry);
5465+static int afs_mntpt_open(struct inode *inode, struct file *file);
5466+//static int afs_mntpt_readlink(struct dentry *dentry, char *buf, int size);
5467+
5468+struct file_operations afs_mntpt_file_operations = {
5469+ open: afs_mntpt_open,
5470+};
5471+
5472+struct inode_operations afs_mntpt_inode_operations = {
5473+ lookup: afs_mntpt_lookup,
5474+ readlink: page_readlink,
5475+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
5476+ getattr: afs_inode_getattr,
5477+#else
5478+ revalidate: afs_inode_revalidate,
5479+#endif
5480+};
5481+
5482+/*****************************************************************************/
5483+/*
5484+ * check a symbolic link to see whether it actually encodes a mountpoint
5485+ * - sets the AFS_VNODE_MOUNTPOINT flag on the vnode appropriately
5486+ */
5487+int afs_mntpt_check_symlink(afs_vnode_t *vnode)
5488+{
5489+ struct page *page;
5490+ size_t size;
5491+ char *buf;
5492+ int ret;
5493+
5494+ _enter("{%u,%u}",vnode->fid.vnode,vnode->fid.unique);
5495+
5496+ /* read the contents of the symlink into the pagecache */
5497+ page = read_cache_page(AFS_VNODE_TO_I(vnode)->i_mapping,0,
5498+ (filler_t*)AFS_VNODE_TO_I(vnode)->i_mapping->a_ops->readpage,NULL);
5499+ if (IS_ERR(page)) {
5500+ ret = PTR_ERR(page);
5501+ goto out;
5502+ }
5503+
5504+ ret = -EIO;
5505+ wait_on_page_locked(page);
5506+ buf = kmap(page);
5507+ if (!PageUptodate(page))
5508+ goto out_free;
5509+ if (PageError(page))
5510+ goto out_free;
5511+
5512+ /* examine the symlink's contents */
5513+ size = vnode->status.size;
5514+ _debug("symlink to %*.*s",size,size,buf);
5515+
5516+ if (size>2 &&
5517+ (buf[0]=='%' || buf[0]=='#') &&
5518+ buf[size-1]=='.'
5519+ ) {
5520+ _debug("symlink is a mountpoint");
5521+ spin_lock(&vnode->lock);
5522+ vnode->flags |= AFS_VNODE_MOUNTPOINT;
5523+ spin_unlock(&vnode->lock);
5524+ }
5525+
5526+ ret = 0;
5527+
5528+ out_free:
5529+ kunmap(page);
5530+ page_cache_release(page);
5531+ out:
5532+ _leave(" = %d",ret);
5533+ return ret;
5534+
5535+} /* end afs_mntpt_check_symlink() */
5536+
5537+/*****************************************************************************/
5538+/*
5539+ * no valid lookup procedure on this sort of dir
5540+ */
5541+static struct dentry *afs_mntpt_lookup(struct inode *dir, struct dentry *dentry)
5542+{
5543+ return ERR_PTR(-EREMOTE);
5544+} /* end afs_mntpt_lookup() */
5545+
5546+/*****************************************************************************/
5547+/*
5548+ * no valid open procedure on this sort of dir
5549+ */
5550+static int afs_mntpt_open(struct inode *inode, struct file *file)
5551+{
5552+ return -EREMOTE;
5553+} /* end afs_mntpt_open() */
5554diff -urNp linux-5240/fs/afs/mount.h linux-5250/fs/afs/mount.h
5555--- linux-5240/fs/afs/mount.h 1970-01-01 01:00:00.000000000 +0100
5556+++ linux-5250/fs/afs/mount.h
5557@@ -0,0 +1,23 @@
5558+/* mount.h: mount parameters
5559+ *
5560+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5561+ * Written by David Howells (dhowells@redhat.com)
5562+ *
5563+ * This program is free software; you can redistribute it and/or
5564+ * modify it under the terms of the GNU General Public License
5565+ * as published by the Free Software Foundation; either version
5566+ * 2 of the License, or (at your option) any later version.
5567+ */
5568+
5569+#ifndef _LINUX_AFS_MOUNT_H
5570+#define _LINUX_AFS_MOUNT_H
5571+
5572+struct afs_mountdata {
5573+ const char *volume; /* name of volume */
5574+ const char *cell; /* name of cell containing volume */
5575+ const char *cache; /* name of cache block device */
5576+ size_t nservers; /* number of server addresses listed */
5577+ u_int32_t servers[10]; /* IP addresses of servers in this cell */
5578+};
5579+
5580+#endif /* _LINUX_AFS_MOUNT_H */
5581diff -urNp linux-5240/fs/afs/proc.c linux-5250/fs/afs/proc.c
5582--- linux-5240/fs/afs/proc.c 1970-01-01 01:00:00.000000000 +0100
5583+++ linux-5250/fs/afs/proc.c
5584@@ -0,0 +1,744 @@
5585+/* proc.c: /proc interface for AFS
5586+ *
5587+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
5588+ * Written by David Howells (dhowells@redhat.com)
5589+ *
5590+ * This program is free software; you can redistribute it and/or
5591+ * modify it under the terms of the GNU General Public License
5592+ * as published by the Free Software Foundation; either version
5593+ * 2 of the License, or (at your option) any later version.
5594+ */
5595+
5596+#include <linux/sched.h>
5597+#include <linux/slab.h>
5598+#include <linux/module.h>
5599+#include <linux/proc_fs.h>
5600+#include <linux/seq_file.h>
5601+#include "cell.h"
5602+#include "volume.h"
5603+#include <asm/uaccess.h>
5604+#include "internal.h"
5605+
5606+static struct proc_dir_entry *proc_afs;
5607+
5608+
5609+static int afs_proc_cells_open(struct inode *inode, struct file *file);
5610+static void *afs_proc_cells_start(struct seq_file *p, loff_t *pos);
5611+static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos);
5612+static void afs_proc_cells_stop(struct seq_file *p, void *v);
5613+static int afs_proc_cells_show(struct seq_file *m, void *v);
5614+static ssize_t afs_proc_cells_write(struct file *file, const char *buf, size_t size, loff_t *_pos);
5615+
5616+static struct seq_operations afs_proc_cells_ops = {
5617+ start: afs_proc_cells_start,
5618+ next: afs_proc_cells_next,
5619+ stop: afs_proc_cells_stop,
5620+ show: afs_proc_cells_show,
5621+};
5622+
5623+static struct file_operations afs_proc_cells_fops = {
5624+ open: afs_proc_cells_open,
5625+ read: seq_read,
5626+ write: afs_proc_cells_write,
5627+ llseek: seq_lseek,
5628+ release: seq_release,
5629+};
5630+
5631+static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file);
5632+static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file);
5633+static void *afs_proc_cell_volumes_start(struct seq_file *p, loff_t *pos);
5634+static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v, loff_t *pos);
5635+static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v);
5636+static int afs_proc_cell_volumes_show(struct seq_file *m, void *v);
5637+
5638+static struct seq_operations afs_proc_cell_volumes_ops = {
5639+ start: afs_proc_cell_volumes_start,
5640+ next: afs_proc_cell_volumes_next,
5641+ stop: afs_proc_cell_volumes_stop,
5642+ show: afs_proc_cell_volumes_show,
5643+};
5644+
5645+static struct file_operations afs_proc_cell_volumes_fops = {
5646+ open: afs_proc_cell_volumes_open,
5647+ read: seq_read,
5648+ llseek: seq_lseek,
5649+ release: afs_proc_cell_volumes_release,
5650+};
5651+
5652+static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file);
5653+static int afs_proc_cell_vlservers_release(struct inode *inode, struct file *file);
5654+static void *afs_proc_cell_vlservers_start(struct seq_file *p, loff_t *pos);
5655+static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v, loff_t *pos);
5656+static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v);
5657+static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v);
5658+
5659+static struct seq_operations afs_proc_cell_vlservers_ops = {
5660+ start: afs_proc_cell_vlservers_start,
5661+ next: afs_proc_cell_vlservers_next,
5662+ stop: afs_proc_cell_vlservers_stop,
5663+ show: afs_proc_cell_vlservers_show,
5664+};
5665+
5666+static struct file_operations afs_proc_cell_vlservers_fops = {
5667+ open: afs_proc_cell_vlservers_open,
5668+ read: seq_read,
5669+ llseek: seq_lseek,
5670+ release: afs_proc_cell_vlservers_release,
5671+};
5672+
5673+static int afs_proc_cell_servers_open(struct inode *inode, struct file *file);
5674+static int afs_proc_cell_servers_release(struct inode *inode, struct file *file);
5675+static void *afs_proc_cell_servers_start(struct seq_file *p, loff_t *pos);
5676+static void *afs_proc_cell_servers_next(struct seq_file *p, void *v, loff_t *pos);
5677+static void afs_proc_cell_servers_stop(struct seq_file *p, void *v);
5678+static int afs_proc_cell_servers_show(struct seq_file *m, void *v);
5679+
5680+static struct seq_operations afs_proc_cell_servers_ops = {
5681+ start: afs_proc_cell_servers_start,
5682+ next: afs_proc_cell_servers_next,
5683+ stop: afs_proc_cell_servers_stop,
5684+ show: afs_proc_cell_servers_show,
5685+};
5686+
5687+static struct file_operations afs_proc_cell_servers_fops = {
5688+ open: afs_proc_cell_servers_open,
5689+ read: seq_read,
5690+ llseek: seq_lseek,
5691+ release: afs_proc_cell_servers_release,
5692+};
5693+
5694+/*****************************************************************************/
5695+/*
5696+ * initialise the /proc/fs/afs/ directory
5697+ */
5698+int afs_proc_init(void)
5699+{
5700+ struct proc_dir_entry *p;
5701+
5702+ _enter("");
5703+
5704+ proc_afs = proc_mkdir("fs/afs",NULL);
5705+ if (!proc_afs)
5706+ goto error;
5707+ proc_afs->owner = THIS_MODULE;
5708+
5709+ p = create_proc_entry("cells",0,proc_afs);
5710+ if (!p)
5711+ goto error_proc;
5712+ p->proc_fops = &afs_proc_cells_fops;
5713+ p->owner = THIS_MODULE;
5714+
5715+ _leave(" = 0");
5716+ return 0;
5717+
5718+#if 0
5719+ error_cells:
5720+ remove_proc_entry("cells",proc_afs);
5721+#endif
5722+ error_proc:
5723+ remove_proc_entry("fs/afs",NULL);
5724+ error:
5725+ _leave(" = -ENOMEM");
5726+ return -ENOMEM;
5727+
5728+} /* end afs_proc_init() */
5729+
5730+/*****************************************************************************/
5731+/*
5732+ * clean up the /proc/fs/afs/ directory
5733+ */
5734+void afs_proc_cleanup(void)
5735+{
5736+ remove_proc_entry("cells",proc_afs);
5737+
5738+ remove_proc_entry("fs/afs",NULL);
5739+
5740+} /* end afs_proc_cleanup() */
5741+
5742+/*****************************************************************************/
5743+/*
5744+ * open "/proc/fs/afs/cells" which provides a summary of extant cells
5745+ */
5746+static int afs_proc_cells_open(struct inode *inode, struct file *file)
5747+{
5748+ struct seq_file *m;
5749+ int ret;
5750+
5751+ ret = seq_open(file,&afs_proc_cells_ops);
5752+ if (ret<0)
5753+ return ret;
5754+
5755+ m = file->private_data;
5756+ m->private = PDE(inode)->data;
5757+
5758+ return 0;
5759+} /* end afs_proc_cells_open() */
5760+
5761+/*****************************************************************************/
5762+/*
5763+ * set up the iterator to start reading from the cells list and return the first item
5764+ */
5765+static void *afs_proc_cells_start(struct seq_file *m, loff_t *_pos)
5766+{
5767+ struct list_head *_p;
5768+ loff_t pos = *_pos;
5769+
5770+ /* lock the list against modification */
5771+ down_read(&afs_proc_cells_sem);
5772+
5773+ /* allow for the header line */
5774+ if (!pos)
5775+ return (void *)1;
5776+ pos--;
5777+
5778+ /* find the n'th element in the list */
5779+ list_for_each(_p,&afs_proc_cells)
5780+ if (!pos--)
5781+ break;
5782+
5783+ return _p!=&afs_proc_cells ? _p : NULL;
5784+} /* end afs_proc_cells_start() */
5785+
5786+/*****************************************************************************/
5787+/*
5788+ * move to next cell in cells list
5789+ */
5790+static void *afs_proc_cells_next(struct seq_file *p, void *v, loff_t *pos)
5791+{
5792+ struct list_head *_p;
5793+
5794+ (*pos)++;
5795+
5796+ _p = v;
5797+ _p = v==(void*)1 ? afs_proc_cells.next : _p->next;
5798+
5799+ return _p!=&afs_proc_cells ? _p : NULL;
5800+} /* end afs_proc_cells_next() */
5801+
5802+/*****************************************************************************/
5803+/*
5804+ * clean up after reading from the cells list
5805+ */
5806+static void afs_proc_cells_stop(struct seq_file *p, void *v)
5807+{
5808+ up_read(&afs_proc_cells_sem);
5809+
5810+} /* end afs_proc_cells_stop() */
5811+
5812+/*****************************************************************************/
5813+/*
5814+ * display a header line followed by a load of cell lines
5815+ */
5816+static int afs_proc_cells_show(struct seq_file *m, void *v)
5817+{
5818+ afs_cell_t *cell = list_entry(v,afs_cell_t,proc_link);
5819+
5820+ /* display header on line 1 */
5821+ if (v == (void *)1) {
5822+ seq_puts(m, "USE IX NAME\n");
5823+ return 0;
5824+ }
5825+
5826+ /* display one cell per line on subsequent lines */
5827+ seq_printf(m,"%3d %3u %s\n",
5828+ atomic_read(&cell->usage),
5829+ cell->cache_ix,
5830+ cell->name
5831+ );
5832+
5833+ return 0;
5834+} /* end afs_proc_cells_show() */
5835+
5836+/*****************************************************************************/
5837+/*
5838+ * handle writes to /proc/fs/afs/cells
5839+ * - to add cells: echo "add <cellname> <IP>[:<IP>][:<IP>]*
5840+ */
5841+static ssize_t afs_proc_cells_write(struct file *file, const char *buf, size_t size, loff_t *_pos)
5842+{
5843+ char *kbuf, *name, *args;
5844+ int ret;
5845+
5846+ /* start by dragging the command into memory */
5847+ if (size<=1 || size>=PAGE_SIZE)
5848+ return -EINVAL;
5849+
5850+ kbuf = kmalloc(size+1,GFP_KERNEL);
5851+ if (!kbuf)
5852+ return -ENOMEM;
5853+
5854+ ret = -EFAULT;
5855+ if (copy_from_user(kbuf,buf,size)!=0)
5856+ goto done;
5857+ kbuf[size] = 0;
5858+
5859+ /* trim to first NL */
5860+ name = memchr(kbuf,'\n',size);
5861+ if (name) *name = 0;
5862+
5863+ /* split into command, name and argslist */
5864+ name = strchr(kbuf,' ');
5865+ if (!name) goto inval;
5866+ do { *name++ = 0; } while(*name==' ');
5867+ if (!*name) goto inval;
5868+
5869+ args = strchr(name,' ');
5870+ if (!args) goto inval;
5871+ do { *args++ = 0; } while(*args==' ');
5872+ if (!*args) goto inval;
5873+
5874+ /* determine command to perform */
5875+ _debug("cmd=%s name=%s args=%s",kbuf,name,args);
5876+
5877+ if (strcmp(kbuf,"add")==0) {
5878+ afs_cell_t *cell;
5879+ ret = afs_cell_create(name,args,&cell);
5880+ if (ret<0)
5881+ goto done;
5882+
5883+ printk("kAFS: Added new cell '%s'\n",name);
5884+ }
5885+ else {
5886+ goto inval;
5887+ }
5888+
5889+ ret = size;
5890+
5891+ done:
5892+ kfree(kbuf);
5893+ _leave(" = %d",ret);
5894+ return ret;
5895+
5896+ inval:
5897+ ret = -EINVAL;
5898+ printk("kAFS: Invalid Command on /proc/fs/afs/cells file\n");
5899+ goto done;
5900+} /* end afs_proc_cells_write() */
5901+
5902+/*****************************************************************************/
5903+/*
5904+ * initialise /proc/fs/afs/<cell>/
5905+ */
5906+int afs_proc_cell_setup(afs_cell_t *cell)
5907+{
5908+ struct proc_dir_entry *p;
5909+
5910+ _enter("%p{%s}",cell,cell->name);
5911+
5912+ cell->proc_dir = proc_mkdir(cell->name,proc_afs);
5913+ if (!cell->proc_dir)
5914+ return -ENOMEM;
5915+
5916+ p = create_proc_entry("servers",0,cell->proc_dir);
5917+ if (!p)
5918+ goto error_proc;
5919+ p->proc_fops = &afs_proc_cell_servers_fops;
5920+ p->owner = THIS_MODULE;
5921+ p->data = cell;
5922+
5923+ p = create_proc_entry("vlservers",0,cell->proc_dir);
5924+ if (!p)
5925+ goto error_servers;
5926+ p->proc_fops = &afs_proc_cell_vlservers_fops;
5927+ p->owner = THIS_MODULE;
5928+ p->data = cell;
5929+
5930+ p = create_proc_entry("volumes",0,cell->proc_dir);
5931+ if (!p)
5932+ goto error_vlservers;
5933+ p->proc_fops = &afs_proc_cell_volumes_fops;
5934+ p->owner = THIS_MODULE;
5935+ p->data = cell;
5936+
5937+ _leave(" = 0");
5938+ return 0;
5939+
5940+ error_vlservers:
5941+ remove_proc_entry("vlservers",cell->proc_dir);
5942+ error_servers:
5943+ remove_proc_entry("servers",cell->proc_dir);
5944+ error_proc:
5945+ remove_proc_entry(cell->name,proc_afs);
5946+ _leave(" = -ENOMEM");
5947+ return -ENOMEM;
5948+} /* end afs_proc_cell_setup() */
5949+
5950+/*****************************************************************************/
5951+/*
5952+ * remove /proc/fs/afs/<cell>/
5953+ */
5954+void afs_proc_cell_remove(afs_cell_t *cell)
5955+{
5956+ _enter("");
5957+
5958+ remove_proc_entry("volumes",cell->proc_dir);
5959+ remove_proc_entry("vlservers",cell->proc_dir);
5960+ remove_proc_entry("servers",cell->proc_dir);
5961+ remove_proc_entry(cell->name,proc_afs);
5962+
5963+ _leave("");
5964+} /* end afs_proc_cell_remove() */
5965+
5966+/*****************************************************************************/
5967+/*
5968+ * open "/proc/fs/afs/<cell>/volumes" which provides a summary of extant cells
5969+ */
5970+static int afs_proc_cell_volumes_open(struct inode *inode, struct file *file)
5971+{
5972+ struct seq_file *m;
5973+ afs_cell_t *cell;
5974+ int ret;
5975+
5976+ cell = afs_get_cell_maybe((afs_cell_t**)&PDE(inode)->data);
5977+ if (!cell)
5978+ return -ENOENT;
5979+
5980+ ret = seq_open(file,&afs_proc_cell_volumes_ops);
5981+ if (ret<0)
5982+ return ret;
5983+
5984+ m = file->private_data;
5985+ m->private = cell;
5986+
5987+ return 0;
5988+} /* end afs_proc_cell_volumes_open() */
5989+
5990+/*****************************************************************************/
5991+/*
5992+ * close the file and release the ref to the cell
5993+ */
5994+static int afs_proc_cell_volumes_release(struct inode *inode, struct file *file)
5995+{
5996+ afs_cell_t *cell = PDE(inode)->data;
5997+ int ret;
5998+
5999+ ret = seq_release(inode,file);
6000+
6001+ afs_put_cell(cell);
6002+
6003+} /* end afs_proc_cell_volumes_release() */
6004+
6005+/*****************************************************************************/
6006+/*
6007+ * set up the iterator to start reading from the cells list and return the first item
6008+ */
6009+static void *afs_proc_cell_volumes_start(struct seq_file *m, loff_t *_pos)
6010+{
6011+ struct list_head *_p;
6012+ afs_cell_t *cell = m->private;
6013+ loff_t pos = *_pos;
6014+
6015+ _enter("cell=%p pos=%Ld",cell,*_pos);
6016+
6017+ /* lock the list against modification */
6018+ down_read(&cell->vl_sem);
6019+
6020+ /* allow for the header line */
6021+ if (!pos)
6022+ return (void *)1;
6023+ pos--;
6024+
6025+ /* find the n'th element in the list */
6026+ list_for_each(_p,&cell->vl_list)
6027+ if (!pos--)
6028+ break;
6029+
6030+ return _p!=&cell->vl_list ? _p : NULL;
6031+} /* end afs_proc_cell_volumes_start() */
6032+
6033+/*****************************************************************************/
6034+/*
6035+ * move to next cell in cells list
6036+ */
6037+static void *afs_proc_cell_volumes_next(struct seq_file *p, void *v, loff_t *_pos)
6038+{
6039+ struct list_head *_p;
6040+ afs_cell_t *cell = p->private;
6041+
6042+ _enter("cell=%p pos=%Ld",cell,*_pos);
6043+
6044+ (*_pos)++;
6045+
6046+ _p = v;
6047+ _p = v==(void*)1 ? cell->vl_list.next : _p->next;
6048+
6049+ return _p!=&cell->vl_list ? _p : NULL;
6050+} /* end afs_proc_cell_volumes_next() */
6051+
6052+/*****************************************************************************/
6053+/*
6054+ * clean up after reading from the cells list
6055+ */
6056+static void afs_proc_cell_volumes_stop(struct seq_file *p, void *v)
6057+{
6058+ afs_cell_t *cell = p->private;
6059+
6060+ up_read(&cell->vl_sem);
6061+
6062+} /* end afs_proc_cell_volumes_stop() */
6063+
6064+/*****************************************************************************/
6065+/*
6066+ * display a header line followed by a load of volume lines
6067+ */
6068+static int afs_proc_cell_volumes_show(struct seq_file *m, void *v)
6069+{
6070+ afs_vlocation_t *vlocation = list_entry(v,afs_vlocation_t,link);
6071+
6072+ /* display header on line 1 */
6073+ if (v == (void *)1) {
6074+ seq_puts(m, "USE IX VLID[0] VLID[1] VLID[2] NAME\n");
6075+ return 0;
6076+ }
6077+
6078+ /* display one cell per line on subsequent lines */
6079+ seq_printf(m,"%3d %3hu %08x %08x %08x %s\n",
6080+ atomic_read(&vlocation->usage),
6081+ vlocation->vix.index,
6082+ vlocation->vldb.vid[0],
6083+ vlocation->vldb.vid[1],
6084+ vlocation->vldb.vid[2],
6085+ vlocation->vldb.name
6086+ );
6087+
6088+ return 0;
6089+} /* end afs_proc_cell_volumes_show() */
6090+
6091+/*****************************************************************************/
6092+/*
6093+ * open "/proc/fs/afs/<cell>/vlservers" which provides a list of volume location server
6094+ */
6095+static int afs_proc_cell_vlservers_open(struct inode *inode, struct file *file)
6096+{
6097+ struct seq_file *m;
6098+ afs_cell_t *cell;
6099+ int ret;
6100+
6101+ cell = afs_get_cell_maybe((afs_cell_t**)&PDE(inode)->data);
6102+ if (!cell)
6103+ return -ENOENT;
6104+
6105+ ret = seq_open(file,&afs_proc_cell_vlservers_ops);
6106+ if (ret<0)
6107+ return ret;
6108+
6109+ m = file->private_data;
6110+ m->private = cell;
6111+
6112+ return 0;
6113+} /* end afs_proc_cell_vlservers_open() */
6114+
6115+/*****************************************************************************/
6116+/*
6117+ * close the file and release the ref to the cell
6118+ */
6119+static int afs_proc_cell_vlservers_release(struct inode *inode, struct file *file)
6120+{
6121+ afs_cell_t *cell = PDE(inode)->data;
6122+ int ret;
6123+
6124+ ret = seq_release(inode,file);
6125+
6126+ afs_put_cell(cell);
6127+
6128+} /* end afs_proc_cell_vlservers_release() */
6129+
6130+/*****************************************************************************/
6131+/*
6132+ * set up the iterator to start reading from the cells list and return the first item
6133+ */
6134+static void *afs_proc_cell_vlservers_start(struct seq_file *m, loff_t *_pos)
6135+{
6136+ afs_cell_t *cell = m->private;
6137+ loff_t pos = *_pos;
6138+
6139+ _enter("cell=%p pos=%Ld",cell,*_pos);
6140+
6141+ /* lock the list against modification */
6142+ down_read(&cell->vl_sem);
6143+
6144+ /* allow for the header line */
6145+ if (!pos)
6146+ return (void *)1;
6147+ pos--;
6148+
6149+ if (pos>=cell->vl_naddrs)
6150+ return NULL;
6151+
6152+ return &cell->vl_addrs[pos];
6153+} /* end afs_proc_cell_vlservers_start() */
6154+
6155+/*****************************************************************************/
6156+/*
6157+ * move to next cell in cells list
6158+ */
6159+static void *afs_proc_cell_vlservers_next(struct seq_file *p, void *v, loff_t *_pos)
6160+{
6161+ afs_cell_t *cell = p->private;
6162+ loff_t pos;
6163+
6164+ _enter("cell=%p{nad=%u} pos=%Ld",cell,cell->vl_naddrs,*_pos);
6165+
6166+ pos = *_pos;
6167+ (*_pos)++;
6168+ if (pos>=cell->vl_naddrs)
6169+ return NULL;
6170+
6171+ return &cell->vl_addrs[pos];
6172+} /* end afs_proc_cell_vlservers_next() */
6173+
6174+/*****************************************************************************/
6175+/*
6176+ * clean up after reading from the cells list
6177+ */
6178+static void afs_proc_cell_vlservers_stop(struct seq_file *p, void *v)
6179+{
6180+ afs_cell_t *cell = p->private;
6181+
6182+ up_read(&cell->vl_sem);
6183+
6184+} /* end afs_proc_cell_vlservers_stop() */
6185+
6186+/*****************************************************************************/
6187+/*
6188+ * display a header line followed by a load of volume lines
6189+ */
6190+static int afs_proc_cell_vlservers_show(struct seq_file *m, void *v)
6191+{
6192+ struct in_addr *addr = v;
6193+
6194+ /* display header on line 1 */
6195+ if (v == (struct in_addr *)1) {
6196+ seq_puts(m,"ADDRESS\n");
6197+ return 0;
6198+ }
6199+
6200+ /* display one cell per line on subsequent lines */
6201+ seq_printf(m,"%u.%u.%u.%u\n",NIPQUAD(addr->s_addr));
6202+
6203+ return 0;
6204+} /* end afs_proc_cell_vlservers_show() */
6205+
6206+/*****************************************************************************/
6207+/*
6208+ * open "/proc/fs/afs/<cell>/servers" which provides a summary of active servers
6209+ */
6210+static int afs_proc_cell_servers_open(struct inode *inode, struct file *file)
6211+{
6212+ struct seq_file *m;
6213+ afs_cell_t *cell;
6214+ int ret;
6215+
6216+ cell = afs_get_cell_maybe((afs_cell_t**)&PDE(inode)->data);
6217+ if (!cell)
6218+ return -ENOENT;
6219+
6220+ ret = seq_open(file,&afs_proc_cell_servers_ops);
6221+ if (ret<0)
6222+ return ret;
6223+
6224+ m = file->private_data;
6225+ m->private = cell;
6226+
6227+ return 0;
6228+} /* end afs_proc_cell_servers_open() */
6229+
6230+/*****************************************************************************/
6231+/*
6232+ * close the file and release the ref to the cell
6233+ */
6234+static int afs_proc_cell_servers_release(struct inode *inode, struct file *file)
6235+{
6236+ afs_cell_t *cell = PDE(inode)->data;
6237+ int ret;
6238+
6239+ ret = seq_release(inode,file);
6240+
6241+ afs_put_cell(cell);
6242+
6243+} /* end afs_proc_cell_servers_release() */
6244+
6245+/*****************************************************************************/
6246+/*
6247+ * set up the iterator to start reading from the cells list and return the first item
6248+ */
6249+static void *afs_proc_cell_servers_start(struct seq_file *m, loff_t *_pos)
6250+{
6251+ struct list_head *_p;
6252+ afs_cell_t *cell = m->private;
6253+ loff_t pos = *_pos;
6254+
6255+ _enter("cell=%p pos=%Ld",cell,*_pos);
6256+
6257+ /* lock the list against modification */
6258+ read_lock(&cell->sv_lock);
6259+
6260+ /* allow for the header line */
6261+ if (!pos)
6262+ return (void *)1;
6263+ pos--;
6264+
6265+ /* find the n'th element in the list */
6266+ list_for_each(_p,&cell->sv_list)
6267+ if (!pos--)
6268+ break;
6269+
6270+ return _p!=&cell->sv_list ? _p : NULL;
6271+} /* end afs_proc_cell_servers_start() */
6272+
6273+/*****************************************************************************/
6274+/*
6275+ * move to next cell in cells list
6276+ */
6277+static void *afs_proc_cell_servers_next(struct seq_file *p, void *v, loff_t *_pos)
6278+{
6279+ struct list_head *_p;
6280+ afs_cell_t *cell = p->private;
6281+
6282+ _enter("cell=%p pos=%Ld",cell,*_pos);
6283+
6284+ (*_pos)++;
6285+
6286+ _p = v;
6287+ _p = v==(void*)1 ? cell->sv_list.next : _p->next;
6288+
6289+ return _p!=&cell->sv_list ? _p : NULL;
6290+} /* end afs_proc_cell_servers_next() */
6291+
6292+/*****************************************************************************/
6293+/*
6294+ * clean up after reading from the cells list
6295+ */
6296+static void afs_proc_cell_servers_stop(struct seq_file *p, void *v)
6297+{
6298+ afs_cell_t *cell = p->private;
6299+
6300+ read_unlock(&cell->sv_lock);
6301+
6302+} /* end afs_proc_cell_servers_stop() */
6303+
6304+/*****************************************************************************/
6305+/*
6306+ * display a header line followed by a load of volume lines
6307+ */
6308+static int afs_proc_cell_servers_show(struct seq_file *m, void *v)
6309+{
6310+ afs_server_t *server = list_entry(v,afs_server_t,link);
6311+ char ipaddr[20];
6312+
6313+ /* display header on line 1 */
6314+ if (v == (void *)1) {
6315+ seq_puts(m, "USE ADDR STATE\n");
6316+ return 0;
6317+ }
6318+
6319+ /* display one cell per line on subsequent lines */
6320+ sprintf(ipaddr,"%u.%u.%u.%u",NIPQUAD(server->addr));
6321+ seq_printf(m,"%3d %-15.15s %5d\n",
6322+ atomic_read(&server->usage),
6323+ ipaddr,
6324+ server->fs_state
6325+ );
6326+
6327+ return 0;
6328+} /* end afs_proc_cell_servers_show() */
6329diff -urNp linux-5240/fs/afs/server.c linux-5250/fs/afs/server.c
6330--- linux-5240/fs/afs/server.c 1970-01-01 01:00:00.000000000 +0100
6331+++ linux-5250/fs/afs/server.c
6332@@ -0,0 +1,490 @@
6333+/* server.c: AFS server record management
6334+ *
6335+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
6336+ * Written by David Howells (dhowells@redhat.com)
6337+ *
6338+ * This program is free software; you can redistribute it and/or
6339+ * modify it under the terms of the GNU General Public License
6340+ * as published by the Free Software Foundation; either version
6341+ * 2 of the License, or (at your option) any later version.
6342+ */
6343+
6344+#include <linux/sched.h>
6345+#include <linux/slab.h>
6346+#include <rxrpc/peer.h>
6347+#include <rxrpc/connection.h>
6348+#include "volume.h"
6349+#include "cell.h"
6350+#include "server.h"
6351+#include "transport.h"
6352+#include "cache.h"
6353+#include "vlclient.h"
6354+#include "kafstimod.h"
6355+#include "internal.h"
6356+
6357+spinlock_t afs_server_peer_lock = SPIN_LOCK_UNLOCKED;
6358+
6359+#define FS_SERVICE_ID 1 /* AFS Volume Location Service ID */
6360+#define VL_SERVICE_ID 52 /* AFS Volume Location Service ID */
6361+
6362+static void __afs_server_timeout(afs_timer_t *timer)
6363+{
6364+ afs_server_t *server = list_entry(timer,afs_server_t,timeout);
6365+
6366+ _debug("SERVER TIMEOUT [%p{u=%d}]",server,atomic_read(&server->usage));
6367+
6368+ afs_server_do_timeout(server);
6369+}
6370+
6371+static const struct afs_timer_ops afs_server_timer_ops = {
6372+ timed_out: __afs_server_timeout,
6373+};
6374+
6375+/*****************************************************************************/
6376+/*
6377+ * lookup a server record in a cell
6378+ * - TODO: search the cell's server list
6379+ */
6380+int afs_server_lookup(afs_cell_t *cell, const struct in_addr *addr, afs_server_t **_server)
6381+{
6382+ struct list_head *_p;
6383+ afs_server_t *server, *active, *zombie;
6384+ int loop;
6385+
6386+ _enter("%p,%08x,",cell,ntohl(addr->s_addr));
6387+
6388+ /* allocate and initialise a server record */
6389+ server = kmalloc(sizeof(afs_server_t),GFP_KERNEL);
6390+ if (!server) {
6391+ _leave(" = -ENOMEM");
6392+ return -ENOMEM;
6393+ }
6394+
6395+ memset(server,0,sizeof(afs_server_t));
6396+ atomic_set(&server->usage,1);
6397+
6398+ INIT_LIST_HEAD(&server->link);
6399+ init_rwsem(&server->sem);
6400+ INIT_LIST_HEAD(&server->fs_callq);
6401+ spin_lock_init(&server->fs_lock);
6402+ INIT_LIST_HEAD(&server->cb_promises);
6403+ spin_lock_init(&server->cb_lock);
6404+
6405+ for (loop=0; loop<AFS_SERVER_CONN_LIST_SIZE; loop++)
6406+ server->fs_conn_cnt[loop] = 4;
6407+
6408+ memcpy(&server->addr,addr,sizeof(struct in_addr));
6409+ server->addr.s_addr = addr->s_addr;
6410+
6411+ afs_timer_init(&server->timeout,&afs_server_timer_ops);
6412+
6413+ /* add to the cell */
6414+ write_lock(&cell->sv_lock);
6415+
6416+ /* check the active list */
6417+ list_for_each(_p,&cell->sv_list) {
6418+ active = list_entry(_p,afs_server_t,link);
6419+
6420+ if (active->addr.s_addr==addr->s_addr)
6421+ goto use_active_server;
6422+ }
6423+
6424+ /* check the inactive list */
6425+ spin_lock(&cell->sv_gylock);
6426+ list_for_each(_p,&cell->sv_graveyard) {
6427+ zombie = list_entry(_p,afs_server_t,link);
6428+
6429+ if (zombie->addr.s_addr==addr->s_addr)
6430+ goto resurrect_server;
6431+ }
6432+ spin_unlock(&cell->sv_gylock);
6433+
6434+ afs_get_cell(cell);
6435+ server->cell = cell;
6436+ list_add_tail(&server->link,&cell->sv_list);
6437+
6438+ write_unlock(&cell->sv_lock);
6439+
6440+ *_server = server;
6441+ _leave(" = 0 (%p)",server);
6442+ return 0;
6443+
6444+ /* found a matching active server */
6445+ use_active_server:
6446+ _debug("active server");
6447+ afs_get_server(active);
6448+ write_unlock(&cell->sv_lock);
6449+
6450+ kfree(server);
6451+
6452+ *_server = active;
6453+ _leave(" = 0 (%p)",active);
6454+ return 0;
6455+
6456+ /* found a matching server in the graveyard, so resurrect it and dispose of the new rec */
6457+ resurrect_server:
6458+ _debug("resurrecting server");
6459+
6460+ list_del(&zombie->link);
6461+ list_add_tail(&zombie->link,&cell->sv_list);
6462+ afs_get_server(zombie);
6463+ afs_kafstimod_del_timer(&zombie->timeout);
6464+ spin_unlock(&cell->sv_gylock);
6465+ write_unlock(&cell->sv_lock);
6466+
6467+ kfree(server);
6468+
6469+ *_server = zombie;
6470+ _leave(" = 0 (%p)",zombie);
6471+ return 0;
6472+
6473+} /* end afs_server_lookup() */
6474+
6475+/*****************************************************************************/
6476+/*
6477+ * destroy a server record
6478+ * - removes from the cell list
6479+ */
6480+void afs_put_server(afs_server_t *server)
6481+{
6482+ afs_cell_t *cell;
6483+
6484+ _enter("%p",server);
6485+
6486+ cell = server->cell;
6487+
6488+ /* sanity check */
6489+ if (atomic_read(&server->usage)<=0)
6490+ BUG();
6491+
6492+ /* to prevent a race, the decrement and the dequeue must be effectively atomic */
6493+ write_lock(&cell->sv_lock);
6494+
6495+ if (likely(!atomic_dec_and_test(&server->usage))) {
6496+ write_unlock(&cell->sv_lock);
6497+ _leave("");
6498+ return;
6499+ }
6500+
6501+ spin_lock(&cell->sv_gylock);
6502+ list_del(&server->link);
6503+ list_add_tail(&server->link,&cell->sv_graveyard);
6504+
6505+ /* time out in 10 secs */
6506+ afs_kafstimod_add_timer(&server->timeout,10*HZ);
6507+
6508+ spin_unlock(&cell->sv_gylock);
6509+ write_unlock(&cell->sv_lock);
6510+
6511+ _leave(" [killed]");
6512+} /* end afs_put_server() */
6513+
6514+/*****************************************************************************/
6515+/*
6516+ * timeout server record
6517+ * - removes from the cell's graveyard if the usage count is zero
6518+ */
6519+void afs_server_do_timeout(afs_server_t *server)
6520+{
6521+ struct rxrpc_peer *peer;
6522+ afs_cell_t *cell;
6523+ int loop;
6524+
6525+ _enter("%p",server);
6526+
6527+ cell = server->cell;
6528+
6529+ if (atomic_read(&server->usage)<0) BUG();
6530+
6531+ /* remove from graveyard if still dead */
6532+ spin_lock(&cell->vl_gylock);
6533+ if (atomic_read(&server->usage)==0)
6534+ list_del_init(&server->link);
6535+ else
6536+ server = NULL;
6537+ spin_unlock(&cell->vl_gylock);
6538+
6539+ if (!server) {
6540+ _leave("");
6541+ return; /* resurrected */
6542+ }
6543+
6544+ /* we can now destroy it properly */
6545+ afs_put_cell(cell);
6546+
6547+ /* uncross-point the structs under a global lock */
6548+ spin_lock(&afs_server_peer_lock);
6549+ peer = server->peer;
6550+ if (peer) {
6551+ server->peer = NULL;
6552+ peer->user = NULL;
6553+ }
6554+ spin_unlock(&afs_server_peer_lock);
6555+
6556+ /* finish cleaning up the server */
6557+ for (loop=AFS_SERVER_CONN_LIST_SIZE-1; loop>=0; loop--)
6558+ if (server->fs_conn[loop])
6559+ rxrpc_put_connection(server->fs_conn[loop]);
6560+
6561+ if (server->vlserver)
6562+ rxrpc_put_connection(server->vlserver);
6563+
6564+ kfree(server);
6565+
6566+ _leave(" [destroyed]");
6567+} /* end afs_server_do_timeout() */
6568+
6569+/*****************************************************************************/
6570+/*
6571+ * get a callslot on a connection to the fileserver on the specified server
6572+ */
6573+int afs_server_request_callslot(afs_server_t *server, struct afs_server_callslot *callslot)
6574+{
6575+ struct afs_server_callslot *pcallslot;
6576+ struct rxrpc_connection *conn;
6577+ int nconn, ret;
6578+
6579+ _enter("%p,",server);
6580+
6581+ INIT_LIST_HEAD(&callslot->link);
6582+ callslot->task = current;
6583+ callslot->conn = NULL;
6584+ callslot->nconn = -1;
6585+ callslot->ready = 0;
6586+
6587+ ret = 0;
6588+ conn = NULL;
6589+
6590+ /* get hold of a callslot first */
6591+ spin_lock(&server->fs_lock);
6592+
6593+ /* resurrect the server if it's death timeout has expired */
6594+ if (server->fs_state) {
6595+ if (time_before(jiffies,server->fs_dead_jif)) {
6596+ ret = server->fs_state;
6597+ spin_unlock(&server->fs_lock);
6598+ _leave(" = %d [still dead]",ret);
6599+ return ret;
6600+ }
6601+
6602+ server->fs_state = 0;
6603+ }
6604+
6605+ /* try and find a connection that has spare callslots */
6606+ for (nconn=0; nconn<AFS_SERVER_CONN_LIST_SIZE; nconn++) {
6607+ if (server->fs_conn_cnt[nconn]>0) {
6608+ server->fs_conn_cnt[nconn]--;
6609+ spin_unlock(&server->fs_lock);
6610+ callslot->nconn = nconn;
6611+ goto obtained_slot;
6612+ }
6613+ }
6614+
6615+ /* none were available - wait interruptibly for one to become available */
6616+ set_current_state(TASK_INTERRUPTIBLE);
6617+ list_add_tail(&callslot->link,&server->fs_callq);
6618+ spin_unlock(&server->fs_lock);
6619+
6620+ while (!callslot->ready && !signal_pending(current)) {
6621+ schedule();
6622+ set_current_state(TASK_INTERRUPTIBLE);
6623+ }
6624+
6625+ set_current_state(TASK_RUNNING);
6626+
6627+ /* even if we were interrupted we may still be queued */
6628+ if (!callslot->ready) {
6629+ spin_lock(&server->fs_lock);
6630+ list_del_init(&callslot->link);
6631+ spin_unlock(&server->fs_lock);
6632+ }
6633+
6634+ nconn = callslot->nconn;
6635+
6636+ /* if interrupted, we must release any slot we also got before returning an error */
6637+ if (signal_pending(current)) {
6638+ ret = -EINTR;
6639+ goto error_release;
6640+ }
6641+
6642+ /* if we were woken up with an error, then pass that error back to the called */
6643+ if (nconn<0) {
6644+ _leave(" = %d",callslot->errno);
6645+ return callslot->errno;
6646+ }
6647+
6648+ /* were we given a connection directly? */
6649+ if (callslot->conn) {
6650+ /* yes - use it */
6651+ _leave(" = 0 (nc=%d)",nconn);
6652+ return 0;
6653+ }
6654+
6655+ /* got a callslot, but no connection */
6656+ obtained_slot:
6657+
6658+ /* need to get hold of the RxRPC connection */
6659+ down_write(&server->sem);
6660+
6661+ /* quick check to see if there's an outstanding error */
6662+ ret = server->fs_state;
6663+ if (ret)
6664+ goto error_release_upw;
6665+
6666+ if (server->fs_conn[nconn]) {
6667+ /* reuse an existing connection */
6668+ rxrpc_get_connection(server->fs_conn[nconn]);
6669+ callslot->conn = server->fs_conn[nconn];
6670+ }
6671+ else {
6672+ /* create a new connection */
6673+ ret = rxrpc_create_connection(afs_transport,
6674+ htons(7000),
6675+ server->addr.s_addr,
6676+ FS_SERVICE_ID,
6677+ NULL,
6678+ &server->fs_conn[nconn]);
6679+
6680+ if (ret<0)
6681+ goto error_release_upw;
6682+
6683+ callslot->conn = server->fs_conn[0];
6684+ rxrpc_get_connection(callslot->conn);
6685+ }
6686+
6687+ up_write(&server->sem);
6688+
6689+ _leave(" = 0");
6690+ return 0;
6691+
6692+ /* handle an error occurring */
6693+ error_release_upw:
6694+ up_write(&server->sem);
6695+
6696+ error_release:
6697+ /* either release the callslot or pass it along to another deserving task */
6698+ spin_lock(&server->fs_lock);
6699+
6700+ if (nconn<0) {
6701+ /* no callslot allocated */
6702+ }
6703+ else if (list_empty(&server->fs_callq)) {
6704+ /* no one waiting */
6705+ server->fs_conn_cnt[nconn]++;
6706+ spin_unlock(&server->fs_lock);
6707+ }
6708+ else {
6709+ /* someone's waiting - dequeue them and wake them up */
6710+ pcallslot = list_entry(server->fs_callq.next,struct afs_server_callslot,link);
6711+ list_del_init(&pcallslot->link);
6712+
6713+ pcallslot->errno = server->fs_state;
6714+ if (!pcallslot->errno) {
6715+ /* pass them out callslot details */
6716+ callslot->conn = xchg(&pcallslot->conn,callslot->conn);
6717+ pcallslot->nconn = nconn;
6718+ callslot->nconn = nconn = -1;
6719+ }
6720+ pcallslot->ready = 1;
6721+ wake_up_process(pcallslot->task);
6722+ spin_unlock(&server->fs_lock);
6723+ }
6724+
6725+ if (callslot->conn) rxrpc_put_connection(callslot->conn);
6726+ callslot->conn = NULL;
6727+
6728+ _leave(" = %d",ret);
6729+ return ret;
6730+
6731+} /* end afs_server_request_callslot() */
6732+
6733+/*****************************************************************************/
6734+/*
6735+ * release a callslot back to the server
6736+ * - transfers the RxRPC connection to the next pending callslot if possible
6737+ */
6738+void afs_server_release_callslot(afs_server_t *server, struct afs_server_callslot *callslot)
6739+{
6740+ struct afs_server_callslot *pcallslot;
6741+
6742+ _enter("{ad=%08x,cnt=%u},{%d}",
6743+ ntohl(server->addr.s_addr),
6744+ server->fs_conn_cnt[callslot->nconn],
6745+ callslot->nconn);
6746+
6747+ if (callslot->nconn<0) BUG();
6748+
6749+ spin_lock(&server->fs_lock);
6750+
6751+ if (list_empty(&server->fs_callq)) {
6752+ /* no one waiting */
6753+ server->fs_conn_cnt[callslot->nconn]++;
6754+ spin_unlock(&server->fs_lock);
6755+ }
6756+ else {
6757+ /* someone's waiting - dequeue them and wake them up */
6758+ pcallslot = list_entry(server->fs_callq.next,struct afs_server_callslot,link);
6759+ list_del_init(&pcallslot->link);
6760+
6761+ pcallslot->errno = server->fs_state;
6762+ if (!pcallslot->errno) {
6763+ /* pass them out callslot details */
6764+ callslot->conn = xchg(&pcallslot->conn,callslot->conn);
6765+ pcallslot->nconn = callslot->nconn;
6766+ callslot->nconn = -1;
6767+ }
6768+
6769+ pcallslot->ready = 1;
6770+ wake_up_process(pcallslot->task);
6771+ spin_unlock(&server->fs_lock);
6772+ }
6773+
6774+ if (callslot->conn) rxrpc_put_connection(callslot->conn);
6775+
6776+ _leave("");
6777+} /* end afs_server_release_callslot() */
6778+
6779+/*****************************************************************************/
6780+/*
6781+ * get a handle to a connection to the vlserver (volume location) on the specified server
6782+ */
6783+int afs_server_get_vlconn(afs_server_t *server, struct rxrpc_connection **_conn)
6784+{
6785+ struct rxrpc_connection *conn;
6786+ int ret;
6787+
6788+ _enter("%p,",server);
6789+
6790+ ret = 0;
6791+ conn = NULL;
6792+ down_read(&server->sem);
6793+
6794+ if (server->vlserver) {
6795+ /* reuse an existing connection */
6796+ rxrpc_get_connection(server->vlserver);
6797+ conn = server->vlserver;
6798+ up_read(&server->sem);
6799+ }
6800+ else {
6801+ /* create a new connection */
6802+ up_read(&server->sem);
6803+ down_write(&server->sem);
6804+ if (!server->vlserver) {
6805+ ret = rxrpc_create_connection(afs_transport,
6806+ htons(7003),
6807+ server->addr.s_addr,
6808+ VL_SERVICE_ID,
6809+ NULL,
6810+ &server->vlserver);
6811+ }
6812+ if (ret==0) {
6813+ rxrpc_get_connection(server->vlserver);
6814+ conn = server->vlserver;
6815+ }
6816+ up_write(&server->sem);
6817+ }
6818+
6819+ *_conn = conn;
6820+ _leave(" = %d",ret);
6821+ return ret;
6822+} /* end afs_server_get_vlconn() */
6823diff -urNp linux-5240/fs/afs/server.h linux-5250/fs/afs/server.h
6824--- linux-5240/fs/afs/server.h 1970-01-01 01:00:00.000000000 +0100
6825+++ linux-5250/fs/afs/server.h
6826@@ -0,0 +1,97 @@
6827+/* server.h: AFS server record
6828+ *
6829+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
6830+ * Written by David Howells (dhowells@redhat.com)
6831+ *
6832+ * This program is free software; you can redistribute it and/or
6833+ * modify it under the terms of the GNU General Public License
6834+ * as published by the Free Software Foundation; either version
6835+ * 2 of the License, or (at your option) any later version.
6836+ */
6837+
6838+#ifndef _LINUX_AFS_SERVER_H
6839+#define _LINUX_AFS_SERVER_H
6840+
6841+#include "types.h"
6842+#include "kafstimod.h"
6843+#include <rxrpc/peer.h>
6844+#include <linux/rwsem.h>
6845+
6846+extern spinlock_t afs_server_peer_lock;
6847+
6848+/*****************************************************************************/
6849+/*
6850+ * AFS server record
6851+ */
6852+struct afs_server
6853+{
6854+ atomic_t usage;
6855+ afs_cell_t *cell; /* cell in which server resides */
6856+ struct list_head link; /* link in cell's server list */
6857+ struct rw_semaphore sem; /* access lock */
6858+ afs_timer_t timeout; /* graveyard timeout */
6859+ struct in_addr addr; /* server address */
6860+ struct rxrpc_peer *peer; /* peer record for this server */
6861+ struct rxrpc_connection *vlserver; /* connection to the volume location service */
6862+
6863+ /* file service access */
6864+#define AFS_SERVER_CONN_LIST_SIZE 2
6865+ struct rxrpc_connection *fs_conn[AFS_SERVER_CONN_LIST_SIZE]; /* FS connections */
6866+ unsigned fs_conn_cnt[AFS_SERVER_CONN_LIST_SIZE]; /* per conn call count */
6867+ struct list_head fs_callq; /* queue of processes waiting to make a call */
6868+ spinlock_t fs_lock; /* access lock */
6869+ int fs_state; /* 0 or reason FS currently marked dead (-errno) */
6870+ unsigned fs_rtt; /* FS round trip time */
6871+ unsigned long fs_act_jif; /* time at which last activity occurred */
6872+ unsigned long fs_dead_jif; /* time at which no longer to be considered dead */
6873+
6874+ /* callback promise management */
6875+ struct list_head cb_promises; /* as yet unbroken promises from this server */
6876+ spinlock_t cb_lock; /* access lock */
6877+};
6878+
6879+extern int afs_server_lookup(afs_cell_t *cell, const struct in_addr *addr, afs_server_t **_server);
6880+
6881+#define afs_get_server(S) do { atomic_inc(&(S)->usage); } while(0)
6882+
6883+extern void afs_put_server(afs_server_t *server);
6884+extern void afs_server_do_timeout(afs_server_t *server);
6885+
6886+extern int afs_server_find_by_peer(const struct rxrpc_peer *peer, afs_server_t **_server);
6887+
6888+extern int afs_server_get_vlconn(afs_server_t *server, struct rxrpc_connection **_conn);
6889+
6890+static inline afs_server_t *afs_server_get_from_peer(struct rxrpc_peer *peer)
6891+{
6892+ afs_server_t *server;
6893+
6894+ spin_lock(&afs_server_peer_lock);
6895+ server = peer->user;
6896+ if (server)
6897+ afs_get_server(server);
6898+ spin_unlock(&afs_server_peer_lock);
6899+
6900+ return server;
6901+}
6902+
6903+/*****************************************************************************/
6904+/*
6905+ * AFS server callslot grant record
6906+ */
6907+struct afs_server_callslot
6908+{
6909+ struct list_head link; /* link in server's list */
6910+ struct task_struct *task; /* process waiting to make call */
6911+ struct rxrpc_connection *conn; /* connection to use (or NULL on error) */
6912+ short nconn; /* connection slot number (-1 on error) */
6913+ char ready; /* T when ready */
6914+ int errno; /* error number if nconn==-1 */
6915+};
6916+
6917+extern int afs_server_request_callslot(afs_server_t *server,
6918+ struct afs_server_callslot *callslot);
6919+
6920+extern void afs_server_release_callslot(afs_server_t *server,
6921+ struct afs_server_callslot *callslot);
6922+
6923+#endif /* _LINUX_AFS_SERVER_H */
6924diff -urNp linux-5240/fs/afs/super.c linux-5250/fs/afs/super.c
6925--- linux-5240/fs/afs/super.c 1970-01-01 01:00:00.000000000 +0100
6926+++ linux-5250/fs/afs/super.c
6927@@ -0,0 +1,609 @@
6928+/*
6929+ * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
6930+ *
6931+ * This software may be freely redistributed under the terms of the
6932+ * GNU General Public License.
6933+ *
6934+ * You should have received a copy of the GNU General Public License
6935+ * along with this program; if not, write to the Free Software
6936+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
6937+ *
6938+ * Authors: David Howells <dhowells@redhat.com>
6939+ * David Woodhouse <dwmw2@cambridge.redhat.com>
6940+ *
6941+ */
6942+
6943+#include <linux/kernel.h>
6944+#include <linux/module.h>
6945+#include <linux/init.h>
6946+#include <linux/slab.h>
6947+#include <linux/fs.h>
6948+#include <linux/pagemap.h>
6949+#include "vnode.h"
6950+#include "volume.h"
6951+#include "cell.h"
6952+#include "cmservice.h"
6953+#include "fsclient.h"
6954+#include "super.h"
6955+#include "cache.h"
6956+#include "internal.h"
6957+
6958+#define AFS_FS_MAGIC 0x6B414653 /* 'kAFS' */
6959+
6960+static inline char *strdup(const char *s)
6961+{
6962+ char *ns = kmalloc(strlen(s)+1,GFP_KERNEL);
6963+ if (ns)
6964+ strcpy(ns,s);
6965+ return ns;
6966+}
6967+
6968+static void afs_i_init_once(void *foo, kmem_cache_t *cachep, unsigned long flags);
6969+
6970+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6971+static struct super_block *afs_get_sb(struct file_system_type *fs_type,
6972+ int flags, char *dev_name, void *data);
6973+#else
6974+static struct super_block *afs_read_super(struct super_block *sb, void *data, int);
6975+static void afs_put_inode(struct inode *inode);
6976+#endif
6977+
6978+static struct inode *afs_alloc_inode(struct super_block *sb);
6979+
6980+static void afs_put_super(struct super_block *sb);
6981+
6982+static void afs_destroy_inode(struct inode *inode);
6983+
6984+static struct file_system_type afs_fs_type = {
6985+ owner: THIS_MODULE,
6986+ name: "afs",
6987+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6988+ get_sb: afs_get_sb,
6989+ kill_sb: kill_anon_super,
6990+#else
6991+ read_super: afs_read_super,
6992+#endif
6993+};
6994+
6995+static struct super_operations afs_super_ops = {
6996+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
6997+ statfs: simple_statfs,
6998+ alloc_inode: afs_alloc_inode,
6999+ drop_inode: generic_delete_inode,
7000+ destroy_inode: afs_destroy_inode,
7001+#else
7002+ put_inode: afs_put_inode,
7003+ read_inode2: afs_read_inode2,
7004+#endif
7005+ clear_inode: afs_clear_inode,
7006+ put_super: afs_put_super,
7007+};
7008+
7009+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7010+static kmem_cache_t *afs_inode_cachep;
7011+#endif
7012+
7013+#if 0
7014+static const char *cachedev;
7015+#endif
7016+static afs_cache_t *afs_cache;
7017+
7018+/*****************************************************************************/
7019+/*
7020+ * initialise the filesystem
7021+ */
7022+int __init afs_fs_init(void)
7023+{
7024+ int ret;
7025+
7026+ /* open the cache */
7027+#if 0
7028+ ret = -EINVAL;
7029+ if (!cachedev) {
7030+ printk(KERN_NOTICE "kAFS: No cache device specified as module parm\n");
7031+ printk(KERN_NOTICE "kAFS: Set with \"cachedev=<devname>\" on insmod's cmdline\n");
7032+ return ret;
7033+ }
7034+
7035+ ret = afs_cache_open(cachedev,&afs_cache);
7036+ if (ret<0) {
7037+ printk(KERN_NOTICE "kAFS: Failed to open cache device\n");
7038+ return ret;
7039+ }
7040+#endif
7041+
7042+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7043+ /* create ourselves an inode cache */
7044+ ret = -ENOMEM;
7045+ afs_inode_cachep = kmem_cache_create("afs_inode_cache",
7046+ sizeof(afs_vnode_t),
7047+ 0,
7048+ SLAB_HWCACHE_ALIGN,
7049+ afs_i_init_once,
7050+ NULL);
7051+ if (!afs_inode_cachep) {
7052+ printk(KERN_NOTICE "kAFS: Failed to allocate inode cache\n");
7053+#if 0
7054+ afs_put_cache(afs_cache);
7055+#endif
7056+ return ret;
7057+ }
7058+#endif
7059+
7060+ /* now export our filesystem to lesser mortals */
7061+ ret = register_filesystem(&afs_fs_type);
7062+ if (ret<0) {
7063+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7064+ kmem_cache_destroy(afs_inode_cachep);
7065+#endif
7066+#if 0
7067+ afs_put_cache(afs_cache);
7068+#endif
7069+ return ret;
7070+ }
7071+
7072+ return 0;
7073+} /* end afs_fs_init() */
7074+
7075+/*****************************************************************************/
7076+/*
7077+ * clean up the filesystem
7078+ */
7079+void __exit afs_fs_exit(void)
7080+{
7081+ /* destroy our private inode cache */
7082+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7083+ kmem_cache_destroy(afs_inode_cachep);
7084+#endif
7085+
7086+ unregister_filesystem(&afs_fs_type);
7087+
7088+#if 0
7089+ if (afs_cache)
7090+ afs_put_cache(afs_cache);
7091+#endif
7092+} /* end afs_fs_exit() */
7093+
7094+/*****************************************************************************/
7095+/*
7096+ * check that an argument has a value
7097+ */
7098+static int want_arg(char **_value, const char *option)
7099+{
7100+ if (!_value || !*_value || !**_value) {
7101+ printk(KERN_NOTICE "kAFS: %s: argument missing\n",option);
7102+ return 0;
7103+ }
7104+ return 1;
7105+} /* end want_arg() */
7106+
7107+/*****************************************************************************/
7108+/*
7109+ * check that there is a value
7110+ */
7111+#if 0
7112+static int want_value(char **_value, const char *option)
7113+{
7114+ if (!_value || !*_value || !**_value) {
7115+ printk(KERN_NOTICE "kAFS: %s: argument incomplete\n",option);
7116+ return 0;
7117+ }
7118+ return 1;
7119+} /* end want_value() */
7120+#endif
7121+
7122+/*****************************************************************************/
7123+/*
7124+ * check that there's no subsequent value
7125+ */
7126+static int want_no_value(char *const *_value, const char *option)
7127+{
7128+ if (*_value && **_value) {
7129+ printk(KERN_NOTICE "kAFS: %s: Invalid argument: %s\n",option,*_value);
7130+ return 0;
7131+ }
7132+ return 1;
7133+} /* end want_no_value() */
7134+
7135+/*****************************************************************************/
7136+/*
7137+ * extract a number from an option string value
7138+ */
7139+#if 0
7140+static int want_number(char **_value, const char *option, unsigned long *number,
7141+ unsigned long limit)
7142+{
7143+ char *value = *_value;
7144+
7145+ if (!want_value(_value,option))
7146+ return 0;
7147+
7148+ *number = simple_strtoul(value,_value,0);
7149+
7150+ if (value==*_value) {
7151+ printk(KERN_NOTICE "kAFS: %s: Invalid number: %s\n",option,value);
7152+ return 0;
7153+ }
7154+
7155+ if (*number>limit) {
7156+ printk(KERN_NOTICE "kAFS: %s: numeric value %lu > %lu\n",option,*number,limit);
7157+ return 0;
7158+ }
7159+
7160+ return 1;
7161+} /* end want_number() */
7162+#endif
7163+
7164+/*****************************************************************************/
7165+/*
7166+ * extract a separator from an option string value
7167+ */
7168+#if 0
7169+static int want_sep(char **_value, const char *option, char sep)
7170+{
7171+ if (!want_value(_value,option))
7172+ return 0;
7173+
7174+ if (*(*_value)++ != sep) {
7175+ printk(KERN_NOTICE "kAFS: %s: '%c' expected: %s\n",option,sep,*_value-1);
7176+ return 0;
7177+ }
7178+
7179+ return 1;
7180+} /* end want_number() */
7181+#endif
7182+
7183+/*****************************************************************************/
7184+/*
7185+ * extract an IP address from an option string value
7186+ */
7187+#if 0
7188+static int want_ipaddr(char **_value, const char *option, struct in_addr *addr)
7189+{
7190+ unsigned long number[4];
7191+
7192+ if (!want_value(_value,option))
7193+ return 0;
7194+
7195+ if (!want_number(_value,option,&number[0],255) ||
7196+ !want_sep(_value,option,'.') ||
7197+ !want_number(_value,option,&number[1],255) ||
7198+ !want_sep(_value,option,'.') ||
7199+ !want_number(_value,option,&number[2],255) ||
7200+ !want_sep(_value,option,'.') ||
7201+ !want_number(_value,option,&number[3],255))
7202+ return 0;
7203+
7204+ ((u8*)addr)[0] = number[0];
7205+ ((u8*)addr)[1] = number[1];
7206+ ((u8*)addr)[2] = number[2];
7207+ ((u8*)addr)[3] = number[3];
7208+
7209+ return 1;
7210+} /* end want_numeric() */
7211+#endif
7212+
7213+/*****************************************************************************/
7214+/*
7215+ * parse the mount options
7216+ * - this function has been shamelessly adapted from the ext3 fs which shamelessly adapted it from
7217+ * the msdos fs
7218+ */
7219+static int afs_super_parse_options(struct afs_super_info *as, char *options, char **devname)
7220+{
7221+ char *key, *value;
7222+ int ret;
7223+
7224+ kenter("%s",options);
7225+
7226+ ret = 0;
7227+ while ((key = strsep(&options,",")))
7228+ {
7229+ value = strchr(key,'=');
7230+ if (value)
7231+ *value++ = 0;
7232+
7233+ printk("kAFS: KEY: %s, VAL:%s\n",key,value?:"-");
7234+
7235+ if (strcmp(key,"rwpath")==0) {
7236+ if (!want_no_value(&value,"rwpath")) return -EINVAL;
7237+ as->rwparent = 1;
7238+ continue;
7239+ }
7240+ else if (strcmp(key,"vol")==0) {
7241+ if (!want_arg(&value,"vol")) return -EINVAL;
7242+ *devname = value;
7243+ continue;
7244+ }
7245+
7246+#if 0
7247+ if (strcmp(key,"servers")==0) {
7248+ if (!want_arg(&value,"servers")) return -EINVAL;
7249+
7250+ _debug("servers=%s",value);
7251+
7252+ for (;;) {
7253+ struct in_addr addr;
7254+
7255+ if (!want_ipaddr(&value,"servers",&addr))
7256+ return -EINVAL;
7257+
7258+ ret = afs_create_server(as->cell,&addr,&as->server);
7259+ if (ret<0) {
7260+ printk("kAFS: unable to create server: %d\n",ret);
7261+ return ret;
7262+ }
7263+
7264+ if (!*value)
7265+ break;
7266+
7267+ if (as->server) {
7268+ printk(KERN_NOTICE
7269+ "kAFS: only one server can be specified\n");
7270+ return -EINVAL;
7271+ }
7272+
7273+ if (!want_sep(&value,"servers",':'))
7274+ return -EINVAL;
7275+ }
7276+ continue;
7277+ }
7278+#endif
7279+
7280+ printk("kAFS: Unknown mount option: '%s'\n",key);
7281+ ret = -EINVAL;
7282+ goto error;
7283+ }
7284+
7285+ ret = 0;
7286+
7287+ error:
7288+ kleave(" = %d",ret);
7289+
7290+ return ret;
7291+} /* end afs_super_parse_options() */
7292+
7293+/*****************************************************************************/
7294+/*
7295+ * fill in the superblock
7296+ */
7297+static int afs_fill_super(struct super_block *sb, void *_data, int silent)
7298+{
7299+ struct afs_super_info *as = NULL;
7300+ struct dentry *root = NULL;
7301+ struct inode *inode = NULL;
7302+ afs_fid_t fid;
7303+ void **data = _data;
7304+ char *options, *devname;
7305+ int ret;
7306+
7307+ kenter("");
7308+
7309+ if (!data) {
7310+ kleave(" = -EINVAL");
7311+ return -EINVAL;
7312+ }
7313+ devname = data[0];
7314+ options = data[1];
7315+ if (options)
7316+ options[PAGE_SIZE-1] = 0;
7317+
7318+ /* allocate a superblock info record */
7319+ as = kmalloc(sizeof(struct afs_super_info),GFP_KERNEL);
7320+ if (!as) {
7321+ kleave(" = -ENOMEM");
7322+ return -ENOMEM;
7323+ }
7324+
7325+ memset(as,0,sizeof(struct afs_super_info));
7326+
7327+ /* parse the options */
7328+ if (options) {
7329+ ret = afs_super_parse_options(as,options,&devname);
7330+ if (ret<0)
7331+ goto error;
7332+ if (!devname) {
7333+ printk("kAFS: no volume name specified\n");
7334+ ret = -EINVAL;
7335+ goto error;
7336+ }
7337+ }
7338+
7339+ /* parse the device name */
7340+ ret = afs_volume_lookup(afs_cache,devname,as->rwparent,&as->volume);
7341+ if (ret<0)
7342+ goto error;
7343+
7344+ /* fill in the superblock */
7345+ sb->s_blocksize = PAGE_CACHE_SIZE;
7346+ sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
7347+ sb->s_magic = AFS_FS_MAGIC;
7348+ sb->s_op = &afs_super_ops;
7349+ sb->u.generic_sbp = as;
7350+
7351+ /* allocate the root inode and dentry */
7352+ fid.vid = as->volume->vid;
7353+ fid.vnode = 1;
7354+ fid.unique = 1;
7355+ ret = afs_iget(sb,&fid,&inode);
7356+ if (ret<0)
7357+ goto error;
7358+
7359+ ret = -ENOMEM;
7360+ root = d_alloc_root(inode);
7361+ if (!root)
7362+ goto error;
7363+
7364+ sb->s_root = root;
7365+
7366+ kleave(" = 0");
7367+ return 0;
7368+
7369+ error:
7370+ if (root) dput(root);
7371+ if (inode) iput(inode);
7372+ if (as) {
7373+ if (as->volume) afs_put_volume(as->volume);
7374+ kfree(as);
7375+ }
7376+ sb->u.generic_sbp = NULL;
7377+
7378+ kleave(" = %d",ret);
7379+ return ret;
7380+} /* end afs_fill_super() */
7381+
7382+/*****************************************************************************/
7383+/*
7384+ * get an AFS superblock
7385+ * - TODO: don't use get_sb_nodev(), but rather call sget() directly
7386+ */
7387+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7388+static struct super_block *afs_get_sb(struct file_system_type *fs_type,
7389+ int flags,
7390+ char *dev_name,
7391+ void *options)
7392+{
7393+ struct super_block *sb;
7394+ void *data[2] = { dev_name, options };
7395+ int ret;
7396+
7397+ _enter(",,%s,%p",dev_name,options);
7398+
7399+ /* start the cache manager */
7400+ ret = afscm_start();
7401+ if (ret<0) {
7402+ _leave(" = %d",ret);
7403+ return ERR_PTR(ret);
7404+ }
7405+
7406+ /* allocate a deviceless superblock */
7407+ sb = get_sb_nodev(fs_type,flags,data,afs_fill_super);
7408+ if (IS_ERR(sb)) {
7409+ afscm_stop();
7410+ return sb;
7411+ }
7412+
7413+ _leave("");
7414+ return sb;
7415+} /* end afs_get_sb() */
7416+#endif
7417+
7418+/*****************************************************************************/
7419+/*
7420+ * read an AFS superblock
7421+ */
7422+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
7423+static struct super_block *afs_read_super(struct super_block *sb, void *options, int silent)
7424+{
7425+ void *data[2] = { NULL, options };
7426+ int ret;
7427+
7428+ kenter(",,%s",(char*)options);
7429+
7430+ /* start the cache manager */
7431+ ret = afscm_start();
7432+ if (ret<0) {
7433+ kleave(" = NULL (%d)",ret);
7434+ return NULL;
7435+ }
7436+
7437+ /* allocate a deviceless superblock */
7438+ ret = afs_fill_super(sb,data,silent);
7439+ if (ret<0) {
7440+ afscm_stop();
7441+ kleave(" = NULL (%d)",ret);
7442+ return NULL;
7443+ }
7444+
7445+ kleave(" = %p",sb);
7446+ return sb;
7447+} /* end afs_read_super() */
7448+#endif
7449+
7450+/*****************************************************************************/
7451+/*
7452+ * finish the unmounting process on the superblock
7453+ */
7454+static void afs_put_super(struct super_block *sb)
7455+{
7456+ struct afs_super_info *as = sb->u.generic_sbp;
7457+
7458+ _enter("");
7459+
7460+ if (as) {
7461+ if (as->volume) afs_put_volume(as->volume);
7462+ }
7463+
7464+ /* stop the cache manager */
7465+ afscm_stop();
7466+
7467+ _leave("");
7468+} /* end afs_put_super() */
7469+
7470+/*****************************************************************************/
7471+/*
7472+ * initialise an inode cache slab element prior to any use
7473+ */
7474+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7475+static void afs_i_init_once(void *_vnode, kmem_cache_t *cachep, unsigned long flags)
7476+{
7477+ afs_vnode_t *vnode = (afs_vnode_t *) _vnode;
7478+
7479+ if ((flags & (SLAB_CTOR_VERIFY|SLAB_CTOR_CONSTRUCTOR)) == SLAB_CTOR_CONSTRUCTOR) {
7480+ memset(vnode,0,sizeof(*vnode));
7481+ inode_init_once(&vnode->vfs_inode);
7482+ init_waitqueue_head(&vnode->update_waitq);
7483+ spin_lock_init(&vnode->lock);
7484+ INIT_LIST_HEAD(&vnode->cb_link);
7485+ INIT_LIST_HEAD(&vnode->cb_hash_link);
7486+ afs_timer_init(&vnode->cb_timeout,&afs_vnode_cb_timed_out_ops);
7487+ }
7488+
7489+} /* end afs_i_init_once() */
7490+#endif
7491+
7492+/*****************************************************************************/
7493+/*
7494+ * allocate an AFS inode struct from our slab cache
7495+ */
7496+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7497+static struct inode *afs_alloc_inode(struct super_block *sb)
7498+{
7499+ afs_vnode_t *vnode;
7500+
7501+ vnode = (afs_vnode_t *) kmem_cache_alloc(afs_inode_cachep,SLAB_KERNEL);
7502+ if (!vnode)
7503+ return NULL;
7504+
7505+ memset(&vnode->fid,0,sizeof(vnode->fid));
7506+ memset(&vnode->status,0,sizeof(vnode->status));
7507+
7508+ vnode->volume = NULL;
7509+ vnode->update_cnt = 0;
7510+ vnode->flags = 0;
7511+
7512+ return &vnode->vfs_inode;
7513+} /* end afs_alloc_inode() */
7514+#endif
7515+
7516+/*****************************************************************************/
7517+/*
7518+ * put an inode
7519+ */
7520+static void afs_put_inode(struct inode *inode)
7521+{
7522+ if (inode->u.generic_ip) kfree(inode->u.generic_ip);
7523+
7524+} /* end afs_put_inode() */
7525+
7526+/*****************************************************************************/
7527+/*
7528+ * destroy an AFS inode struct
7529+ */
7530+#if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)
7531+static void afs_destroy_inode(struct inode *inode)
7532+{
7533+ _enter("{%lu}",inode->i_ino);
7534+ kmem_cache_free(afs_inode_cachep, AFS_FS_I(inode));
7535+} /* end afs_destroy_inode() */
7536+#endif
7537diff -urNp linux-5240/fs/afs/super.h linux-5250/fs/afs/super.h
7538--- linux-5240/fs/afs/super.h 1970-01-01 01:00:00.000000000 +0100
7539+++ linux-5250/fs/afs/super.h
7540@@ -0,0 +1,43 @@
7541+/* super.h: AFS filesystem internal private data
7542+ *
7543+ * Copyright (c) 2002 Red Hat, Inc. All rights reserved.
7544+ *
7545+ * This software may be freely redistributed under the terms of the
7546+ * GNU General Public License.
7547+ *
7548+ * You should have received a copy of the GNU General Public License
7549+ * along with this program; if not, write to the Free Software
7550+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
7551+ *
7552+ * Authors: David Woodhouse <dwmw2@cambridge.redhat.com>
7553+ * David Howells <dhowells@redhat.com>
7554+ *
7555+ */
7556+
7557+#ifndef _LINUX_AFS_SUPER_H
7558+#define _LINUX_AFS_SUPER_H
7559+
7560+#include <linux/fs.h>
7561+#include "server.h"
7562+
7563+#ifdef __KERNEL__
7564+
7565+/*****************************************************************************/
7566+/*
7567+ * AFS superblock private data
7568+ * - there's one superblock per volume
7569+ */
7570+struct afs_super_info
7571+{
7572+ afs_volume_t *volume; /* volume record */
7573+ char rwparent; /* T if parent is R/W AFS volume */
7574+};
7575+
7576+static inline struct afs_super_info *AFS_FS_S(struct super_block *sb)
7577+{
7578+ return sb->u.generic_sbp;
7579+}
7580+
7581+#endif /* __KERNEL__ */
7582+
7583+#endif /* _LINUX_AFS_SUPER_H */
7584diff -urNp linux-5240/fs/afs/transport.h linux-5250/fs/afs/transport.h
7585--- linux-5240/fs/afs/transport.h 1970-01-01 01:00:00.000000000 +0100
7586+++ linux-5250/fs/afs/transport.h
7587@@ -0,0 +1,21 @@
7588+/* transport.h: AFS transport management
7589+ *
7590+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
7591+ * Written by David Howells (dhowells@redhat.com)
7592+ *
7593+ * This program is free software; you can redistribute it and/or
7594+ * modify it under the terms of the GNU General Public License
7595+ * as published by the Free Software Foundation; either version
7596+ * 2 of the License, or (at your option) any later version.
7597+ */
7598+
7599+#ifndef _LINUX_AFS_TRANSPORT_H
7600+#define _LINUX_AFS_TRANSPORT_H
7601+
7602+#include "types.h"
7603+#include <rxrpc/transport.h>
7604+
7605+/* the cache manager transport endpoint */
7606+extern struct rxrpc_transport *afs_transport;
7607+
7608+#endif /* _LINUX_AFS_TRANSPORT_H */
7609diff -urNp linux-5240/fs/afs/types.h linux-5250/fs/afs/types.h
7610--- linux-5240/fs/afs/types.h 1970-01-01 01:00:00.000000000 +0100
7611+++ linux-5250/fs/afs/types.h
7612@@ -0,0 +1,141 @@
7613+/* types.h: AFS types
7614+ *
7615+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
7616+ * Written by David Howells (dhowells@redhat.com)
7617+ *
7618+ * This program is free software; you can redistribute it and/or
7619+ * modify it under the terms of the GNU General Public License
7620+ * as published by the Free Software Foundation; either version
7621+ * 2 of the License, or (at your option) any later version.
7622+ */
7623+
7624+#ifndef _LINUX_AFS_TYPES_H
7625+#define _LINUX_AFS_TYPES_H
7626+
7627+#ifdef __KERNEL__
7628+#include <rxrpc/types.h>
7629+#endif /* __KERNEL__ */
7630+
7631+typedef unsigned afs_volid_t;
7632+typedef unsigned afs_vnodeid_t;
7633+typedef unsigned long long afs_dataversion_t;
7634+
7635+typedef struct afs_async_op afs_async_op_t;
7636+typedef struct afs_cache afs_cache_t;
7637+typedef struct afs_cache_volindex afs_cache_volindex_t;
7638+typedef struct afs_callback afs_callback_t;
7639+typedef struct afs_cell afs_cell_t;
7640+typedef struct afs_fid afs_fid_t;
7641+typedef struct afs_file_status afs_file_status_t;
7642+typedef struct afs_server afs_server_t;
7643+typedef struct afs_timer afs_timer_t;
7644+typedef struct afs_vlocation afs_vlocation_t;
7645+typedef struct afs_vnode afs_vnode_t;
7646+typedef struct afs_volsync afs_volsync_t;
7647+typedef struct afs_volume afs_volume_t;
7648+typedef struct afs_volume_info afs_volume_info_t;
7649+
7650+typedef struct afsvl_dbentry afsvl_dbentry_t;
7651+
7652+typedef enum {
7653+ AFSVL_RWVOL, /* read/write volume */
7654+ AFSVL_ROVOL, /* read-only volume */
7655+ AFSVL_BACKVOL, /* backup volume */
7656+} afs_voltype_t;
7657+
7658+extern const char *afs_voltypes[];
7659+
7660+typedef enum {
7661+ AFS_FTYPE_INVALID = 0,
7662+ AFS_FTYPE_FILE = 1,
7663+ AFS_FTYPE_DIR = 2,
7664+ AFS_FTYPE_SYMLINK = 3,
7665+} afs_file_type_t;
7666+
7667+#ifdef __KERNEL__
7668+
7669+/*****************************************************************************/
7670+/*
7671+ * AFS file identifier
7672+ */
7673+struct afs_fid
7674+{
7675+ afs_volid_t vid; /* volume ID */
7676+ afs_vnodeid_t vnode; /* file index within volume */
7677+ unsigned unique; /* unique ID number (file index version) */
7678+};
7679+
7680+/*****************************************************************************/
7681+/*
7682+ * AFS callback notification
7683+ */
7684+typedef enum {
7685+ AFSCM_CB_UNTYPED = 0, /* no type set on CB break */
7686+ AFSCM_CB_EXCLUSIVE = 1, /* CB exclusive to CM [not implemented] */
7687+ AFSCM_CB_SHARED = 2, /* CB shared by other CM's */
7688+ AFSCM_CB_DROPPED = 3, /* CB promise cancelled by file server */
7689+} afs_callback_type_t;
7690+
7691+struct afs_callback
7692+{
7693+ afs_server_t *server; /* server that made the promise */
7694+ afs_fid_t fid; /* file identifier */
7695+ unsigned version; /* callback version */
7696+ unsigned expiry; /* time at which expires */
7697+ afs_callback_type_t type; /* type of callback */
7698+};
7699+
7700+#define AFSCBMAX 50
7701+
7702+/*****************************************************************************/
7703+/*
7704+ * AFS volume information
7705+ */
7706+struct afs_volume_info
7707+{
7708+ afs_volid_t vid; /* volume ID */
7709+ afs_voltype_t type; /* type of this volume */
7710+ afs_volid_t type_vids[5]; /* volume ID's for possible types for this vol */
7711+
7712+ /* list of fileservers serving this volume */
7713+ size_t nservers; /* number of entries used in servers[] */
7714+ struct {
7715+ struct in_addr addr; /* fileserver address */
7716+ } servers[8];
7717+};
7718+
7719+/*****************************************************************************/
7720+/*
7721+ * AFS file status information
7722+ */
7723+struct afs_file_status
7724+{
7725+ unsigned if_version; /* interface version */
7726+#define AFS_FSTATUS_VERSION 1
7727+
7728+ afs_file_type_t type; /* file type */
7729+ unsigned nlink; /* link count */
7730+ size_t size; /* file size */
7731+ afs_dataversion_t version; /* current data version */
7732+ unsigned author; /* author ID */
7733+ unsigned owner; /* owner ID */
7734+ unsigned caller_access; /* access rights for authenticated caller */
7735+ unsigned anon_access; /* access rights for unauthenticated caller */
7736+ umode_t mode; /* UNIX mode */
7737+ afs_fid_t parent; /* parent file ID */
7738+ time_t mtime_client; /* last time client changed data */
7739+ time_t mtime_server; /* last time server changed data */
7740+};
7741+
7742+/*****************************************************************************/
7743+/*
7744+ * AFS volume synchronisation information
7745+ */
7746+struct afs_volsync
7747+{
7748+ time_t creation; /* volume creation time */
7749+};
7750+
7751+#endif /* __KERNEL__ */
7752+
7753+#endif /* _LINUX_AFS_TYPES_H */
7754diff -urNp linux-5240/fs/afs/vlclient.c linux-5250/fs/afs/vlclient.c
7755--- linux-5240/fs/afs/vlclient.c 1970-01-01 01:00:00.000000000 +0100
7756+++ linux-5250/fs/afs/vlclient.c
7757@@ -0,0 +1,661 @@
7758+/* vlclient.c: AFS Volume Location Service client
7759+ *
7760+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
7761+ * Written by David Howells (dhowells@redhat.com)
7762+ *
7763+ * This program is free software; you can redistribute it and/or
7764+ * modify it under the terms of the GNU General Public License
7765+ * as published by the Free Software Foundation; either version
7766+ * 2 of the License, or (at your option) any later version.
7767+ */
7768+
7769+#include <linux/init.h>
7770+#include <linux/sched.h>
7771+#include <rxrpc/rxrpc.h>
7772+#include <rxrpc/transport.h>
7773+#include <rxrpc/connection.h>
7774+#include <rxrpc/call.h>
7775+#include "server.h"
7776+#include "vlclient.h"
7777+#include "kafsasyncd.h"
7778+#include "kafstimod.h"
7779+#include "errors.h"
7780+#include "internal.h"
7781+
7782+#define VLGETENTRYBYID 503 /* AFS Get Cache Entry By ID operation ID */
7783+#define VLGETENTRYBYNAME 504 /* AFS Get Cache Entry By Name operation ID */
7784+#define VLPROBE 514 /* AFS Probe Volume Location Service operation ID */
7785+
7786+static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call);
7787+static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call);
7788+
7789+/*****************************************************************************/
7790+/*
7791+ * map afs VL abort codes to/from Linux error codes
7792+ * - called with call->lock held
7793+ */
7794+static void afs_rxvl_aemap(struct rxrpc_call *call)
7795+{
7796+ int err;
7797+
7798+ _enter("{%u,%u,%d}",call->app_err_state,call->app_abort_code,call->app_errno);
7799+
7800+ switch (call->app_err_state) {
7801+ case RXRPC_ESTATE_LOCAL_ABORT:
7802+ call->app_abort_code = -call->app_errno;
7803+ return;
7804+
7805+ case RXRPC_ESTATE_PEER_ABORT:
7806+ switch (call->app_abort_code) {
7807+ case AFSVL_IDEXIST: err = -EEXIST; break;
7808+ case AFSVL_IO: err = -EREMOTEIO; break;
7809+ case AFSVL_NAMEEXIST: err = -EEXIST; break;
7810+ case AFSVL_CREATEFAIL: err = -EREMOTEIO; break;
7811+ case AFSVL_NOENT: err = -ENOMEDIUM; break;
7812+ case AFSVL_EMPTY: err = -ENOMEDIUM; break;
7813+ case AFSVL_ENTDELETED: err = -ENOMEDIUM; break;
7814+ case AFSVL_BADNAME: err = -EINVAL; break;
7815+ case AFSVL_BADINDEX: err = -EINVAL; break;
7816+ case AFSVL_BADVOLTYPE: err = -EINVAL; break;
7817+ case AFSVL_BADSERVER: err = -EINVAL; break;
7818+ case AFSVL_BADPARTITION: err = -EINVAL; break;
7819+ case AFSVL_REPSFULL: err = -EFBIG; break;
7820+ case AFSVL_NOREPSERVER: err = -ENOENT; break;
7821+ case AFSVL_DUPREPSERVER: err = -EEXIST; break;
7822+ case AFSVL_RWNOTFOUND: err = -ENOENT; break;
7823+ case AFSVL_BADREFCOUNT: err = -EINVAL; break;
7824+ case AFSVL_SIZEEXCEEDED: err = -EINVAL; break;
7825+ case AFSVL_BADENTRY: err = -EINVAL; break;
7826+ case AFSVL_BADVOLIDBUMP: err = -EINVAL; break;
7827+ case AFSVL_IDALREADYHASHED: err = -EINVAL; break;
7828+ case AFSVL_ENTRYLOCKED: err = -EBUSY; break;
7829+ case AFSVL_BADVOLOPER: err = -EBADRQC; break;
7830+ case AFSVL_BADRELLOCKTYPE: err = -EINVAL; break;
7831+ case AFSVL_RERELEASE: err = -EREMOTEIO; break;
7832+ case AFSVL_BADSERVERFLAG: err = -EINVAL; break;
7833+ case AFSVL_PERM: err = -EACCES; break;
7834+ case AFSVL_NOMEM: err = -EREMOTEIO; break;
7835+ default:
7836+ err = afs_abort_to_error(call->app_abort_code);
7837+ break;
7838+ }
7839+ call->app_errno = err;
7840+ return;
7841+
7842+ default:
7843+ return;
7844+ }
7845+} /* end afs_rxvl_aemap() */
7846+
7847+/*****************************************************************************/
7848+/*
7849+ * probe a volume location server to see if it is still alive
7850+ */
7851+int afs_rxvl_probe(afs_server_t *server, int alloc_flags)
7852+{
7853+ DECLARE_WAITQUEUE(myself,current);
7854+
7855+ struct rxrpc_connection *conn;
7856+ struct rxrpc_call *call;
7857+ struct iovec piov[1];
7858+ size_t sent;
7859+ int ret;
7860+ u32 param[1];
7861+
7862+ /* get hold of the vlserver connection */
7863+ ret = afs_server_get_vlconn(server,&conn);
7864+ if (ret<0)
7865+ goto out;
7866+
7867+ /* create a call through that connection */
7868+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxvl_aemap,&call);
7869+ if (ret<0) {
7870+ printk("kAFS: Unable to create call: %d\n",ret);
7871+ goto out_put_conn;
7872+ }
7873+ call->app_opcode = VLPROBE;
7874+
7875+ /* we want to get event notifications from the call */
7876+ add_wait_queue(&call->waitq,&myself);
7877+
7878+ /* marshall the parameters */
7879+ param[0] = htonl(VLPROBE);
7880+ piov[0].iov_len = sizeof(param);
7881+ piov[0].iov_base = param;
7882+
7883+ /* send the parameters to the server */
7884+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,alloc_flags,0,&sent);
7885+ if (ret<0)
7886+ goto abort;
7887+
7888+ /* wait for the reply to completely arrive */
7889+ for (;;) {
7890+ set_current_state(TASK_INTERRUPTIBLE);
7891+ if (call->app_call_state!=RXRPC_CSTATE_CLNT_RCV_REPLY ||
7892+ signal_pending(current))
7893+ break;
7894+ schedule();
7895+ }
7896+ set_current_state(TASK_RUNNING);
7897+
7898+ ret = -EINTR;
7899+ if (signal_pending(current))
7900+ goto abort;
7901+
7902+ switch (call->app_call_state) {
7903+ case RXRPC_CSTATE_ERROR:
7904+ ret = call->app_errno;
7905+ goto out_unwait;
7906+
7907+ case RXRPC_CSTATE_CLNT_GOT_REPLY:
7908+ ret = 0;
7909+ goto out_unwait;
7910+
7911+ default:
7912+ BUG();
7913+ }
7914+
7915+ abort:
7916+ set_current_state(TASK_UNINTERRUPTIBLE);
7917+ rxrpc_call_abort(call,ret);
7918+ schedule();
7919+
7920+ out_unwait:
7921+ set_current_state(TASK_RUNNING);
7922+ remove_wait_queue(&call->waitq,&myself);
7923+ rxrpc_put_call(call);
7924+ out_put_conn:
7925+ rxrpc_put_connection(conn);
7926+ out:
7927+ return ret;
7928+
7929+} /* end afs_rxvl_probe() */
7930+
7931+/*****************************************************************************/
7932+/*
7933+ * look up a volume location database entry by name
7934+ */
7935+int afs_rxvl_get_entry_by_name(afs_server_t *server, const char *volname,
7936+ struct afs_cache_volume *entry)
7937+{
7938+ DECLARE_WAITQUEUE(myself,current);
7939+
7940+ struct rxrpc_connection *conn;
7941+ struct rxrpc_call *call;
7942+ struct iovec piov[3];
7943+ unsigned tmp;
7944+ size_t sent;
7945+ int ret, loop;
7946+ u32 *bp, param[2], zero;
7947+
7948+ _enter(",%s,",volname);
7949+
7950+ memset(entry,0,sizeof(*entry));
7951+
7952+ /* get hold of the vlserver connection */
7953+ ret = afs_server_get_vlconn(server,&conn);
7954+ if (ret<0)
7955+ goto out;
7956+
7957+ /* create a call through that connection */
7958+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxvl_aemap,&call);
7959+ if (ret<0) {
7960+ printk("kAFS: Unable to create call: %d\n",ret);
7961+ goto out_put_conn;
7962+ }
7963+ call->app_opcode = VLGETENTRYBYNAME;
7964+
7965+ /* we want to get event notifications from the call */
7966+ add_wait_queue(&call->waitq,&myself);
7967+
7968+ /* marshall the parameters */
7969+ piov[1].iov_len = strlen(volname);
7970+ piov[1].iov_base = (char*)volname;
7971+
7972+ zero = 0;
7973+ piov[2].iov_len = (4 - (piov[1].iov_len & 3)) & 3;
7974+ piov[2].iov_base = &zero;
7975+
7976+ param[0] = htonl(VLGETENTRYBYNAME);
7977+ param[1] = htonl(piov[1].iov_len);
7978+
7979+ piov[0].iov_len = sizeof(param);
7980+ piov[0].iov_base = param;
7981+
7982+ /* send the parameters to the server */
7983+ ret = rxrpc_call_write_data(call,3,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
7984+ if (ret<0)
7985+ goto abort;
7986+
7987+ /* wait for the reply to completely arrive */
7988+ bp = rxrpc_call_alloc_scratch(call,384);
7989+
7990+ ret = rxrpc_call_read_data(call,bp,384,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
7991+ if (ret<0) {
7992+ if (ret==-ECONNABORTED) {
7993+ ret = call->app_errno;
7994+ goto out_unwait;
7995+ }
7996+ goto abort;
7997+ }
7998+
7999+ /* unmarshall the reply */
8000+ for (loop=0; loop<64; loop++)
8001+ entry->name[loop] = ntohl(*bp++);
8002+ bp++; /* final NUL */
8003+
8004+ bp++; /* type */
8005+ entry->nservers = ntohl(*bp++);
8006+
8007+ for (loop=0; loop<8; loop++)
8008+ entry->servers[loop].s_addr = *bp++;
8009+
8010+ bp += 8; /* partition IDs */
8011+
8012+ for (loop=0; loop<8; loop++) {
8013+ tmp = ntohl(*bp++);
8014+ if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RW;
8015+ if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RO;
8016+ if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_BAK;
8017+ }
8018+
8019+ entry->vid[0] = ntohl(*bp++);
8020+ entry->vid[1] = ntohl(*bp++);
8021+ entry->vid[2] = ntohl(*bp++);
8022+
8023+ bp++; /* clone ID */
8024+
8025+ tmp = ntohl(*bp++); /* flags */
8026+ if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RW;
8027+ if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RO;
8028+ if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_CACHE_VOL_STM_BAK;
8029+
8030+ ret = -ENOMEDIUM;
8031+ if (!entry->vidmask)
8032+ goto abort;
8033+
8034+ /* success */
8035+ entry->ctime = xtime.tv_sec;
8036+ ret = 0;
8037+
8038+ out_unwait:
8039+ set_current_state(TASK_RUNNING);
8040+ remove_wait_queue(&call->waitq,&myself);
8041+ rxrpc_put_call(call);
8042+ out_put_conn:
8043+ rxrpc_put_connection(conn);
8044+ out:
8045+ _leave(" = %d",ret);
8046+ return ret;
8047+
8048+ abort:
8049+ set_current_state(TASK_UNINTERRUPTIBLE);
8050+ rxrpc_call_abort(call,ret);
8051+ schedule();
8052+ goto out_unwait;
8053+} /* end afs_rxvl_get_entry_by_name() */
8054+
8055+/*****************************************************************************/
8056+/*
8057+ * look up a volume location database entry by ID
8058+ */
8059+int afs_rxvl_get_entry_by_id(afs_server_t *server,
8060+ afs_volid_t volid,
8061+ afs_voltype_t voltype,
8062+ struct afs_cache_volume *entry)
8063+{
8064+ DECLARE_WAITQUEUE(myself,current);
8065+
8066+ struct rxrpc_connection *conn;
8067+ struct rxrpc_call *call;
8068+ struct iovec piov[1];
8069+ unsigned tmp;
8070+ size_t sent;
8071+ int ret, loop;
8072+ u32 *bp, param[3];
8073+
8074+ _enter(",%x,%d,",volid,voltype);
8075+
8076+ memset(entry,0,sizeof(*entry));
8077+
8078+ /* get hold of the vlserver connection */
8079+ ret = afs_server_get_vlconn(server,&conn);
8080+ if (ret<0)
8081+ goto out;
8082+
8083+ /* create a call through that connection */
8084+ ret = rxrpc_create_call(conn,NULL,NULL,afs_rxvl_aemap,&call);
8085+ if (ret<0) {
8086+ printk("kAFS: Unable to create call: %d\n",ret);
8087+ goto out_put_conn;
8088+ }
8089+ call->app_opcode = VLGETENTRYBYID;
8090+
8091+ /* we want to get event notifications from the call */
8092+ add_wait_queue(&call->waitq,&myself);
8093+
8094+ /* marshall the parameters */
8095+ param[0] = htonl(VLGETENTRYBYID);
8096+ param[1] = htonl(volid);
8097+ param[2] = htonl(voltype);
8098+
8099+ piov[0].iov_len = sizeof(param);
8100+ piov[0].iov_base = param;
8101+
8102+ /* send the parameters to the server */
8103+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
8104+ if (ret<0)
8105+ goto abort;
8106+
8107+ /* wait for the reply to completely arrive */
8108+ bp = rxrpc_call_alloc_scratch(call,384);
8109+
8110+ ret = rxrpc_call_read_data(call,bp,384,RXRPC_CALL_READ_BLOCK|RXRPC_CALL_READ_ALL);
8111+ if (ret<0) {
8112+ if (ret==-ECONNABORTED) {
8113+ ret = call->app_errno;
8114+ goto out_unwait;
8115+ }
8116+ goto abort;
8117+ }
8118+
8119+ /* unmarshall the reply */
8120+ for (loop=0; loop<64; loop++)
8121+ entry->name[loop] = ntohl(*bp++);
8122+ bp++; /* final NUL */
8123+
8124+ bp++; /* type */
8125+ entry->nservers = ntohl(*bp++);
8126+
8127+ for (loop=0; loop<8; loop++)
8128+ entry->servers[loop].s_addr = *bp++;
8129+
8130+ bp += 8; /* partition IDs */
8131+
8132+ for (loop=0; loop<8; loop++) {
8133+ tmp = ntohl(*bp++);
8134+ if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RW;
8135+ if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RO;
8136+ if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_BAK;
8137+ }
8138+
8139+ entry->vid[0] = ntohl(*bp++);
8140+ entry->vid[1] = ntohl(*bp++);
8141+ entry->vid[2] = ntohl(*bp++);
8142+
8143+ bp++; /* clone ID */
8144+
8145+ tmp = ntohl(*bp++); /* flags */
8146+ if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RW;
8147+ if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RO;
8148+ if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_CACHE_VOL_STM_BAK;
8149+
8150+ ret = -ENOMEDIUM;
8151+ if (!entry->vidmask)
8152+ goto abort;
8153+
8154+#if 0 /* TODO: remove */
8155+ entry->nservers = 3;
8156+ entry->servers[0].s_addr = htonl(0xac101249);
8157+ entry->servers[1].s_addr = htonl(0xac101243);
8158+ entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
8159+
8160+ entry->srvtmask[0] = AFS_CACHE_VOL_STM_RO;
8161+ entry->srvtmask[1] = AFS_CACHE_VOL_STM_RO;
8162+ entry->srvtmask[2] = AFS_CACHE_VOL_STM_RO | AFS_CACHE_VOL_STM_RW;
8163+#endif
8164+
8165+ /* success */
8166+ entry->ctime = xtime.tv_sec;
8167+ ret = 0;
8168+
8169+ out_unwait:
8170+ set_current_state(TASK_RUNNING);
8171+ remove_wait_queue(&call->waitq,&myself);
8172+ rxrpc_put_call(call);
8173+ out_put_conn:
8174+ rxrpc_put_connection(conn);
8175+ out:
8176+ _leave(" = %d",ret);
8177+ return ret;
8178+
8179+ abort:
8180+ set_current_state(TASK_UNINTERRUPTIBLE);
8181+ rxrpc_call_abort(call,ret);
8182+ schedule();
8183+ goto out_unwait;
8184+} /* end afs_rxvl_get_entry_by_id() */
8185+
8186+/*****************************************************************************/
8187+/*
8188+ * look up a volume location database entry by ID asynchronously
8189+ */
8190+int afs_rxvl_get_entry_by_id_async(afs_async_op_t *op,
8191+ afs_volid_t volid,
8192+ afs_voltype_t voltype)
8193+{
8194+ struct rxrpc_connection *conn;
8195+ struct rxrpc_call *call;
8196+ struct iovec piov[1];
8197+ size_t sent;
8198+ int ret;
8199+ u32 param[3];
8200+
8201+ _enter(",%x,%d,",volid,voltype);
8202+
8203+ /* get hold of the vlserver connection */
8204+ ret = afs_server_get_vlconn(op->server,&conn);
8205+ if (ret<0) {
8206+ _leave(" = %d",ret);
8207+ return ret;
8208+ }
8209+
8210+ /* create a call through that connection */
8211+ ret = rxrpc_create_call(conn,
8212+ afs_rxvl_get_entry_by_id_attn,
8213+ afs_rxvl_get_entry_by_id_error,
8214+ afs_rxvl_aemap,
8215+ &op->call);
8216+ rxrpc_put_connection(conn);
8217+
8218+ if (ret<0) {
8219+ printk("kAFS: Unable to create call: %d\n",ret);
8220+ _leave(" = %d",ret);
8221+ return ret;
8222+ }
8223+
8224+ op->call->app_opcode = VLGETENTRYBYID;
8225+ op->call->app_user = op;
8226+
8227+ call = op->call;
8228+ rxrpc_get_call(call);
8229+
8230+ /* send event notifications from the call to kafsasyncd */
8231+ afs_kafsasyncd_begin_op(op);
8232+
8233+ /* marshall the parameters */
8234+ param[0] = htonl(VLGETENTRYBYID);
8235+ param[1] = htonl(volid);
8236+ param[2] = htonl(voltype);
8237+
8238+ piov[0].iov_len = sizeof(param);
8239+ piov[0].iov_base = param;
8240+
8241+ /* allocate result read buffer in scratch space */
8242+ call->app_scr_ptr = rxrpc_call_alloc_scratch(op->call,384);
8243+
8244+ /* send the parameters to the server */
8245+ ret = rxrpc_call_write_data(call,1,piov,RXRPC_LAST_PACKET,GFP_NOFS,0,&sent);
8246+ if (ret<0) {
8247+ rxrpc_call_abort(call,ret); /* handle from kafsasyncd */
8248+ ret = 0;
8249+ goto out;
8250+ }
8251+
8252+ /* wait for the reply to completely arrive */
8253+ ret = rxrpc_call_read_data(call,call->app_scr_ptr,384,0);
8254+ switch (ret) {
8255+ case 0:
8256+ case -EAGAIN:
8257+ case -ECONNABORTED:
8258+ ret = 0;
8259+ break; /* all handled by kafsasyncd */
8260+
8261+ default:
8262+ rxrpc_call_abort(call,ret); /* force kafsasyncd to handle it */
8263+ ret = 0;
8264+ break;
8265+ }
8266+
8267+ out:
8268+ rxrpc_put_call(call);
8269+ _leave(" = %d",ret);
8270+ return ret;
8271+
8272+} /* end afs_rxvl_get_entry_by_id_async() */
8273+
8274+/*****************************************************************************/
8275+/*
8276+ * attend to the asynchronous get VLDB entry by ID
8277+ */
8278+int afs_rxvl_get_entry_by_id_async2(afs_async_op_t *op,
8279+ struct afs_cache_volume *entry)
8280+{
8281+ unsigned *bp, tmp;
8282+ int loop, ret;
8283+
8284+ _enter("{op=%p cst=%u}",op,op->call->app_call_state);
8285+
8286+ memset(entry,0,sizeof(*entry));
8287+
8288+ if (op->call->app_call_state==RXRPC_CSTATE_COMPLETE) {
8289+ /* operation finished */
8290+ afs_kafsasyncd_terminate_op(op);
8291+
8292+ bp = op->call->app_scr_ptr;
8293+
8294+ /* unmarshall the reply */
8295+ for (loop=0; loop<64; loop++)
8296+ entry->name[loop] = ntohl(*bp++);
8297+ bp++; /* final NUL */
8298+
8299+ bp++; /* type */
8300+ entry->nservers = ntohl(*bp++);
8301+
8302+ for (loop=0; loop<8; loop++)
8303+ entry->servers[loop].s_addr = *bp++;
8304+
8305+ bp += 8; /* partition IDs */
8306+
8307+ for (loop=0; loop<8; loop++) {
8308+ tmp = ntohl(*bp++);
8309+ if (tmp & AFS_VLSF_RWVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RW;
8310+ if (tmp & AFS_VLSF_ROVOL ) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_RO;
8311+ if (tmp & AFS_VLSF_BACKVOL) entry->srvtmask[loop] |= AFS_CACHE_VOL_STM_BAK;
8312+ }
8313+
8314+ entry->vid[0] = ntohl(*bp++);
8315+ entry->vid[1] = ntohl(*bp++);
8316+ entry->vid[2] = ntohl(*bp++);
8317+
8318+ bp++; /* clone ID */
8319+
8320+ tmp = ntohl(*bp++); /* flags */
8321+ if (tmp & AFS_VLF_RWEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RW;
8322+ if (tmp & AFS_VLF_ROEXISTS ) entry->vidmask |= AFS_CACHE_VOL_STM_RO;
8323+ if (tmp & AFS_VLF_BACKEXISTS) entry->vidmask |= AFS_CACHE_VOL_STM_BAK;
8324+
8325+ ret = -ENOMEDIUM;
8326+ if (!entry->vidmask) {
8327+ rxrpc_call_abort(op->call,ret);
8328+ goto done;
8329+ }
8330+
8331+#if 0 /* TODO: remove */
8332+ entry->nservers = 3;
8333+ entry->servers[0].s_addr = htonl(0xac101249);
8334+ entry->servers[1].s_addr = htonl(0xac101243);
8335+ entry->servers[2].s_addr = htonl(0xac10125b /*0xac10125b*/);
8336+
8337+ entry->srvtmask[0] = AFS_CACHE_VOL_STM_RO;
8338+ entry->srvtmask[1] = AFS_CACHE_VOL_STM_RO;
8339+ entry->srvtmask[2] = AFS_CACHE_VOL_STM_RO | AFS_CACHE_VOL_STM_RW;
8340+#endif
8341+
8342+ /* success */
8343+ entry->ctime = xtime.tv_sec;
8344+ ret = 0;
8345+ goto done;
8346+ }
8347+
8348+ if (op->call->app_call_state==RXRPC_CSTATE_ERROR) {
8349+ /* operation error */
8350+ ret = op->call->app_errno;
8351+ goto done;
8352+ }
8353+
8354+ _leave(" = -EAGAIN");
8355+ return -EAGAIN;
8356+
8357+ done:
8358+ rxrpc_put_call(op->call);
8359+ op->call = NULL;
8360+ _leave(" = %d",ret);
8361+ return ret;
8362+} /* end afs_rxvl_get_entry_by_id_async2() */
8363+
8364+/*****************************************************************************/
8365+/*
8366+ * handle attention events on an async get-entry-by-ID op
8367+ * - called from krxiod
8368+ */
8369+static void afs_rxvl_get_entry_by_id_attn(struct rxrpc_call *call)
8370+{
8371+ afs_async_op_t *op = call->app_user;
8372+
8373+ _enter("{op=%p cst=%u}",op,call->app_call_state);
8374+
8375+ switch (call->app_call_state) {
8376+ case RXRPC_CSTATE_COMPLETE:
8377+ afs_kafsasyncd_attend_op(op);
8378+ break;
8379+ case RXRPC_CSTATE_CLNT_RCV_REPLY:
8380+ if (call->app_async_read)
8381+ break;
8382+ case RXRPC_CSTATE_CLNT_GOT_REPLY:
8383+ if (call->app_read_count==0)
8384+ break;
8385+ printk("kAFS: Reply bigger than expected {cst=%u asyn=%d mark=%d rdy=%u pr=%u%s}",
8386+ call->app_call_state,
8387+ call->app_async_read,
8388+ call->app_mark,
8389+ call->app_ready_qty,
8390+ call->pkt_rcv_count,
8391+ call->app_last_rcv ? " last" : "");
8392+
8393+ rxrpc_call_abort(call,-EBADMSG);
8394+ break;
8395+ default:
8396+ BUG();
8397+ }
8398+
8399+ _leave("");
8400+
8401+} /* end afs_rxvl_get_entry_by_id_attn() */
8402+
8403+/*****************************************************************************/
8404+/*
8405+ * handle error events on an async get-entry-by-ID op
8406+ * - called from krxiod
8407+ */
8408+static void afs_rxvl_get_entry_by_id_error(struct rxrpc_call *call)
8409+{
8410+ afs_async_op_t *op = call->app_user;
8411+
8412+ _enter("{op=%p cst=%u}",op,call->app_call_state);
8413+
8414+ afs_kafsasyncd_attend_op(op);
8415+
8416+ _leave("");
8417+
8418+} /* end afs_rxvl_get_entry_by_id_error() */
8419diff -urNp linux-5240/fs/afs/vlclient.h linux-5250/fs/afs/vlclient.h
8420--- linux-5240/fs/afs/vlclient.h 1970-01-01 01:00:00.000000000 +0100
8421+++ linux-5250/fs/afs/vlclient.h
8422@@ -0,0 +1,96 @@
8423+/* vlclient.h: Volume Location Service client interface
8424+ *
8425+ * Copyright (C) 2002 Red Hat, Inc. All Rights Reserved.
8426+ * Written by David Howells (dhowells@redhat.com)
8427+ *
8428+ * This program is free software; you can redistribute it and/or
8429+ * modify it under the terms of the GNU General Public License
8430+ * as published by the Free Software Foundation; either version
8431+ * 2 of the License, or (at your option) any later version.
8432+ */
8433+
8434+#ifndef _LINUX_AFS_VLCLIENT_H
8435+#define _LINUX_AFS_VLCLIENT_H
8436+
8437+#include "types.h"
8438+#include "cache-layout.h"
8439+
8440+enum AFSVL_Errors {
8441+ AFSVL_IDEXIST = 363520, /* Volume Id entry exists in vl database */
8442+ AFSVL_IO = 363521, /* I/O related error */
8443+ AFSVL_NAMEEXIST = 363522, /* Volume name entry exists in vl database */
8444+ AFSVL_CREATEFAIL = 363523, /* Internal creation failure */
8445+ AFSVL_NOENT = 363524, /* No such entry */
8446+ AFSVL_EMPTY = 363525, /* Vl database is empty */
8447+ AFSVL_ENTDELETED = 363526, /* Entry is deleted (soft delete) */
8448+ AFSVL_BADNAME = 363527, /* Volume name is illegal */
8449+ AFSVL_BADINDEX = 363528, /* Index is out of range */
8450+ AFSVL_BADVOLTYPE = 363529, /* Bad volume type */
8451+ AFSVL_BADSERVER = 363530, /* Illegal server number (out of range) */
8452+ AFSVL_BADPARTITION = 363531, /* Bad partition number */
8453+ AFSVL_REPSFULL = 363532, /* Run out of space for Replication sites */
8454+ AFSVL_NOREPSERVER = 363533, /* No such Replication server site exists */
8455+ AFSVL_DUPREPSERVER = 363534, /* Replication site already exists */
8456+ AFSVL_RWNOTFOUND = 363535, /* Parent R/W entry not found */
8457+ AFSVL_BADREFCOUNT = 363536, /* Illegal Reference Count number */
8458+ AFSVL_SIZEEXCEEDED = 363537, /* Vl size for attributes exceeded */
8459+ AFSVL_BADENTRY = 363538, /* Bad incoming vl entry */
8460+ AFSVL_BADVOLIDBUMP = 363539, /* Illegal max volid increment */
8461+ AFSVL_IDALREADYHASHED = 363540, /* RO/BACK id already hashed */
8462+ AFSVL_ENTRYLOCKED = 363541, /* Vl entry is already locked */
8463+ AFSVL_BADVOLOPER = 363542, /* Bad volume operation code */
8464+ AFSVL_BADRELLOCKTYPE = 363543, /* Bad release lock type */
8465+ AFSVL_RERELEASE = 363544, /* Status report: last release was aborted */
8466