home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / v1.1 / kdiffs-1.000 / kdiffs
Text File  |  1994-10-17  |  90KB  |  2,955 lines

  1. diff -ru --new-file linux_1.1.54/arch/i386/config.in linux_1.1.54_owld/arch/i386/config.in
  2. --- linux_1.1.54/arch/i386/config.in    Sun Oct 16 00:26:27 1994
  3. +++ linux_1.1.54_owld/arch/i386/config.in    Mon Oct 17 16:43:32 1994
  4. @@ -162,6 +162,7 @@
  5.  bool 'ISO9660 cdrom filesystem support' CONFIG_ISO9660_FS n
  6.  bool 'OS/2 HPFS filesystem support (read only)' CONFIG_HPFS_FS n
  7.  bool 'System V and Coherent filesystem support' CONFIG_SYSV_FS n
  8. +bool 'Disk QUOTA support' CONFIG_QUOTA y
  9.  
  10.  comment 'character devices'
  11.  
  12. diff -ru --new-file linux_1.1.54/drivers/block/ll_rw_blk.c linux_1.1.54_owld/drivers/block/ll_rw_blk.c
  13. --- linux_1.1.54/drivers/block/ll_rw_blk.c    Mon Sep 12 23:19:58 1994
  14. +++ linux_1.1.54_owld/drivers/block/ll_rw_blk.c    Mon Sep 12 23:20:31 1994
  15. @@ -149,7 +149,24 @@
  16.  static void add_request(struct blk_dev_struct * dev, struct request * req)
  17.  {
  18.      struct request * tmp;
  19. +    short disk_index;
  20.  
  21. +    switch (MAJOR(req->dev)) {
  22. +        case SCSI_DISK_MAJOR:
  23. +            disk_index = (MINOR(req->dev) & 0x0070) >> 4;
  24. +            if (disk_index < 4)
  25. +                kstat.dk_drive[disk_index]++;
  26. +            break;
  27. +        case HD_MAJOR:
  28. +        case XT_DISK_MAJOR:
  29. +            disk_index = (MINOR(req->dev) & 0x00C0) >> 6;
  30. +            if (disk_index < 4)
  31. +                kstat.dk_drive[disk_index]++;
  32. +            break;
  33. +        default:
  34. +            break;
  35. +    }
  36. +
  37.      req->next = NULL;
  38.      cli();
  39.      if (req->bh)
  40. diff -ru --new-file linux_1.1.54/fs/Makefile linux_1.1.54_owld/fs/Makefile
  41. --- linux_1.1.54/fs/Makefile    Sun Oct 16 00:26:31 1994
  42. +++ linux_1.1.54_owld/fs/Makefile    Sun Oct 16 00:28:21 1994
  43. @@ -56,9 +56,9 @@
  44.  .s.o:
  45.      $(AS) -o $*.o $<
  46.  
  47. -OBJS=    open.o read_write.o inode.o devices.o file_table.o buffer.o super.o \
  48. -    block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
  49. -    select.o fifo.o locks.o filesystems.o dcache.o $(BINFMTS)
  50. +OBJS=    open.o read_write.o inode.o devices.o file_table.o fileio.o buffer.o \
  51. +    super.o block_dev.o stat.o exec.o pipe.o namei.o fcntl.o ioctl.o \
  52. +    select.o fifo.o locks.o dcache.o dquot.o filesystems.o $(BINFMTS)
  53.  
  54.  all: fs.o filesystems.a modules
  55.  
  56. diff -ru --new-file linux_1.1.54/fs/binfmt_elf.c linux_1.1.54_owld/fs/binfmt_elf.c
  57. --- linux_1.1.54/fs/binfmt_elf.c    Sun Oct 16 00:26:31 1994
  58. +++ linux_1.1.54_owld/fs/binfmt_elf.c    Sun Oct 16 00:35:10 1994
  59. @@ -497,6 +497,8 @@
  60.      current->mm->end_code = 0;
  61.      current->mm->start_mmap = ELF_START_MMAP;
  62.      current->mm->mmap = NULL;
  63. +    current->flags &= ~PF_FORKNOEXEC; /* accounting flags */
  64. +        current->io_usage = 0;
  65.      elf_entry = (unsigned int) elf_ex.e_entry;
  66.      
  67.      /* Do this so that we can load the interpreter, if need be.  We will
  68. diff -ru --new-file linux_1.1.54/fs/buffer.c linux_1.1.54_owld/fs/buffer.c
  69. --- linux_1.1.54/fs/buffer.c    Thu Oct  6 21:16:21 1994
  70. +++ linux_1.1.54_owld/fs/buffer.c    Thu Oct  6 21:18:26 1994
  71. @@ -217,6 +217,9 @@
  72.      sync_supers(dev);
  73.      sync_inodes(dev);
  74.      sync_buffers(dev, 0);
  75. +#ifdef CONFIG_QUOTA
  76. +    sync_dquots(dev, -1);
  77. +#endif
  78.  }
  79.  
  80.  int fsync_dev(dev_t dev)
  81. @@ -224,6 +227,9 @@
  82.      sync_buffers(dev, 0);
  83.      sync_supers(dev);
  84.      sync_inodes(dev);
  85. +#ifdef CONFIG_QUOTA
  86. +    sync_dquots(dev, -1);
  87. +#endif
  88.      return sync_buffers(dev, 1);
  89.  }
  90.  
  91. diff -ru --new-file linux_1.1.54/fs/dquot.c linux_1.1.54_owld/fs/dquot.c
  92. --- linux_1.1.54/fs/dquot.c
  93. +++ linux_1.1.54_owld/fs/dquot.c    Mon Oct 17 16:33:36 1994
  94. @@ -0,0 +1,1008 @@
  95. +/*
  96. + * QUOTA    An implementation of the diskquota system for the LINUX operating
  97. + *          system. QUOTA is implemented using the BSD systemcall interface as
  98. + *          the means of communication with the user level. Should work for all
  99. + *          filesystems because of integration into the VFS layer of the
  100. + *          operating system. This is based on the Melbourne quota system wich
  101. + *          uses both user and group quota files.
  102. + * 
  103. + *          Main layer of quota management
  104. + * 
  105. + * Version: $Id: dquot.c,v 3.11 1994/10/17 09:52:47 mvw Exp mvw $
  106. + * 
  107. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  108. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  109. + *          Linus Torvalds <Linus.Torvalds@cc.helsinki.FI>
  110. + * 
  111. + *          This program is free software; you can redistribute it and/or
  112. + *          modify it under the terms of the GNU General Public License as
  113. + *          published by the Free Software Foundation; either version 2 of the
  114. + *          License, or (at your option) any later version.
  115. + */
  116. +
  117. +#include <linux/errno.h>
  118. +#include <linux/kernel.h>
  119. +#include <linux/sched.h>
  120. +#include <linux/config.h>
  121. +
  122. +#ifdef CONFIG_QUOTA
  123. +#include <linux/types.h>
  124. +#include <linux/string.h>
  125. +#include <linux/fcntl.h>
  126. +#include <linux/stat.h>
  127. +#include <linux/segment.h>
  128. +#include <linux/tty.h>
  129. +#include <linux/malloc.h>
  130. +#include <linux/mount.h>
  131. +#include <linux/fileio.h>
  132. +#include <linux/delay.h>
  133. +
  134. +#include <asm/segment.h>
  135. +#include <sys/sysmacros.h>
  136. +
  137. +static char quotamessage[MAX_QUOTA_MESSAGE];
  138. +static char *quotatypes[] = INITQFNAMES;
  139. +
  140. +static int nr_dquots = 0, nr_free_dquots = 0;
  141. +static struct dquot *hash_table[NR_DQHASH];
  142. +static struct dquot *first_dquot;
  143. +
  144. +static struct wait_queue *dquot_wait = (struct wait_queue *)NULL;
  145. +
  146. +extern void add_dquot_ref(dev_t dev, short type);
  147. +extern void reset_dquot_ptrs(dev_t dev, short type);
  148. +extern void close_fp(struct file *filp, int fd);
  149. +
  150. +#ifndef min
  151. +#define min(a,b) ((a) < (b)) ? (a) : (b)
  152. +#endif
  153. +
  154. +/*
  155. + * Functions for management of the hashlist.
  156. + */
  157. +static inline int const hashfn(dev_t dev, unsigned int id, short type)
  158. +{
  159. +   return ((dev ^ id) * (MAXQUOTAS - type)) % NR_DQHASH;
  160. +}
  161. +
  162. +static inline struct dquot **const hash(dev_t dev, unsigned int id, short type)
  163. +{
  164. +   return hash_table + hashfn(dev, id, type);
  165. +}
  166. +
  167. +static void insert_dquot_free(struct dquot *dquot)
  168. +{
  169. +   dquot->dq_next = first_dquot;
  170. +   dquot->dq_prev = first_dquot->dq_prev;
  171. +   dquot->dq_next->dq_prev = dquot;
  172. +   dquot->dq_prev->dq_next = dquot;
  173. +   first_dquot = dquot;
  174. +}
  175. +
  176. +static void remove_dquot_free(struct dquot *dquot)
  177. +{
  178. +   if (first_dquot == dquot)
  179. +      first_dquot = first_dquot->dq_next;
  180. +   if (dquot->dq_next)
  181. +      dquot->dq_next->dq_prev = dquot->dq_prev;
  182. +   if (dquot->dq_prev)
  183. +      dquot->dq_prev->dq_next = dquot->dq_next;
  184. +   dquot->dq_next = dquot->dq_prev = NODQUOT;
  185. +}
  186. +
  187. +static void insert_dquot_hash(struct dquot *dquot)
  188. +{
  189. +   struct dquot **h;
  190. +
  191. +   h = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
  192. +   dquot->dq_hash_next = *h;
  193. +   dquot->dq_hash_prev = NODQUOT;
  194. +   if (dquot->dq_hash_next)
  195. +      dquot->dq_hash_next->dq_hash_prev = dquot;
  196. +   *h = dquot;
  197. +}
  198. +
  199. +static void remove_dquot_hash(struct dquot *dquot)
  200. +{
  201. +   struct dquot **h;
  202. +
  203. +   h = hash(dquot->dq_dev, dquot->dq_id, dquot->dq_type);
  204. +   if (*h == dquot)
  205. +      *h = dquot->dq_hash_next;
  206. +   if (dquot->dq_hash_next)
  207. +      dquot->dq_hash_next->dq_hash_prev = dquot->dq_hash_prev;
  208. +   if (dquot->dq_hash_prev)
  209. +      dquot->dq_hash_prev->dq_hash_next = dquot->dq_hash_next;
  210. +   dquot->dq_hash_prev = dquot->dq_hash_next = NODQUOT;
  211. +}
  212. +
  213. +static void put_last_free(struct dquot *dquot)
  214. +{
  215. +   remove_dquot_free(dquot);
  216. +   dquot->dq_prev = first_dquot->dq_prev;
  217. +   dquot->dq_prev->dq_next = dquot;
  218. +   dquot->dq_next = first_dquot;
  219. +   dquot->dq_next->dq_prev = dquot;
  220. +}
  221. +
  222. +static void grow_dquots(void)
  223. +{
  224. +   struct dquot *dquot;
  225. +   int i;
  226. +
  227. +   if (!(dquot = (struct dquot*) get_free_page(GFP_KERNEL)))
  228. +      return;
  229. +   i = PAGE_SIZE / sizeof(struct dquot);
  230. +   nr_dquots += i;
  231. +   nr_free_dquots += i;
  232. +   if (!first_dquot)
  233. +      dquot->dq_next = dquot->dq_prev = first_dquot = dquot++, i--;
  234. +   for ( ; i ; i-- )
  235. +      insert_dquot_free(dquot++);
  236. +}
  237. +
  238. +/*
  239. + * Functions for locking and waiting on dquots.
  240. + */
  241. +static void __wait_on_dquot(struct dquot *dquot)
  242. +{
  243. +   struct wait_queue wait = {current, NULL};
  244. +
  245. +   add_wait_queue(&dquot->dq_wait, &wait);
  246. +repeat:
  247. +   current->state = TASK_UNINTERRUPTIBLE;
  248. +   if (dquot->dq_flags & DQ_LOCKED) {
  249. +      dquot->dq_flags |= DQ_WANT;
  250. +      schedule();
  251. +      goto repeat;
  252. +   }
  253. +   remove_wait_queue(&dquot->dq_wait, &wait);
  254. +   current->state = TASK_RUNNING;
  255. +}
  256. +
  257. +static inline void wait_on_dquot(struct dquot *dquot)
  258. +{
  259. +   if (dquot->dq_flags & DQ_LOCKED)
  260. +      __wait_on_dquot(dquot);
  261. +}
  262. +
  263. +static inline void lock_dquot(struct dquot *dquot)
  264. +{
  265. +   wait_on_dquot(dquot);
  266. +   dquot->dq_flags |= DQ_LOCKED;
  267. +}
  268. +
  269. +static inline void unlock_dquot(struct dquot *dquot)
  270. +{
  271. +   dquot->dq_flags &= ~DQ_LOCKED;
  272. +   if (dquot->dq_flags & DQ_WANT) {
  273. +      dquot->dq_flags &= ~DQ_WANT;
  274. +      wake_up(&dquot->dq_wait);
  275. +   }
  276. +}
  277. +/*
  278. + * Note that we don't want to disturb any wait-queues when we discard
  279. + * an dquot.
  280. + *
  281. + * FIXME: As soon as we have a nice solution for the inode problem we
  282. + *        can also fix this one. I.e. the volatile part.
  283. + */
  284. +static void clear_dquot(struct dquot * dquot)
  285. +{
  286. +   struct wait_queue *wait;
  287. +
  288. +   wait_on_dquot(dquot);
  289. +   remove_dquot_hash(dquot);
  290. +   remove_dquot_free(dquot);
  291. +   wait = ((volatile struct dquot *) dquot)->dq_wait;
  292. +   if (dquot->dq_count)
  293. +      nr_free_dquots++;
  294. +   memset(dquot, 0, sizeof(*dquot));
  295. +   ((volatile struct dquot *) dquot)->dq_wait = wait;
  296. +   insert_dquot_free(dquot);
  297. +}
  298. +
  299. +static void write_dquot(struct dquot *dquot)
  300. +{
  301. +   short type = dquot->dq_type;
  302. +   struct file *filp = dquot->dq_mnt->mnt_quotas[type];
  303. +   unsigned short fs;
  304. +
  305. +   if (!(dquot->dq_flags & DQ_MOD) || (filp == (struct file *)0))
  306. +      return;
  307. +   lock_dquot(dquot);
  308. +   down(&dquot->dq_mnt->mnt_sem);
  309. +   if (filp->f_op->lseek) {
  310. +      if (filp->f_op->lseek(filp->f_inode, filp,
  311. +          dqoff(dquot->dq_id), 0) != dqoff(dquot->dq_id)) {
  312. +         up(&dquot->dq_mnt->mnt_sem);
  313. +         return;
  314. +      }
  315. +   } else
  316. +      filp->f_pos = dqoff(dquot->dq_id);
  317. +   fs = get_fs();
  318. +   set_fs(KERNEL_DS);
  319. +   if (filp->f_op->write(filp->f_inode, filp,
  320. +       (char *)&dquot->dq_dqb, sizeof(struct dqblk)) == sizeof(struct dqblk))
  321. +      dquot->dq_flags &= ~DQ_MOD;
  322. +   up(&dquot->dq_mnt->mnt_sem);
  323. +   set_fs(fs);
  324. +   unlock_dquot(dquot);
  325. +}
  326. +
  327. +static void read_dquot(struct dquot *dquot)
  328. +{
  329. +   short type = dquot->dq_type;
  330. +   struct file *filp = dquot->dq_mnt->mnt_quotas[type];
  331. +   unsigned short fs;
  332. +
  333. +   if (filp == (struct file *)0)
  334. +      return;
  335. +   lock_dquot(dquot);
  336. +   down(&dquot->dq_mnt->mnt_sem);
  337. +   if (filp->f_op->lseek) {
  338. +      if (filp->f_op->lseek(filp->f_inode, filp,
  339. +          dqoff(dquot->dq_id),0) != dqoff(dquot->dq_id)) {
  340. +         up(&dquot->dq_mnt->mnt_sem);
  341. +         return;
  342. +      }
  343. +   } else
  344. +      filp->f_pos = dqoff(dquot->dq_id);
  345. +   fs = get_fs();
  346. +   set_fs(KERNEL_DS);
  347. +   filp->f_op->read(filp->f_inode, filp,
  348. +                    (char *)&dquot->dq_dqb, sizeof(struct dqblk));
  349. +   up(&dquot->dq_mnt->mnt_sem);
  350. +   set_fs(fs);
  351. +   if (dquot->dq_bhardlimit == 0 && dquot->dq_bsoftlimit == 0 &&
  352. +       dquot->dq_ihardlimit == 0 && dquot->dq_isoftlimit == 0)
  353. +      dquot->dq_flags |= DQ_FAKE;
  354. +   unlock_dquot(dquot);
  355. +}
  356. +
  357. +int sync_dquots(dev_t dev, short type)
  358. +{
  359. +   struct dquot *dquot = first_dquot;
  360. +   int i;
  361. +
  362. +   for(i = 0; i < nr_dquots * 2; i++, dquot = dquot->dq_next) {
  363. +      if (!dquot->dq_count || (dev && dquot->dq_dev != dev))
  364. +         continue;
  365. +      if (type != -1 && dquot->dq_type != type)
  366. +         continue;
  367. +      wait_on_dquot(dquot);
  368. +      if (dquot->dq_flags & DQ_MOD)
  369. +         write_dquot(dquot);
  370. +   }
  371. +   return 0;
  372. +   /* NOTREACHED */
  373. +}
  374. +
  375. +/*
  376. + * Trash the cache for a certain type on a device.
  377. + */
  378. +void invalidate_dquots(dev_t dev, short type)
  379. +{
  380. +   struct dquot *dquot, *next;
  381. +   int i;
  382. +
  383. +   next = first_dquot;
  384. +   for(i = nr_dquots ; i > 0 ; i--) {
  385. +      dquot = next;
  386. +      next = dquot->dq_next;
  387. +      if (dquot->dq_dev != dev || dquot->dq_type != type)
  388. +         continue;
  389. +      if (dquot->dq_flags & DQ_LOCKED) {
  390. +         printk("VFS: dquot busy on removed device %d/%d\n", MAJOR(dev), MINOR(dev));
  391. +         continue;
  392. +      }
  393. +      if (dquot->dq_flags & DQ_MOD)
  394. +         write_dquot(dquot);
  395. +      clear_dquot(dquot);
  396. +   }
  397. +}
  398. +
  399. +/*
  400. + * Check quota for inodes. Returns QUOTA_OK if can allocate and
  401. + * NO_QUOTA if it can't.
  402. + */
  403. +static int check_idq(struct dquot *dquot, int id, short type, u_long wanted_inodes)
  404. +{
  405. +   if (wanted_inodes == 0 || dquot->dq_flags & DQ_FAKE)
  406. +      return QUOTA_OK;
  407. +   if (dquot->dq_ihardlimit &&
  408. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_ihardlimit) {
  409. +      if (!(dquot->dq_flags & DQ_INODES)) {
  410. +         sprintf(quotamessage,
  411. +                "File LIMIT reached on %s for %s %d. !! NO MORE !!\n\r",
  412. +                dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  413. +         tty_write_message(current->tty, quotamessage);
  414. +         dquot->dq_flags |= DQ_INODES;
  415. +      }
  416. +      return NO_QUOTA;
  417. +   }
  418. +   if (dquot->dq_isoftlimit &&
  419. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_isoftlimit &&
  420. +       dquot->dq_itime && CURRENT_TIME >= dquot->dq_itime) {
  421. +      sprintf(quotamessage,
  422. +              "File QUOTA exceeded TOO long on %s for %s %d. !! NO MORE !!\n\r",
  423. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  424. +      tty_write_message(current->tty, quotamessage);
  425. +      return NO_QUOTA;
  426. +   }
  427. +   if (dquot->dq_isoftlimit &&
  428. +      (dquot->dq_curinodes + wanted_inodes) >= dquot->dq_isoftlimit &&
  429. +       dquot->dq_itime == 0) {
  430. +      sprintf(quotamessage,
  431. +              "File QUOTA exceeded on %s for %s %d\n\r",
  432. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  433. +      tty_write_message(current->tty, quotamessage);
  434. +      dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
  435. +   }
  436. +   return QUOTA_OK;
  437. +   /* NOTREACHED */
  438. +}
  439. +
  440. +/*
  441. + * Check quota for blocks. Returns QUOTA_OK if can allocate and
  442. + * NO_QUOTA if it can't. When we can't allocate wanted_blocks you get
  443. + * the number we can allocate in avail_blocks.
  444. + */
  445. +static int check_bdq(struct dquot *dquot, int id, short type,
  446. +                     u_long wanted_blocks, u_long *avail_blocks)
  447. +{
  448. +   *avail_blocks = wanted_blocks;
  449. +   if (wanted_blocks == 0 || dquot->dq_flags & DQ_FAKE)
  450. +      return QUOTA_OK;
  451. +   if (dquot->dq_bhardlimit &&
  452. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bhardlimit) {
  453. +      if ((dquot->dq_flags & DQ_BLKS) == 0) {
  454. +         sprintf(quotamessage,
  455. +                 "Block LIMIT reached on %s for %s %d. !! NO MORE !!\n\r",
  456. +                 dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  457. +         tty_write_message(current->tty, quotamessage);
  458. +         dquot->dq_flags |= DQ_BLKS;
  459. +      }
  460. +      if (dquot->dq_curblocks < dquot->dq_bhardlimit) {
  461. +         *avail_blocks = dquot->dq_bhardlimit - dquot->dq_curblocks;
  462. +         return QUOTA_OK;
  463. +      } else
  464. +         return NO_QUOTA;
  465. +   }
  466. +   if (dquot->dq_bsoftlimit &&
  467. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bsoftlimit &&
  468. +       dquot->dq_btime && CURRENT_TIME >= dquot->dq_btime) {
  469. +      sprintf(quotamessage,
  470. +              "Block QUOTA exceeded TOO long on %s for %s %d. !! NO MORE !!\n\r",
  471. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  472. +      tty_write_message(current->tty, quotamessage);
  473. +      return NO_QUOTA;
  474. +   }
  475. +   if (dquot->dq_bsoftlimit &&
  476. +      (dquot->dq_curblocks + wanted_blocks) >= dquot->dq_bsoftlimit &&
  477. +       dquot->dq_btime == 0) {
  478. +      sprintf(quotamessage,
  479. +              "Block QUOTA exceeded on %s for %s %d\n\r",
  480. +              dquot->dq_mnt->mnt_devname, quotatypes[type], id);
  481. +      tty_write_message(current->tty, quotamessage);
  482. +      dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
  483. +   }
  484. +   return QUOTA_OK;
  485. +   /* NOTREACHED */
  486. +}
  487. +
  488. +/*
  489. + * Add a number of inodes and blocks to a diskquota.
  490. + */
  491. +static inline void incr_quota(struct dquot *dquot, u_long inodes, u_long blocks)
  492. +{
  493. +   lock_dquot(dquot);
  494. +   dquot->dq_curinodes += inodes;
  495. +   dquot->dq_curblocks += blocks;
  496. +   dquot->dq_flags |= DQ_MOD;
  497. +   unlock_dquot(dquot);
  498. +}
  499. +
  500. +/*
  501. + * Remove a number of inodes and blocks from a quota.
  502. + * Reset gracetimes if under softlimit.
  503. + */
  504. +static inline void decr_quota(struct dquot *dquot, u_long inodes, u_long blocks)
  505. +{
  506. +   lock_dquot(dquot);
  507. +   if (dquot->dq_curinodes >= inodes)
  508. +      dquot->dq_curinodes -= inodes;
  509. +   else
  510. +      dquot->dq_curinodes = 0;
  511. +   if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  512. +      dquot->dq_itime = (time_t) 0;
  513. +   dquot->dq_flags &= ~DQ_INODES;
  514. +   if (dquot->dq_curblocks >= blocks)
  515. +      dquot->dq_curblocks -= blocks;
  516. +   else
  517. +      dquot->dq_curblocks = 0;
  518. +   if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  519. +      dquot->dq_btime = (time_t) 0;
  520. +   dquot->dq_flags &= ~DQ_BLKS;
  521. +   dquot->dq_flags |= DQ_MOD;
  522. +   unlock_dquot(dquot);
  523. +}
  524. +
  525. +/*
  526. + * Initialize a dquot-struct with new quota info. This is used by the
  527. + * systemcall interface functions.
  528. + */ 
  529. +static int set_dqblk(dev_t dev, int id, short type, int flags, struct dqblk *dqblk)
  530. +{
  531. +   struct dquot *dquot;
  532. +   struct dqblk dq_dqblk;
  533. +   int error;
  534. +
  535. +   if (dqblk == (struct dqblk *)0)
  536. +      return -EFAULT;
  537. +
  538. +   if (flags & QUOTA_SYSCALL) {
  539. +      if ((error = verify_area(VERIFY_READ, dqblk, sizeof(struct dqblk))) != 0)
  540. +         return error;
  541. +      memcpy_fromfs(&dq_dqblk, dqblk, sizeof(struct dqblk));
  542. +   } else {
  543. +      memcpy(&dq_dqblk, dqblk, sizeof(struct dqblk));
  544. +   }
  545. +   if ((dquot = dqget(dev, id, type)) != NODQUOT) {
  546. +      lock_dquot(dquot);
  547. +      if (id > 0 && ((flags & SET_QUOTA) || (flags & SET_QLIMIT))) {
  548. +         dquot->dq_bhardlimit = dq_dqblk.dqb_bhardlimit;
  549. +         dquot->dq_bsoftlimit = dq_dqblk.dqb_bsoftlimit;
  550. +         dquot->dq_ihardlimit = dq_dqblk.dqb_ihardlimit;
  551. +         dquot->dq_isoftlimit = dq_dqblk.dqb_isoftlimit;
  552. +      }
  553. +      if ((flags & SET_QUOTA) || (flags & SET_USE)) {
  554. +         if (dquot->dq_isoftlimit &&
  555. +             dquot->dq_curinodes < dquot->dq_isoftlimit &&
  556. +             dq_dqblk.dqb_curinodes >= dquot->dq_isoftlimit)
  557. +            dquot->dq_itime = CURRENT_TIME + dquot->dq_mnt->mnt_iexp[type];
  558. +         dquot->dq_curinodes = dq_dqblk.dqb_curinodes;
  559. +         if (dquot->dq_curinodes < dquot->dq_isoftlimit)
  560. +            dquot->dq_flags &= ~DQ_INODES;
  561. +         if (dquot->dq_bsoftlimit &&
  562. +             dquot->dq_curblocks < dquot->dq_bsoftlimit &&
  563. +             dq_dqblk.dqb_curblocks >= dquot->dq_bsoftlimit)
  564. +            dquot->dq_btime = CURRENT_TIME + dquot->dq_mnt->mnt_bexp[type];
  565. +         dquot->dq_curblocks = dq_dqblk.dqb_curblocks;
  566. +         if (dquot->dq_curblocks < dquot->dq_bsoftlimit)
  567. +            dquot->dq_flags &= ~DQ_BLKS;
  568. +      }
  569. +      if (id == 0) {
  570. +         /* 
  571. +          * Change in expiretimes, change them in dq_mnt.
  572. +          */
  573. +         dquot->dq_mnt->mnt_bexp[type] = dquot->dq_btime = dq_dqblk.dqb_btime;
  574. +         dquot->dq_mnt->mnt_iexp[type] = dquot->dq_itime = dq_dqblk.dqb_itime;
  575. +      }
  576. +      if (dq_dqblk.dqb_bhardlimit == 0 && dq_dqblk.dqb_bsoftlimit == 0 &&
  577. +          dq_dqblk.dqb_ihardlimit == 0 && dq_dqblk.dqb_isoftlimit == 0)
  578. +         dquot->dq_flags |= DQ_FAKE; /* No limits, only usage */
  579. +      dquot->dq_flags |= DQ_MOD;
  580. +      unlock_dquot(dquot);
  581. +      dqput(dquot);
  582. +   }
  583. +   return 0;
  584. +}
  585. +
  586. +static int get_quota(dev_t dev, int id, short type, struct dqblk * dqblk)
  587. +{
  588. +   struct vfsmount *vfsmnt;
  589. +   struct dquot *dquot;
  590. +   int error;
  591. +
  592. +   if ((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)0 &&
  593. +        vfsmnt->mnt_quotas[type] != (struct file *)0) {
  594. +      if (dqblk == (struct dqblk *) 0)
  595. +         return -EFAULT;
  596. +
  597. +      if ((error = verify_area(VERIFY_WRITE, dqblk, sizeof(struct dqblk))) != 0)
  598. +         return (error);
  599. +
  600. +      if ((dquot = dqget(dev, id, type)) != NODQUOT) {
  601. +         memcpy_tofs(dqblk, (char *)&dquot->dq_dqb, sizeof(struct dqblk));
  602. +         dqput(dquot);
  603. +         return 0;
  604. +      }
  605. +   }
  606. +   return -ESRCH;
  607. +}
  608. +
  609. +/*
  610. + * Turn quota off on a device. type == -1 ==> quotaoff for all types (umount)
  611. + */
  612. +int quota_off(dev_t dev, short type)
  613. +{
  614. +   struct vfsmount *vfsmnt;
  615. +   short cnt;
  616. +
  617. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  618. +      if (type != -1 && cnt != type)
  619. +         continue;
  620. +      if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0 ||
  621. +           vfsmnt->mnt_quotas[cnt] == (struct file *)0)
  622. +         continue;
  623. +      vfsmnt->mnt_flags |= QF_CLOSING;
  624. +      reset_dquot_ptrs(dev, cnt);
  625. +      invalidate_dquots(dev, cnt);
  626. +      close_fp(vfsmnt->mnt_quotas[cnt], 0);
  627. +      vfsmnt->mnt_quotas[cnt] = (struct file *)0;
  628. +      vfsmnt->mnt_iexp[cnt] = vfsmnt->mnt_bexp[cnt] = (time_t)0;
  629. +      vfsmnt->mnt_flags &= ~QF_CLOSING;
  630. +   }
  631. +   return 0;
  632. +}
  633. +
  634. +static int quota_on(dev_t dev, short type, char *path)
  635. +{
  636. +   struct file *filp = (struct file *)0;
  637. +   struct vfsmount *vfsmnt;
  638. +   struct inode *inode;
  639. +   struct dquot *dquot;
  640. +   char *tmp;
  641. +   int error;
  642. +
  643. +   if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0)
  644. +      return -ENODEV;
  645. +   if (vfsmnt->mnt_quotas[type] != (struct file *)0)
  646. +      return -EBUSY;
  647. +   if ((error = getname(path, &tmp)) != 0)
  648. +      return (error);
  649. +   vfsmnt->mnt_flags |= QF_OPENING;
  650. +   error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
  651. +   putname(tmp);
  652. +   if (error) {
  653. +      vfsmnt->mnt_flags &= ~QF_OPENING;
  654. +      return (error);
  655. +   }
  656. +   if (!S_ISREG(inode->i_mode)) {
  657. +      vfsmnt->mnt_flags &= ~QF_OPENING;
  658. +      iput(inode);
  659. +      return -EACCES;
  660. +   }
  661. +   if (!inode->i_op || !inode->i_op->default_file_ops)
  662. +      goto end_quotaon;
  663. +   if ((filp = get_empty_filp()) == (struct file *)0)
  664. +      goto end_quotaon;
  665. +   filp->f_mode = (O_RDWR + 1) & O_ACCMODE;
  666. +   filp->f_flags = O_RDWR;
  667. +   filp->f_inode = inode;
  668. +   filp->f_pos = 0;
  669. +   filp->f_reada = 0;
  670. +   filp->f_op = inode->i_op->default_file_ops;
  671. +   if (filp->f_op->open)
  672. +      if (filp->f_op->open(filp->f_inode, filp))
  673. +         goto end_quotaon;
  674. +   if (!filp->f_op->read || !filp->f_op->write)
  675. +      goto end_quotaon;
  676. +   vfsmnt->mnt_quotas[type] = filp;
  677. +   vfs_open(filp);
  678. +   vfsmnt->mnt_flags &= ~QF_OPENING;
  679. +   dquot = dqget(dev, 0, type);
  680. +   vfsmnt->mnt_iexp[type] = (dquot) ? dquot->dq_itime : MAX_IQ_TIME;
  681. +   vfsmnt->mnt_bexp[type] = (dquot) ? dquot->dq_btime : MAX_DQ_TIME;
  682. +   dqput(dquot);
  683. +   add_dquot_ref(dev, type);
  684. +   return 0;
  685. +end_quotaon:
  686. +   vfsmnt->mnt_flags &= ~QF_OPENING;
  687. +   if (filp != (struct file *)0)
  688. +      filp->f_count--;
  689. +   iput(inode);
  690. +   return -EIO;
  691. +}
  692. +
  693. +/*
  694. + * Just like iput, decrement referencecount of dquot.
  695. + */
  696. +void dqput(struct dquot *dquot)
  697. +{
  698. +   if (!dquot)
  699. +      return;
  700. +   /*
  701. +    * If the dq_mnt pointer isn't initialized this entry needs no
  702. +    * checking and doesn't need to be written. It just an empty
  703. +    * dquot that is put back into the freelist.
  704. +    */
  705. +   if (dquot->dq_mnt != (struct vfsmount *)0) {
  706. +      wait_on_dquot(dquot);
  707. +      if (!dquot->dq_count) {
  708. +         printk("VFS: iput: trying to free free dquot\n");
  709. +         printk("VFS: device %d/%d, dquot of %s %d\n",
  710. +                MAJOR(dquot->dq_dev), MINOR(dquot->dq_dev),
  711. +                quotatypes[dquot->dq_type], dquot->dq_id);
  712. +         return;
  713. +      }
  714. +repeat:
  715. +      if (dquot->dq_count > 1) {
  716. +         dquot->dq_count--;
  717. +         return;
  718. +      }
  719. +      wake_up(&dquot_wait);
  720. +      if (dquot->dq_flags & DQ_MOD) {
  721. +         write_dquot(dquot);   /* we can sleep - so do again */
  722. +         wait_on_dquot(dquot);
  723. +         goto repeat;
  724. +      }
  725. +   }
  726. +   if (dquot->dq_count) {
  727. +      dquot->dq_count--;
  728. +      nr_free_dquots++;
  729. +   }
  730. +   return;
  731. +}
  732. +
  733. +static struct dquot *get_empty_dquot(void)
  734. +{
  735. +   struct dquot *dquot, *best;
  736. +   int i;
  737. +
  738. +   if (nr_dquots < NR_DQUOTS && nr_free_dquots < (nr_dquots >> 2))
  739. +      grow_dquots();
  740. +
  741. +repeat:
  742. +   dquot = first_dquot;
  743. +   best = NODQUOT;
  744. +   for (i = 0; i < nr_dquots; dquot = dquot->dq_next, i++) {
  745. +      if (!dquot->dq_count) {
  746. +         if (!best)
  747. +            best = dquot;
  748. +         if (!(dquot->dq_flags & DQ_MOD) && !(dquot->dq_flags & DQ_LOCKED)) {
  749. +            best = dquot;
  750. +            break;
  751. +         }
  752. +      }
  753. +   }
  754. +   if (!best || best->dq_flags & DQ_MOD || best->dq_flags & DQ_LOCKED)
  755. +      if (nr_dquots < NR_DQUOTS) {
  756. +         grow_dquots();
  757. +         goto repeat;
  758. +      }
  759. +   dquot = best;
  760. +   if (!dquot) {
  761. +      printk("VFS: No free dquots - contact mvw@mcs.ow.org\n");
  762. +      sleep_on(&dquot_wait);
  763. +      goto repeat;
  764. +   }
  765. +   if (dquot->dq_flags & DQ_LOCKED) {
  766. +      wait_on_dquot(dquot);
  767. +      goto repeat;
  768. +   }
  769. +   if (dquot->dq_flags & DQ_MOD) {
  770. +      write_dquot(dquot);
  771. +      goto repeat;
  772. +   }
  773. +   if (dquot->dq_count)
  774. +      goto repeat;
  775. +   clear_dquot(dquot);
  776. +   dquot->dq_count = 1;
  777. +   nr_free_dquots--;
  778. +   if (nr_free_dquots < 0) {
  779. +      printk ("VFS: get_empty_dquot: bad free dquot count.\n");
  780. +      nr_free_dquots = 0;
  781. +   }
  782. +   return dquot;
  783. +}
  784. +
  785. +/*
  786. + * Just like iget, increment referencecount of a dquot and return
  787. + * pointer to it in the hashqueue.
  788. + */
  789. +struct dquot *dqget(dev_t dev, unsigned int id, short type)
  790. +{
  791. +   struct dquot *dquot, *empty;
  792. +   struct vfsmount *vfsmnt;
  793. +
  794. +   if ((vfsmnt = lookup_vfsmnt(dev)) == (struct vfsmount *)0 ||
  795. +       (vfsmnt->mnt_flags & (QF_OPENING | QF_CLOSING)) ||
  796. +       (vfsmnt->mnt_quotas[type] == (struct file *)0))
  797. +      return (NODQUOT);
  798. +   empty = get_empty_dquot();
  799. +repeat:
  800. +   dquot = *(hash(dev, id, type));
  801. +   while (dquot) {
  802. +      if (dquot->dq_dev != dev || dquot->dq_id != id) {
  803. +         dquot = dquot->dq_hash_next;
  804. +         continue;
  805. +      }
  806. +      wait_on_dquot(dquot);
  807. +      if (dquot->dq_dev != dev || dquot->dq_id != id)
  808. +         goto repeat;
  809. +      if (!dquot->dq_count)
  810. +         nr_free_dquots--;
  811. +      dquot->dq_count++;
  812. +      if (empty)
  813. +         dqput(empty);
  814. +      return dquot;
  815. +   }
  816. +   if (!empty)
  817. +      return (NODQUOT);
  818. +   dquot = empty;
  819. +   dquot->dq_id = id;
  820. +   dquot->dq_type = type;
  821. +   dquot->dq_dev = dev;
  822. +   dquot->dq_mnt = vfsmnt;
  823. +   put_last_free(dquot);
  824. +   insert_dquot_hash(dquot);
  825. +   read_dquot(dquot);
  826. +   return dquot;
  827. +}
  828. +
  829. +/*
  830. + * Initialize pointer in a inode to the right dquots.
  831. + * Be smart and increment count only if already valid pointervalue.
  832. + */
  833. +void getinoquota(struct inode *inode, short type)
  834. +{
  835. +   unsigned int id = 0;
  836. +   short cnt;
  837. +
  838. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  839. +      if (type != -1 && cnt != type)
  840. +         continue;
  841. +      if (inode->i_dquot[cnt] != NODQUOT) {
  842. +         inode->i_dquot[cnt]->dq_count++;
  843. +         continue;
  844. +      }
  845. +      switch (cnt) {
  846. +         case USRQUOTA:
  847. +            id = inode->i_uid;
  848. +            break;
  849. +         case GRPQUOTA:
  850. +            id = inode->i_gid;
  851. +            break;
  852. +      }
  853. +      inode->i_dquot[cnt] = dqget(inode->i_dev, id, cnt);
  854. +   }
  855. +}
  856. +
  857. +void putinoquota(struct inode *inode)
  858. +{
  859. +   short cnt;
  860. +
  861. +   for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  862. +      if (inode->i_dquot[cnt] == NODQUOT)
  863. +         continue;
  864. +      dqput(inode->i_dquot[cnt]);
  865. +      if (!inode->i_writecount)
  866. +         inode->i_dquot[cnt] = NODQUOT;
  867. +   }
  868. +}
  869. +
  870. +/*
  871. + * This are two simple algorithms that calculates the size of a file in blocks
  872. + * and from a number of blocks to a isize.
  873. + * It is not perfect but works most of the time.
  874. + */
  875. +u_long isize_to_blocks(size_t isize, size_t blksize)
  876. +{
  877. +   u_long blocks;
  878. +   u_long indirect;
  879. +
  880. +   if (!blksize)
  881. +      blksize = BLOCK_SIZE;
  882. +   blocks = (isize / blksize) + ((isize % blksize) ? 1 : 0);
  883. +   if (blocks > 10) {
  884. +      indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
  885. +      if (blocks > (10 + 256)) {
  886. +         indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
  887. +         if (blocks > (10 + 256 + (256 << 8)))
  888. +            indirect++; /* triple indirect blocks */
  889. +      }
  890. +      blocks += indirect;
  891. +   }
  892. +   return blocks;
  893. +}
  894. +
  895. +size_t blocks_to_isize(u_long blocks, size_t blksize)
  896. +{
  897. +   size_t isize;
  898. +   u_long indirect;
  899. +
  900. +   if (!blksize)
  901. +      blksize = BLOCK_SIZE;
  902. +   isize = blocks * blksize;
  903. +   if (blocks > 10) {
  904. +      indirect = ((blocks - 11) >> 8) + 1; /* single indirect blocks */
  905. +      if (blocks > (10 + 256)) {
  906. +         indirect += ((blocks - 267) >> 16) + 1; /* double indirect blocks */
  907. +         if (blocks > (10 + 256 + (256 << 8)))
  908. +            indirect++; /* triple indirect blocks */
  909. +      }
  910. +      isize -= indirect * blksize;
  911. +   }
  912. +   return isize;
  913. +}
  914. +
  915. +/*
  916. + * Allocate the number of inodes and blocks from a diskquota.
  917. + */
  918. +int quota_alloc(struct inode *inode, u_long wanted_inodes, u_long wanted_blocks,
  919. +                u_long *avail_blocks)
  920. +{
  921. +   u_long availblocks, local_avail;
  922. +   unsigned short cnt;
  923. +
  924. +   availblocks = wanted_blocks;
  925. +   if (wanted_inodes > 0 || wanted_blocks > 0) {
  926. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  927. +         if (inode->i_dquot[cnt] == NODQUOT)
  928. +            continue;
  929. +         if (check_idq(inode->i_dquot[cnt], inode->i_dquot[cnt]->dq_id,
  930. +                       cnt, wanted_inodes) == NO_QUOTA ||
  931. +             check_bdq(inode->i_dquot[cnt], inode->i_dquot[cnt]->dq_id,
  932. +                       cnt, wanted_blocks, &local_avail) == NO_QUOTA)
  933. +            return NO_QUOTA;
  934. +         availblocks = min(availblocks, local_avail);
  935. +      }
  936. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  937. +         if (inode->i_dquot[cnt] == NODQUOT)
  938. +            continue;
  939. +         incr_quota(inode->i_dquot[cnt], wanted_inodes, availblocks);
  940. +      }
  941. +   }
  942. +   if (avail_blocks != (u_long *)0)
  943. +      *avail_blocks = availblocks;
  944. +   return QUOTA_OK;
  945. +   /* NOTREACHED */
  946. +}
  947. +
  948. +/*
  949. + * Remove the number of inodes and blocks from a diskquota.
  950. + */
  951. +void quota_remove(struct inode *inode, u_long inodes, u_long blocks)
  952. +{
  953. +   short cnt;
  954. +
  955. +   if (inodes > 0 || blocks > 0) {
  956. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  957. +         if (inode->i_dquot[cnt] == NODQUOT)
  958. +            continue;
  959. +         decr_quota(inode->i_dquot[cnt], inodes, blocks);
  960. +      }
  961. +   }
  962. +}
  963. +
  964. +/*
  965. + * Transfer the number of inode and blocks from one diskquota to an other.
  966. + */
  967. +int quota_transfer(struct inode *inode, uid_t newuid, gid_t newgid,
  968. +                   u_long inodes, u_long blocks)
  969. +{
  970. +   struct dquot *transfer_to[MAXQUOTAS];
  971. +   u_long availblocks;
  972. +   unsigned int id = 0;
  973. +   short cnt, disc;
  974. +
  975. +   if (inodes > 0 || blocks > 0) {
  976. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  977. +         transfer_to[cnt] = NODQUOT;
  978. +         switch(cnt) {
  979. +            case USRQUOTA:
  980. +               if (inode->i_uid == newuid)
  981. +                  continue;
  982. +               id = newuid;
  983. +               break;
  984. +            case GRPQUOTA:
  985. +               if (inode->i_gid == newgid)
  986. +                  continue;
  987. +               id = newgid;
  988. +               break;
  989. +         }
  990. +         if ((transfer_to[cnt] = dqget(inode->i_dev, id, cnt)) == NODQUOT)
  991. +            continue;
  992. +
  993. +         if (check_idq(transfer_to[cnt], id, cnt, inodes) == NO_QUOTA ||
  994. +             check_bdq(transfer_to[cnt], id, cnt, blocks, &availblocks) == NO_QUOTA ||
  995. +             availblocks != blocks) {
  996. +            for (disc = 0; disc <= cnt; disc++)
  997. +               dqput(transfer_to[disc]);
  998. +            return NO_QUOTA;
  999. +         }
  1000. +      }
  1001. +      for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
  1002. +         if (transfer_to[cnt] == NODQUOT)
  1003. +            continue;
  1004. +         decr_quota(inode->i_dquot[cnt], inodes, blocks);
  1005. +         incr_quota(transfer_to[cnt], inodes, blocks);
  1006. +         transfer_to[cnt]->dq_count += inode->i_writecount;
  1007. +         inode->i_dquot[cnt]->dq_count -= inode->i_writecount;
  1008. +         dqput(inode->i_dquot[cnt]);
  1009. +         inode->i_dquot[cnt] = transfer_to[cnt];
  1010. +      }
  1011. +   }
  1012. +   return QUOTA_OK;
  1013. +   /* NOTREACHED */
  1014. +}
  1015. +
  1016. +void quota_init(void)
  1017. +{
  1018. +   memset(hash_table, 0, sizeof(hash_table));
  1019. +   first_dquot = NODQUOT;
  1020. +}
  1021. +
  1022. +/*
  1023. + * Ok this is the systemcall interface, this communicates with
  1024. + * the userlevel programs.
  1025. + */
  1026. +asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
  1027. +{
  1028. +   int cmds = 0, type = 0, flags = 0;
  1029. +   struct vfsmount *vfsmnt;
  1030. +   struct inode *ino;
  1031. +   dev_t dev;
  1032. +
  1033. +   cmds = cmd >> SUBCMDSHIFT;
  1034. +   type = cmd & SUBCMDMASK;
  1035. +
  1036. +   if ((u_int) type >= MAXQUOTAS)
  1037. +      return -EINVAL;
  1038. +   switch (cmds) {
  1039. +      case Q_SYNC:
  1040. +         break;
  1041. +      case Q_GETQUOTA:
  1042. +         if (((type == USRQUOTA && current->uid != id) ||
  1043. +              (type == GRPQUOTA && current->gid != id)) && !suser())
  1044. +            return -EPERM;
  1045. +         break;
  1046. +      default:
  1047. +         if (!suser())
  1048. +            return -EPERM;
  1049. +   }
  1050. +
  1051. +   if (special == (char *)0 && cmds == Q_SYNC)
  1052. +      dev = 0;
  1053. +   else {
  1054. +      if (namei(special, &ino))
  1055. +         return -EINVAL;
  1056. +      dev = ino->i_rdev;
  1057. +      if (!S_ISBLK(ino->i_mode)) {
  1058. +         iput(ino);
  1059. +         return -ENOTBLK;
  1060. +      }
  1061. +      iput(ino);
  1062. +   }
  1063. +
  1064. +   switch (cmds) {
  1065. +      case Q_QUOTAON:
  1066. +         return quota_on(dev, type, (char *) addr);
  1067. +      case Q_QUOTAOFF:
  1068. +         return quota_off(dev, type);
  1069. +      case Q_GETQUOTA:
  1070. +         return get_quota(dev, id, type, (struct dqblk *) addr);
  1071. +      case Q_SETQUOTA:
  1072. +         flags |= SET_QUOTA;
  1073. +         break;
  1074. +      case Q_SETUSE:
  1075. +         flags |= SET_USE;
  1076. +         break;
  1077. +      case Q_SETQLIM:
  1078. +         flags |= SET_QLIMIT;
  1079. +         break;
  1080. +      case Q_SYNC:
  1081. +         return sync_dquots(dev, type);
  1082. +      default:
  1083. +         return -EINVAL;
  1084. +   }
  1085. +
  1086. +   flags |= QUOTA_SYSCALL;
  1087. +   if ((vfsmnt = lookup_vfsmnt(dev)) != (struct vfsmount *)0 &&
  1088. +        vfsmnt->mnt_quotas[type] != (struct file *)0)
  1089. +      return set_dqblk(dev, id, type, flags, (struct dqblk *) addr);
  1090. +   return -ESRCH;
  1091. +   /* NOTREACHED */
  1092. +}
  1093. +
  1094. +#else
  1095. +
  1096. +asmlinkage int sys_quotactl(int cmd, const char *special, int id, caddr_t addr)
  1097. +{
  1098. +   return -ENOSYS;
  1099. +}
  1100. +
  1101. +#endif /* CONFIG_QUOTA */
  1102. +
  1103. diff -ru --new-file linux_1.1.54/fs/exec.c linux_1.1.54_owld/fs/exec.c
  1104. --- linux_1.1.54/fs/exec.c    Sun Oct 16 00:26:31 1994
  1105. +++ linux_1.1.54_owld/fs/exec.c    Sun Oct 16 00:28:21 1994
  1106. @@ -43,6 +43,7 @@
  1107.  
  1108.  #include <linux/binfmts.h>
  1109.  #include <linux/personality.h>
  1110. +#include <linux/fileio.h>
  1111.  
  1112.  #include <asm/segment.h>
  1113.  #include <asm/system.h>
  1114. @@ -137,6 +138,7 @@
  1115.              return error;
  1116.          }
  1117.      }
  1118. +    vfs_open(f);
  1119.      inode->i_count++;
  1120.      return fd;
  1121.  }
  1122. @@ -146,7 +148,7 @@
  1123.   * macros to write out all the necessary info.
  1124.   */
  1125.  #define DUMP_WRITE(addr,nr) \
  1126. -while (file.f_op->write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  1127. +while (vfs_write(inode,&file,(char *)(addr),(nr)) != (nr)) goto close_coredump
  1128.  
  1129.  #define DUMP_SEEK(offset) \
  1130.  if (file.f_op->lseek) { \
  1131. @@ -154,6 +156,8 @@
  1132.           goto close_coredump; \
  1133.  } else file.f_pos = (offset)        
  1134.  
  1135. +extern int close_fp(struct file *filp, unsigned int fd);
  1136. +
  1137.  /*
  1138.   * Routine writes a core dump image in the current directory.
  1139.   * Currently only a stub-function.
  1140. @@ -207,9 +211,11 @@
  1141.      if (file.f_op->open)
  1142.          if (file.f_op->open(inode,&file))
  1143.              goto end_coredump;
  1144. +    vfs_open(&file);
  1145.      if (!file.f_op->write)
  1146.          goto close_coredump;
  1147.      has_dumped = 1;
  1148. +    current->flags |= PF_DUMPCORE;
  1149.  /* changed the size calculations - should hopefully work better. lbt */
  1150.      dump.magic = CMAGIC;
  1151.      dump.start_code = 0;
  1152. @@ -271,8 +277,9 @@
  1153.      set_fs(KERNEL_DS);
  1154.      DUMP_WRITE(current,sizeof(*current));
  1155.  close_coredump:
  1156. -    if (file.f_op->release)
  1157. -        file.f_op->release(inode,&file);
  1158. +    close_fp(&file, 0);
  1159. +    set_fs(fs);
  1160. +    return has_dumped;
  1161.  end_coredump:
  1162.      set_fs(fs);
  1163.      iput(inode);
  1164. @@ -824,6 +831,8 @@
  1165.      current->mm->mmap = NULL;
  1166.      current->suid = current->euid = current->fsuid = bprm->e_uid;
  1167.      current->sgid = current->egid = current->fsgid = bprm->e_gid;
  1168. +    current->flags &= ~PF_FORKNOEXEC; /* accounting flags */
  1169. +    current->io_usage = 0;
  1170.      if (N_MAGIC(ex) == OMAGIC) {
  1171.          do_mmap(NULL, 0, ex.a_text+ex.a_data,
  1172.              PROT_READ|PROT_WRITE|PROT_EXEC,
  1173. diff -ru --new-file linux_1.1.54/fs/ext2/super.c linux_1.1.54_owld/fs/ext2/super.c
  1174. --- linux_1.1.54/fs/ext2/super.c    Fri Aug 19 18:59:30 1994
  1175. +++ linux_1.1.54_owld/fs/ext2/super.c    Fri Aug 19 19:00:26 1994
  1176. @@ -260,11 +260,8 @@
  1177.                  return 0;
  1178.              }
  1179.          }
  1180. -        else {
  1181. -            printk ("EXT2-fs: Unrecognized mount option %s\n", this_char);
  1182. -            return 0;
  1183. +        else return 1;
  1184.          }
  1185. -    }
  1186.      return 1;
  1187.  }
  1188.  
  1189. diff -ru --new-file linux_1.1.54/fs/fcntl.c linux_1.1.54_owld/fs/fcntl.c
  1190. --- linux_1.1.54/fs/fcntl.c    Fri Aug 19 18:59:30 1994
  1191. +++ linux_1.1.54_owld/fs/fcntl.c    Fri Aug 19 19:00:27 1994
  1192. @@ -12,6 +12,7 @@
  1193.  #include <linux/stat.h>
  1194.  #include <linux/fcntl.h>
  1195.  #include <linux/string.h>
  1196. +#include <linux/fileio.h>
  1197.  
  1198.  extern int fcntl_getlk(unsigned int, struct flock *);
  1199.  extern int fcntl_setlk(unsigned int, unsigned int, struct flock *);
  1200. @@ -32,6 +33,7 @@
  1201.          return -EMFILE;
  1202.      FD_CLR(arg, ¤t->files->close_on_exec);
  1203.      (current->files->fd[arg] = current->files->fd[fd])->f_count++;
  1204. +       vfs_open(current->files->fd[fd]);
  1205.      return arg;
  1206.  }
  1207.  
  1208. diff -ru --new-file linux_1.1.54/fs/file_table.c linux_1.1.54_owld/fs/file_table.c
  1209. --- linux_1.1.54/fs/file_table.c    Mon Apr 18 22:42:14 1994
  1210. +++ linux_1.1.54_owld/fs/file_table.c    Fri May  6 21:37:29 1994
  1211. @@ -7,6 +7,7 @@
  1212.  #include <linux/fs.h>
  1213.  #include <linux/string.h>
  1214.  #include <linux/mm.h>
  1215. +#include <linux/config.h>
  1216.  
  1217.  struct file * first_file;
  1218.  int nr_files = 0;
  1219. @@ -87,3 +88,34 @@
  1220.      }
  1221.      return NULL;
  1222.  }
  1223. +
  1224. +#ifdef CONFIG_QUOTA
  1225. +void add_dquot_ref(dev_t dev, short type)
  1226. +{
  1227. +    struct file *filp;
  1228. +    int i;
  1229. +
  1230. +    /* Check files that are currently opened for writing. */
  1231. +    for (filp = first_file, i = 0; i < nr_files; i++, filp = filp->f_next) {
  1232. +        if (!filp->f_count || !filp->f_inode || filp->f_inode->i_dev != dev)
  1233. +            continue;
  1234. +        if (filp->f_inode->i_writecount > 0) {
  1235. +            getinoquota(filp->f_inode, type);
  1236. +            if (filp->f_inode->i_dquot[type] != NODQUOT)
  1237. +                filp->f_inode->i_dquot[type]->dq_count +=
  1238. +                (filp->f_inode->i_writecount - 1);
  1239. +        }
  1240. +    }
  1241. +}
  1242. +
  1243. +void reset_dquot_ptrs(dev_t dev, short type)
  1244. +{
  1245. +    struct file *filp;
  1246. +    int i;
  1247. +
  1248. +    for (filp = first_file, i = 0; i < nr_files; i++, filp = filp->f_next)
  1249. +        if (filp->f_count && filp->f_inode &&
  1250. +            filp->f_inode->i_writecount && filp->f_inode->i_dev == dev)
  1251. +            filp->f_inode->i_dquot[type] = NODQUOT;
  1252. +}
  1253. +#endif
  1254. diff -ru --new-file linux_1.1.54/fs/fileio.c linux_1.1.54_owld/fs/fileio.c
  1255. --- linux_1.1.54/fs/fileio.c
  1256. +++ linux_1.1.54_owld/fs/fileio.c    Mon Oct 17 17:00:00 1994
  1257. @@ -0,0 +1,379 @@
  1258. +/*
  1259. + *
  1260. + * Simple VFS definitions for fileio.
  1261. + *
  1262. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  1263. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  1264. + *
  1265. + * Version: $Id: fileio.c,v 1.10 1994/10/17 15:59:26 mvw Exp mvw $
  1266. + *
  1267. + */
  1268. +
  1269. +#include <linux/config.h>
  1270. +#include <linux/kernel.h>
  1271. +#include <linux/sched.h>
  1272. +#include <linux/stat.h>
  1273. +#include <linux/string.h>
  1274. +#include <linux/fcntl.h>
  1275. +
  1276. +#ifdef CONFIG_QUOTA
  1277. +extern int lookup(struct inode *, const char *, int, struct inode **);
  1278. +
  1279. +int vfs_write(struct inode *inode, struct file *filp, char *addr, size_t bytes)
  1280. +{
  1281. +   size_t written;
  1282. +   u_long cur_blocks, wanted_blocks = 0, avail_blocks = 0;
  1283. +
  1284. +   if (S_ISREG(inode->i_mode)) {
  1285. +      cur_blocks = isize_to_blocks(inode->i_size, inode->i_blksize);
  1286. +      if ((filp->f_pos + bytes) > inode->i_size) {
  1287. +         wanted_blocks = isize_to_blocks(filp->f_pos + bytes,
  1288. +                         inode->i_blksize) - cur_blocks;
  1289. +         if (wanted_blocks && quota_alloc(inode, 0, wanted_blocks,
  1290. +                                          &avail_blocks) == NO_QUOTA)
  1291. +            return -EDQUOT;
  1292. +         if (wanted_blocks && (avail_blocks < wanted_blocks))
  1293. +            bytes = blocks_to_isize((cur_blocks + avail_blocks),
  1294. +                    inode->i_blksize) - filp->f_pos;
  1295. +      }
  1296. +      if ((written = filp->f_op->write(inode, filp, addr, bytes)) != bytes) {
  1297. +         quota_remove(inode, 0, avail_blocks -
  1298. +                     (isize_to_blocks(inode->i_size, inode->i_blksize) -
  1299. +                      isize_to_blocks((inode->i_size - written), inode->i_blksize)));
  1300. +      }
  1301. +      current->io_usage += written;
  1302. +      if (wanted_blocks && (avail_blocks < wanted_blocks))
  1303. +         return -EDQUOT;
  1304. +
  1305. +      return written;
  1306. +   } else {
  1307. +      current->io_usage += bytes;
  1308. +      return filp->f_op->write(inode, filp, (char *)addr, bytes);
  1309. +   }
  1310. +}
  1311. +
  1312. +int vfs_create(struct inode *dir, const char *basename,
  1313. +               int namelen, int mode, struct inode **res_ino)
  1314. +{
  1315. +   int error;
  1316. +   struct inode new_inode;
  1317. +
  1318. +   memset(&new_inode, 0, sizeof(struct inode));
  1319. +   new_inode.i_dev = dir->i_dev;
  1320. +   new_inode.i_uid = current->fsuid;
  1321. +   new_inode.i_gid = current->fsgid;
  1322. +   getinoquota(&new_inode, -1);
  1323. +
  1324. +   if (quota_alloc(&new_inode, 1, 0, (u_long *)0) == NO_QUOTA) {
  1325. +      putinoquota(&new_inode);
  1326. +      return -EDQUOT;
  1327. +   }
  1328. +   error = dir->i_op->create(dir, basename, namelen, mode, res_ino);
  1329. +   if (error)
  1330. +      quota_remove(&new_inode, 1, 0);
  1331. +   putinoquota(&new_inode);
  1332. +
  1333. +   return error;
  1334. +}
  1335. +
  1336. +int vfs_truncate(struct inode *ino, size_t lenght)
  1337. +{
  1338. +   int error;
  1339. +   size_t old_isize;
  1340. +
  1341. +   old_isize = ino->i_size;
  1342. +   ino->i_size = lenght;
  1343. +   if (ino->i_op && ino->i_op->truncate)
  1344. +      ino->i_op->truncate(ino);
  1345. +   ino->i_ctime = ino->i_mtime = CURRENT_TIME;
  1346. +   ino->i_dirt = 1;
  1347. +   if ((error = notify_change(NOTIFY_SIZE, ino)))
  1348. +      return error;
  1349. +   getinoquota(ino, -1);
  1350. +   quota_remove(ino, 0, isize_to_blocks(old_isize, ino->i_blksize));
  1351. +   putinoquota(ino);
  1352. +
  1353. +   return error;
  1354. +}
  1355. +
  1356. +int vfs_mknod(struct inode *dir, const char *basename,
  1357. +              int namelen, int mode, dev_t dev)
  1358. +{
  1359. +   int error;
  1360. +   struct inode new_inode;
  1361. +
  1362. +   memset(&new_inode, 0, sizeof(struct inode));
  1363. +   new_inode.i_dev = dir->i_dev;
  1364. +   new_inode.i_uid = current->fsuid;
  1365. +   new_inode.i_gid = current->fsgid;
  1366. +   getinoquota(&new_inode, -1);
  1367. +
  1368. +   if (quota_alloc(&new_inode, 1, 0, (u_long *)0) == NO_QUOTA) {
  1369. +      putinoquota(&new_inode);
  1370. +      iput(dir);
  1371. +      return -EDQUOT;
  1372. +   }
  1373. +   dir->i_count++;
  1374. +   error = dir->i_op->mknod(dir, basename, namelen, mode, dev);
  1375. +   if (error)
  1376. +      quota_remove(&new_inode, 1, 0);
  1377. +   putinoquota(&new_inode);
  1378. +   iput(dir);
  1379. +
  1380. +   return error;
  1381. +}
  1382. +
  1383. +int vfs_mkdir(struct inode *dir, const char *basename, int namelen, int mode)
  1384. +{
  1385. +   int error;
  1386. +   struct inode new_inode;
  1387. +
  1388. +   memset(&new_inode, 0, sizeof(struct inode));
  1389. +   new_inode.i_dev = dir->i_dev;
  1390. +   new_inode.i_uid = current->fsuid;
  1391. +   new_inode.i_gid = current->fsgid;
  1392. +   getinoquota(&new_inode, -1);
  1393. +
  1394. +   if (quota_alloc(&new_inode, 1, 1, (u_long *)0) == NO_QUOTA) {
  1395. +      putinoquota(&new_inode);
  1396. +      iput(dir);
  1397. +      return -EDQUOT;
  1398. +   }
  1399. +   dir->i_count++;
  1400. +   error = dir->i_op->mkdir(dir, basename, namelen, mode);
  1401. +   if (error)
  1402. +      quota_remove(&new_inode, 1, 1);
  1403. +   putinoquota(&new_inode);
  1404. +   iput(dir);
  1405. +
  1406. +   return error;
  1407. +}
  1408. +
  1409. +int vfs_rmdir(struct inode *dir, const char *basename, int namelen)
  1410. +{
  1411. +   int error;
  1412. +   struct inode *old_inode;
  1413. +
  1414. +   /*
  1415. +    * Need inode entry of directory for quota operations
  1416. +    */
  1417. +   dir->i_count++;
  1418. +   if ((error = lookup(dir, basename, namelen, &old_inode))) {
  1419. +      iput(dir);
  1420. +      return error;
  1421. +   }
  1422. +   getinoquota(old_inode, -1);
  1423. +   if (!(error = dir->i_op->rmdir(dir, basename, namelen)))
  1424. +      quota_remove(old_inode, 1, 1);
  1425. +   putinoquota(old_inode);
  1426. +   iput(old_inode);
  1427. +
  1428. +   return error;
  1429. +}
  1430. +
  1431. +int vfs_unlink(struct inode *dir, const char *basename, int namelen)
  1432. +{
  1433. +   int error;
  1434. +   struct inode *old_inode;
  1435. +
  1436. +   /*
  1437. +    * Need inode info of to remove file for quota operations.
  1438. +    */
  1439. +   dir->i_count++;
  1440. +   if ((error = lookup(dir, basename, namelen, &old_inode))) {
  1441. +      iput(dir);
  1442. +      return error;
  1443. +   }
  1444. +   getinoquota(old_inode, -1);
  1445. +   error = dir->i_op->unlink(dir, basename, namelen);
  1446. +   /*
  1447. +    * Remove blocks and inode. Only if link-count is 0 !
  1448. +    */
  1449. +   if (!error && old_inode->i_nlink == 0)
  1450. +      quota_remove(old_inode, 1,
  1451. +                   isize_to_blocks(old_inode->i_size, old_inode->i_blksize));
  1452. +   putinoquota(old_inode);
  1453. +   iput(old_inode);
  1454. +
  1455. +   return error;
  1456. +}
  1457. +
  1458. +int vfs_symlink(struct inode *dir, const char *basename,
  1459. +                int namelen, const char *oldname)
  1460. +{
  1461. +   int error;
  1462. +   struct inode new_inode;
  1463. +
  1464. +   memset(&new_inode, 0, sizeof(struct inode));
  1465. +   new_inode.i_dev = dir->i_dev;
  1466. +   new_inode.i_uid = current->fsuid;
  1467. +   new_inode.i_gid = current->fsgid;
  1468. +   getinoquota(&new_inode, -1);
  1469. +
  1470. +   if (quota_alloc(&new_inode, 1, 1, (u_long *)0) == NO_QUOTA) {
  1471. +      putinoquota(&new_inode);
  1472. +      iput(dir);
  1473. +      return -EDQUOT;
  1474. +   }
  1475. +   dir->i_count++;
  1476. +   if (!(error = dir->i_op->symlink(dir, basename, namelen, oldname)))
  1477. +      quota_remove(&new_inode, 1, 1);
  1478. +   putinoquota(&new_inode);
  1479. +   iput(dir);
  1480. +
  1481. +   return error;
  1482. +}
  1483. +
  1484. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid)
  1485. +{
  1486. +   int error;
  1487. +   uid_t olduid, oldgid;
  1488. +   int notify_flag = 0;
  1489. +
  1490. +   olduid = ino->i_uid;
  1491. +   oldgid = ino->i_gid;
  1492. +   getinoquota(ino, -1);
  1493. +   if (quota_transfer(ino, uid, gid, 1,
  1494. +                      isize_to_blocks(ino->i_size,
  1495. +                      ino->i_blksize)) == NO_QUOTA) {
  1496. +      putinoquota(ino);
  1497. +      return -EDQUOT;
  1498. +   }
  1499. +   /*
  1500. +    * If the owner has been changed, remove the setuid bit
  1501. +    */
  1502. +   if (ino->i_uid != uid && ino->i_mode & S_ISUID) {
  1503. +      ino->i_mode &= ~S_ISUID;
  1504. +      notify_flag = NOTIFY_MODE;
  1505. +   }
  1506. +   /*
  1507. +    * If the group has been changed, remove the setgid bit
  1508. +    */
  1509. +   if (ino->i_gid != gid && ino->i_mode & S_ISGID) {
  1510. +      ino->i_mode &= ~S_ISGID;
  1511. +      notify_flag = NOTIFY_MODE;
  1512. +   }
  1513. +   ino->i_uid = uid;
  1514. +   ino->i_gid = gid;
  1515. +   notify_flag |= NOTIFY_UIDGID;
  1516. +   ino->i_ctime = CURRENT_TIME;
  1517. +   ino->i_dirt = 1;
  1518. +   if ((error = notify_change(notify_flag, ino)))
  1519. +      quota_transfer(ino, olduid, oldgid, 1,
  1520. +                     isize_to_blocks(ino->i_size, ino->i_blksize));
  1521. +   putinoquota(ino);
  1522. +   return error;
  1523. +}
  1524. +
  1525. +int vfs_rename(struct inode *old_dir, const char *old_base, int old_len,
  1526. +               struct inode *new_dir, const char *new_base, int new_len)
  1527. +{
  1528. +   int error;
  1529. +   struct inode *old_inode, *new_inode;
  1530. +
  1531. +   /*
  1532. +    * Check if target file already exists, drop quota of file if
  1533. +    * it already exists and is overwritten. Extra check needed for
  1534. +    * renames of file to the same file.
  1535. +    */
  1536. +   old_dir->i_count++;
  1537. +   if ((error = lookup(old_dir, old_base, old_len, &old_inode))) {
  1538. +      iput(old_dir);
  1539. +      iput(new_dir);
  1540. +      return error;
  1541. +   }
  1542. +   new_dir->i_count++;
  1543. +   if (!lookup(new_dir, new_base, new_len, &new_inode)) {
  1544. +      if (old_dir != new_dir && old_inode != new_inode) {
  1545. +         iput(old_inode);
  1546. +         error = old_dir->i_op->rename(old_dir, old_base, old_len, 
  1547. +                                       new_dir, new_base, new_len);
  1548. +         if (!error) {
  1549. +            getinoquota(new_inode, -1);
  1550. +            quota_remove(new_inode, 1,
  1551. +                         isize_to_blocks(new_inode->i_size, new_inode->i_blksize));
  1552. +            putinoquota(new_inode);
  1553. +            iput(new_inode);
  1554. +         }
  1555. +         return error;
  1556. +      }
  1557. +      iput(new_inode);
  1558. +   }
  1559. +   iput(old_inode);
  1560. +   return old_dir->i_op->rename(old_dir, old_base, old_len, 
  1561. +                                new_dir, new_base, new_len);
  1562. +}
  1563. +
  1564. +void vfs_open(struct file *filp)
  1565. +{
  1566. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2)) {
  1567. +      filp->f_inode->i_writecount++;
  1568. +      getinoquota(filp->f_inode, -1); 
  1569. +   }
  1570. +}
  1571. +
  1572. +void vfs_close(struct file *filp)
  1573. +{
  1574. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2)) {
  1575. +      filp->f_inode->i_writecount--;
  1576. +      putinoquota(filp->f_inode); 
  1577. +   }
  1578. +}
  1579. +
  1580. +#else /* CONFIG_QUOTA */
  1581. +
  1582. +int vfs_truncate(struct inode *ino, size_t lenght)
  1583. +{
  1584. +   int error;
  1585. +
  1586. +   ino->i_size = lenght;
  1587. +   if (ino->i_op && ino->i_op->truncate)
  1588. +      ino->i_op->truncate(ino);
  1589. +   if ((error = notify_change(NOTIFY_SIZE, ino))) {
  1590. +      return error;
  1591. +   }
  1592. +   ino->i_dirt = 1;
  1593. +
  1594. +   return error;
  1595. +}
  1596. +
  1597. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid)
  1598. +{
  1599. +   int notify_flag = 0;
  1600. +
  1601. +   /*
  1602. +    * If the owner has been changed, remove the setuid bit
  1603. +    */
  1604. +   if (ino->i_uid != uid && ino->i_mode & S_ISUID) {
  1605. +      ino->i_mode &= ~S_ISUID;
  1606. +      notify_flag = NOTIFY_MODE;
  1607. +   }
  1608. +   /*
  1609. +    * If the group has been changed, remove the setgid bit
  1610. +    */
  1611. +   if (ino->i_gid != gid && ino->i_mode & S_ISGID) {
  1612. +      ino->i_mode &= ~S_ISGID;
  1613. +      notify_flag = NOTIFY_MODE;
  1614. +   }
  1615. +   ino->i_uid = uid;
  1616. +   ino->i_gid = gid;
  1617. +   notify_flag |= NOTIFY_UIDGID;
  1618. +   ino->i_ctime = CURRENT_TIME;
  1619. +   ino->i_dirt = 1;
  1620. +   return(notify_change(notify_flag, ino));
  1621. +}
  1622. +
  1623. +void vfs_open(struct file *filp)
  1624. +{
  1625. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2))
  1626. +      filp->f_inode->i_writecount++;
  1627. +}
  1628. +
  1629. +void vfs_close(struct file *filp)
  1630. +{
  1631. +   if (filp->f_inode && S_ISREG(filp->f_inode->i_mode) && (filp->f_mode & 2))
  1632. +      filp->f_inode->i_writecount--;
  1633. +}
  1634. +
  1635. +#endif /* CONFIG_QUOTA */
  1636. +
  1637. diff -ru --new-file linux_1.1.54/fs/inode.c linux_1.1.54_owld/fs/inode.c
  1638. --- linux_1.1.54/fs/inode.c    Tue Aug 30 23:25:32 1994
  1639. +++ linux_1.1.54_owld/fs/inode.c    Tue Aug 30 23:26:07 1994
  1640. @@ -427,6 +427,7 @@
  1641.      struct inode_hash_entry * h;
  1642.      struct inode * inode;
  1643.      struct inode * empty = NULL;
  1644. +    short cnt;
  1645.  
  1646.      if (!sb)
  1647.          panic("VFS: iget with sb==NULL");
  1648. @@ -455,8 +456,11 @@
  1649.      goto return_it;
  1650.  
  1651.  found_it:
  1652. -    if (!inode->i_count)
  1653. +    if (!inode->i_count) {
  1654.          nr_free_inodes--;
  1655. +        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
  1656. +            inode->i_dquot[cnt] = NODQUOT;
  1657. +    }
  1658.      inode->i_count++;
  1659.      wait_on_inode(inode);
  1660.      if (inode->i_dev != sb->s_dev || inode->i_ino != nr) {
  1661. diff -ru --new-file linux_1.1.54/fs/isofs/inode.c linux_1.1.54_owld/fs/isofs/inode.c
  1662. --- linux_1.1.54/fs/isofs/inode.c    Thu Aug 11 15:40:16 1994
  1663. +++ linux_1.1.54_owld/fs/isofs/inode.c    Thu Aug 11 15:42:27 1994
  1664. @@ -124,7 +124,7 @@
  1665.              break;
  1666.            }
  1667.          }
  1668. -        else return 0;
  1669. +        else return 1;
  1670.      }
  1671.      return 1;
  1672.  }
  1673. diff -ru --new-file linux_1.1.54/fs/msdos/inode.c linux_1.1.54_owld/fs/msdos/inode.c
  1674. --- linux_1.1.54/fs/msdos/inode.c    Wed May  4 16:01:22 1994
  1675. +++ linux_1.1.54_owld/fs/msdos/inode.c    Wed May  4 17:34:45 1994
  1676. @@ -133,7 +133,7 @@
  1677.              if (value) return 0;
  1678.              *quiet = 1;
  1679.          }
  1680. -        else return 0;
  1681. +        else return 1;
  1682.      }
  1683.      return 1;
  1684.  }
  1685. diff -ru --new-file linux_1.1.54/fs/namei.c linux_1.1.54_owld/fs/namei.c
  1686. --- linux_1.1.54/fs/namei.c    Fri Aug 19 18:59:31 1994
  1687. +++ linux_1.1.54_owld/fs/namei.c    Fri Aug 19 19:01:33 1994
  1688. @@ -16,6 +16,7 @@
  1689.  #include <linux/string.h>
  1690.  #include <linux/fcntl.h>
  1691.  #include <linux/stat.h>
  1692. +#include <linux/fileio.h>
  1693.  
  1694.  #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
  1695.  
  1696. @@ -345,7 +346,7 @@
  1697.              error = -EROFS;
  1698.          else {
  1699.              dir->i_count++;        /* create eats the dir */
  1700. -            error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
  1701. +            error = vfs_create(dir,basename,namelen,mode,res_inode);
  1702.              up(&dir->i_sem);
  1703.              iput(dir);
  1704.              return error;
  1705. @@ -396,6 +397,7 @@
  1706.              }
  1707.           }
  1708.       }
  1709. +
  1710.      /*
  1711.       * An append-only file must be opened in append mode for writing
  1712.       */
  1713. @@ -403,16 +405,8 @@
  1714.          iput(inode);
  1715.          return -EPERM;
  1716.      }
  1717. -    if (flag & O_TRUNC) {
  1718. -          inode->i_size = 0;
  1719. -          if (inode->i_op && inode->i_op->truncate)
  1720. -               inode->i_op->truncate(inode);
  1721. -          if ((error = notify_change(NOTIFY_SIZE, inode))) {
  1722. -           iput(inode);
  1723. -           return error;
  1724. -          }
  1725. -          inode->i_dirt = 1;
  1726. -    }
  1727. +    if (flag & O_TRUNC)
  1728. +        vfs_truncate(inode, 0);
  1729.      *res_inode = inode;
  1730.      return 0;
  1731.  }
  1732. @@ -445,7 +439,7 @@
  1733.      }
  1734.      dir->i_count++;
  1735.      down(&dir->i_sem);
  1736. -    error = dir->i_op->mknod(dir,basename,namelen,mode,dev);
  1737. +    error = vfs_mknod(dir,basename,namelen,mode,dev);
  1738.      up(&dir->i_sem);
  1739.      iput(dir);
  1740.      return error;
  1741. @@ -502,7 +496,7 @@
  1742.      }
  1743.      dir->i_count++;
  1744.      down(&dir->i_sem);
  1745. -    error = dir->i_op->mkdir(dir,basename,namelen,mode);
  1746. +    error = vfs_mkdir(dir,basename,namelen,mode);
  1747.      up(&dir->i_sem);
  1748.      iput(dir);
  1749.      return error;
  1750. @@ -553,7 +547,7 @@
  1751.          iput(dir);
  1752.          return -EPERM;
  1753.      }
  1754. -    return dir->i_op->rmdir(dir,basename,namelen);
  1755. +    return vfs_rmdir(dir,basename,namelen);
  1756.  }
  1757.  
  1758.  asmlinkage int sys_rmdir(const char * pathname)
  1759. @@ -601,7 +595,7 @@
  1760.          iput(dir);
  1761.          return -EPERM;
  1762.      }
  1763. -    return dir->i_op->unlink(dir,basename,namelen);
  1764. +    return vfs_unlink(dir,basename,namelen);
  1765.  }
  1766.  
  1767.  asmlinkage int sys_unlink(const char * pathname)
  1768. @@ -644,7 +638,7 @@
  1769.      }
  1770.      dir->i_count++;
  1771.      down(&dir->i_sem);
  1772. -    error = dir->i_op->symlink(dir,basename,namelen,oldname);
  1773. +    error = vfs_symlink(dir,basename,namelen,oldname);
  1774.      up(&dir->i_sem);
  1775.      iput(dir);
  1776.      return error;
  1777. @@ -799,7 +793,7 @@
  1778.      }
  1779.      new_dir->i_count++;
  1780.      down(&new_dir->i_sem);
  1781. -    error = old_dir->i_op->rename(old_dir, old_base, old_len, 
  1782. +    error = vfs_rename(old_dir, old_base, old_len, 
  1783.          new_dir, new_base, new_len);
  1784.      up(&new_dir->i_sem);
  1785.      iput(new_dir);
  1786. diff -ru --new-file linux_1.1.54/fs/open.c linux_1.1.54_owld/fs/open.c
  1787. --- linux_1.1.54/fs/open.c    Fri Aug 19 18:59:31 1994
  1788. +++ linux_1.1.54_owld/fs/open.c    Fri Aug 19 19:04:17 1994
  1789. @@ -16,6 +16,7 @@
  1790.  #include <linux/signal.h>
  1791.  #include <linux/tty.h>
  1792.  #include <linux/time.h>
  1793. +#include <linux/fileio.h>
  1794.  
  1795.  #include <asm/segment.h>
  1796.  
  1797. @@ -85,12 +86,7 @@
  1798.          iput(inode);
  1799.          return -EPERM;
  1800.      }
  1801. -    inode->i_size = length;
  1802. -    if (inode->i_op && inode->i_op->truncate)
  1803. -        inode->i_op->truncate(inode);
  1804. -    inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  1805. -    inode->i_dirt = 1;
  1806. -    error = notify_change(NOTIFY_SIZE, inode);
  1807. +    error = vfs_truncate(inode, length);
  1808.      iput(inode);
  1809.      return error;
  1810.  }
  1811. @@ -108,12 +104,7 @@
  1812.          return -EACCES;
  1813.      if (IS_IMMUTABLE(inode) || IS_APPEND(inode))
  1814.          return -EPERM;
  1815. -    inode->i_size = length;
  1816. -    if (inode->i_op && inode->i_op->truncate)
  1817. -        inode->i_op->truncate(inode);
  1818. -    inode->i_ctime = inode->i_mtime = CURRENT_TIME;
  1819. -    inode->i_dirt = 1;
  1820. -    return notify_change(NOTIFY_SIZE, inode);
  1821. +    return vfs_truncate(inode, length);
  1822.  }
  1823.  
  1824.  /* If times==NULL, set access and modification to current time,
  1825. @@ -319,25 +310,7 @@
  1826.      if ((current->fsuid == inode->i_uid && user == inode->i_uid &&
  1827.           (in_group_p(group) || group == inode->i_gid)) ||
  1828.          fsuser()) {
  1829. -        inode->i_uid = user;
  1830. -        inode->i_gid = group;
  1831. -        /*
  1832. -         * If the owner has been changed, remove the setuid bit
  1833. -         */
  1834. -        if (old_user != inode->i_uid && inode->i_mode & S_ISUID) {
  1835. -            inode->i_mode &= ~S_ISUID;
  1836. -            notify_flag = NOTIFY_MODE;
  1837. -        }
  1838. -        /*
  1839. -         * If the group has been changed, remove the setgid bit
  1840. -         */
  1841. -        if (old_group != inode->i_gid && inode->i_mode & S_ISGID) {
  1842. -            inode->i_mode &= ~S_ISGID;
  1843. -            notify_flag = NOTIFY_MODE;
  1844. -        }
  1845. -        inode->i_ctime = CURRENT_TIME;
  1846. -        inode->i_dirt = 1;
  1847. -        return notify_change(notify_flag | NOTIFY_UIDGID, inode);
  1848. +        return vfs_chown(inode, user, group);
  1849.      }
  1850.      return -EPERM;
  1851.  }
  1852. @@ -366,25 +339,7 @@
  1853.      if ((current->fsuid == inode->i_uid && user == inode->i_uid &&
  1854.           (in_group_p(group) || group == inode->i_gid)) ||
  1855.          fsuser()) {
  1856. -        inode->i_uid = user;
  1857. -        inode->i_gid = group;
  1858. -        /*
  1859. -         * If the owner has been changed, remove the setuid bit
  1860. -         */
  1861. -        if (old_user != inode->i_uid && inode->i_mode & S_ISUID) {
  1862. -            inode->i_mode &= ~S_ISUID;
  1863. -            notify_flag = NOTIFY_MODE;
  1864. -        }
  1865. -        /*
  1866. -         * If the group has been changed, remove the setgid bit
  1867. -         */
  1868. -        if (old_group != inode->i_gid && inode->i_mode & S_ISGID) {
  1869. -            inode->i_mode &= ~S_ISGID;
  1870. -            notify_flag = NOTIFY_MODE;
  1871. -        }
  1872. -        inode->i_ctime = CURRENT_TIME;
  1873. -        inode->i_dirt = 1;
  1874. -        error = notify_change(notify_flag | NOTIFY_UIDGID, inode);
  1875. +        error = vfs_chown(inode, user, group);
  1876.          iput(inode);
  1877.          return error;
  1878.      }
  1879. @@ -450,6 +405,7 @@
  1880.              return error;
  1881.          }
  1882.      }
  1883. +    vfs_open(f);
  1884.      f->f_flags &= ~(O_CREAT | O_EXCL | O_NOCTTY | O_TRUNC);
  1885.      return (fd);
  1886.  }
  1887. @@ -483,6 +439,7 @@
  1888.      inode = filp->f_inode;
  1889.      if (inode)
  1890.          fcntl_remove_locks(current, filp, fd);
  1891. +    vfs_close(filp);
  1892.      if (filp->f_count > 1) {
  1893.          filp->f_count--;
  1894.          return 0;
  1895. diff -ru --new-file linux_1.1.54/fs/read_write.c linux_1.1.54_owld/fs/read_write.c
  1896. --- linux_1.1.54/fs/read_write.c    Fri Aug 19 18:59:31 1994
  1897. +++ linux_1.1.54_owld/fs/read_write.c    Fri Aug 19 19:00:28 1994
  1898. @@ -9,6 +9,7 @@
  1899.  #include <linux/stat.h>
  1900.  #include <linux/kernel.h>
  1901.  #include <linux/sched.h>
  1902. +#include <linux/fileio.h>
  1903.  
  1904.  #include <asm/segment.h>
  1905.  
  1906. @@ -122,6 +123,7 @@
  1907.      error = verify_area(VERIFY_WRITE,buf,count);
  1908.      if (error)
  1909.          return error;
  1910. +    current->io_usage += count;
  1911.      return file->f_op->read(inode,file,buf,count);
  1912.  }
  1913.  
  1914. diff -ru --new-file linux_1.1.54/fs/super.c linux_1.1.54_owld/fs/super.c
  1915. --- linux_1.1.54/fs/super.c    Thu Oct  6 21:16:23 1994
  1916. +++ linux_1.1.54_owld/fs/super.c    Thu Oct  6 21:37:27 1994
  1917. @@ -2,16 +2,20 @@
  1918.   *  linux/fs/super.c
  1919.   *
  1920.   *  Copyright (C) 1991, 1992  Linus Torvalds
  1921. + *
  1922. + *  super.c contains code to handle: - mount structures
  1923. + *                                   - super-block tables.
  1924. + *                                   - mount systemcall
  1925. + *                                   - umount systemcall
  1926.   */
  1927.  
  1928. -/*
  1929. - * super.c contains code to handle the super-block tables.
  1930. - */
  1931.  #include <stdarg.h>
  1932.  
  1933.  #include <linux/config.h>
  1934.  #include <linux/sched.h>
  1935.  #include <linux/kernel.h>
  1936. +#include <linux/mount.h>
  1937. +#include <linux/malloc.h>
  1938.  #include <linux/major.h>
  1939.  #include <linux/stat.h>
  1940.  #include <linux/errno.h>
  1941. @@ -21,23 +25,112 @@
  1942.  #include <asm/system.h>
  1943.  #include <asm/segment.h>
  1944.  #include <asm/bitops.h>
  1945. +
  1946.  extern struct file_operations * get_blkfops(unsigned int);
  1947. -extern struct file_operations * get_chrfops(unsigned int);
  1948.  
  1949.  extern void wait_for_keypress(void);
  1950.  extern void fcntl_init_locks(void);
  1951.  
  1952.  extern int root_mountflags;
  1953.  
  1954. -struct super_block super_blocks[NR_SUPER];
  1955. -
  1956.  static int do_remount_sb(struct super_block *sb, int flags, char * data);
  1957.  
  1958. -/* this is initialized in init/main.c */
  1959. +/*
  1960. + * This is initialized in init/main.c
  1961. + */
  1962.  dev_t ROOT_DEV = 0;
  1963.  
  1964. -static struct file_system_type * file_systems = NULL;
  1965. +struct super_block super_blocks[NR_SUPER];
  1966. +static struct file_system_type *file_systems = (struct file_system_type *) NULL;
  1967. +static struct vfsmount *vfsmntlist = (struct vfsmount *) NULL,
  1968. +                       *vfsmnttail = (struct vfsmount *) NULL,
  1969. +                       *mru_vfsmnt = (struct vfsmount *) NULL;
  1970. +
  1971. +/* 
  1972. + * This part handles the management of the list of mounted filesystems.
  1973. + * Superblock retrieval is also done with this list.
  1974. + */
  1975. +struct vfsmount *lookup_vfsmnt(dev_t dev)
  1976. +{
  1977. +    register struct vfsmount *lptr;
  1978. +
  1979. +    if (vfsmntlist == (struct vfsmount *) 0)
  1980. +        return ((struct vfsmount *) 0);
  1981. +
  1982. +    if (mru_vfsmnt != (struct vfsmount *) 0 && mru_vfsmnt->mnt_dev == dev)
  1983. +        return (mru_vfsmnt);
  1984. +
  1985. +    for (lptr = vfsmntlist; lptr != (struct vfsmount *)0; lptr = lptr->mnt_next)
  1986. +        if (lptr->mnt_dev == dev)
  1987. +            return (lptr);
  1988. +
  1989. +    return ((struct vfsmount *) 0);
  1990. +    /* NOTREACHED */
  1991. +}
  1992. +
  1993. +static struct vfsmount *add_vfsmnt(dev_t dev, const char *dev_name,
  1994. +                   const char *dir_name)
  1995. +{
  1996. +    register struct vfsmount *lptr;
  1997. +    char *tmp;
  1998. +
  1999. +    if ((lptr = (struct vfsmount *)
  2000. +         kmalloc(sizeof(struct vfsmount), GFP_KERNEL)) == (struct vfsmount *) 0)
  2001. +        panic("VFS: Unable to allocate memory for vfsmount devicelist");
  2002. +
  2003. +    memset(lptr, 0, sizeof(struct vfsmount));
  2004. +    lptr->mnt_dev = dev;
  2005. +    if (dev_name) {
  2006. +        if (!getname(dev_name, &tmp)) {
  2007. +            if ((lptr->mnt_devname =
  2008. +                (char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)0)
  2009. +                strcpy(lptr->mnt_devname, tmp);
  2010. +            putname(tmp);
  2011. +        }
  2012. +    }
  2013. +    if (dir_name) {
  2014. +        if (!getname(dir_name, &tmp)) {
  2015. +            if ((lptr->mnt_dirname =
  2016. +                (char *) kmalloc(strlen(tmp), GFP_KERNEL)) != (char *)0)
  2017. +            strcpy(lptr->mnt_dirname, tmp);
  2018. +            putname(tmp);
  2019. +        }
  2020. +    }
  2021. +
  2022. +    if (vfsmntlist == (struct vfsmount *)0)
  2023. +        vfsmntlist = vfsmnttail = lptr;
  2024. +    else {
  2025. +        vfsmnttail->mnt_next = lptr;
  2026. +        vfsmnttail = lptr;
  2027. +    }
  2028. +    return (lptr);
  2029. +}
  2030. +
  2031. +static void remove_vfsmnt(dev_t dev)
  2032. +{
  2033. +    register struct vfsmount *lptr, *tofree;
  2034. +
  2035. +    if (vfsmntlist == (struct vfsmount *) 0)
  2036. +        return;
  2037. +    lptr = vfsmntlist;
  2038. +    if (lptr->mnt_dev == dev) {
  2039. +        tofree = lptr;
  2040. +        vfsmntlist = lptr->mnt_next;
  2041. +    } else {
  2042. +        while (lptr->mnt_next != (struct vfsmount *) 0) {
  2043. +            if (lptr->mnt_next->mnt_dev == dev)
  2044. +                break;
  2045. +            lptr = lptr->mnt_next;
  2046. +        }
  2047. +        tofree = lptr->mnt_next;
  2048. +        if (vfsmnttail->mnt_dev == dev)
  2049. +            vfsmnttail = lptr;
  2050. +        lptr->mnt_next = lptr->mnt_next->mnt_next;
  2051. +    }
  2052. +    kfree(tofree->mnt_devname);
  2053. +    kfree(tofree->mnt_dirname);
  2054. +    kfree_s(tofree, sizeof(struct vfsmount));
  2055. +}
  2056.  
  2057.  int register_filesystem(struct file_system_type * fs)
  2058.  {
  2059. @@ -319,17 +412,30 @@
  2060.              MAJOR(dev), MINOR(dev));
  2061.  }
  2062.  
  2063. +extern void acct_auto_close(dev_t dev);
  2064. +
  2065.  static int do_umount(dev_t dev)
  2066.  {
  2067.      struct super_block * sb;
  2068.      int retval;
  2069.      
  2070.      if (dev==ROOT_DEV) {
  2071. -        /* Special case for "unmounting" root.  We just try to remount
  2072. -           it readonly, and sync() the device. */
  2073. +        /*
  2074. +         * Special case for "unmounting" root. We just try to remount
  2075. +         * it readonly, and sync() the device.
  2076. +         */
  2077.          if (!(sb=get_super(dev)))
  2078.              return -ENOENT;
  2079.          if (!(sb->s_flags & MS_RDONLY)) {
  2080. +#ifdef CONFIG_QUOTA
  2081. +            /*
  2082. +             * Make sure all quotas are turned off on this device we need to mount
  2083. +             * it readonly so no more writes by the quotasystem.
  2084. +             * If later on the remount fails to bad there are no quotas running
  2085. +             * anymore. Turn them on again by hand.
  2086. +             */
  2087. +            (void) quota_off(dev, -1);
  2088. +#endif
  2089.              fsync_dev(dev);
  2090.              retval = do_remount_sb(sb, MS_RDONLY, 0);
  2091.              if (retval)
  2092. @@ -342,6 +448,18 @@
  2093.      if (!sb->s_covered->i_mount)
  2094.          printk("VFS: umount(%d/%d): mounted inode has i_mount=NULL\n",
  2095.                              MAJOR(dev), MINOR(dev));
  2096. +#ifdef CONFIG_QUOTA
  2097. +    /*
  2098. +     * Before checking if the filesystem is still busy make sure the kernel
  2099. +     * doesn't hold any quotafiles open on that device. If the umount fails
  2100. +     * to bad there are no quotas running anymore. Turn them on again by hand.
  2101. +     */
  2102. +    (void) quota_off(dev, -1);
  2103. +#endif
  2104. +    /*
  2105. +     * The same as for quota is also true for the accounting file.
  2106. +     */
  2107. +    acct_auto_close(dev);
  2108.      if (!fs_may_umount(dev, sb->s_mounted))
  2109.          return -EBUSY;
  2110.      sb->s_covered->i_mount = NULL;
  2111. @@ -352,6 +470,7 @@
  2112.      if (sb->s_op && sb->s_op->write_super && sb->s_dirt)
  2113.          sb->s_op->write_super(sb);
  2114.      put_super(dev);
  2115. +    remove_vfsmnt(dev);
  2116.      return 0;
  2117.  }
  2118.  
  2119. @@ -427,13 +546,15 @@
  2120.   * We also have to flush all inode-data for this device, as the new mount
  2121.   * might need new info.
  2122.   */
  2123. -static int do_mount(dev_t dev, const char * dir, char * type, int flags, void * data)
  2124. +static int do_mount(dev_t dev, const char * dev_name, const char * dir_name,
  2125. +            char * type, int flags, void * data)
  2126.  {
  2127.      struct inode * dir_i;
  2128.      struct super_block * sb;
  2129. +    struct vfsmount *vfsmnt;
  2130.      int error;
  2131.  
  2132. -    error = namei(dir,&dir_i);
  2133. +    error = namei(dir_name,&dir_i);
  2134.      if (error)
  2135.          return error;
  2136.      if (dir_i->i_count != 1 || dir_i->i_mount) {
  2137. @@ -453,6 +574,9 @@
  2138.          iput(dir_i);
  2139.          return -EBUSY;
  2140.      }
  2141. +    vfsmnt = add_vfsmnt(dev, dev_name, dir_name);
  2142. +    vfsmnt->mnt_sb = sb;
  2143. +    vfsmnt->mnt_sem.count = 1;
  2144.      sb->s_covered = dir_i;
  2145.      dir_i->i_mount = sb->s_mounted;
  2146.      return 0;        /* we don't iput(dir_i) - see umount */
  2147. @@ -623,7 +747,7 @@
  2148.              return retval;
  2149.          }
  2150.      }
  2151. -    retval = do_mount(dev,dir_name,t,flags,(void *) page);
  2152. +    retval = do_mount(dev,dev_name,dir_name,t,flags,(void *) page);
  2153.      free_page(page);
  2154.      if (retval && fops && fops->release)
  2155.          fops->release(inode, NULL);
  2156. @@ -635,10 +759,11 @@
  2157.  {
  2158.      struct file_system_type * fs_type;
  2159.      struct super_block * sb;
  2160. +    struct vfsmount *vfsmnt;
  2161.      struct inode * inode, d_inode;
  2162.      struct file filp;
  2163.      int retval;
  2164. -
  2165. +  
  2166.      memset(super_blocks, 0, sizeof(super_blocks));
  2167.      fcntl_init_locks();
  2168.      if (MAJOR(ROOT_DEV) == FLOPPY_MAJOR) {
  2169. @@ -664,9 +789,9 @@
  2170.      for (fs_type = file_systems ; fs_type ; fs_type = fs_type->next) {
  2171.          if(retval)
  2172.              break;
  2173. -        if (!fs_type->requires_dev)
  2174. -            continue;
  2175. -        sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
  2176. +          if (!fs_type->requires_dev)
  2177. +              continue;
  2178. +          sb = read_super(ROOT_DEV,fs_type->name,root_mountflags,NULL,1);
  2179.          if (sb) {
  2180.              inode = sb->s_mounted;
  2181.              inode->i_count += 3 ;    /* NOTE! it is logically used 4 times, not 1 */
  2182. @@ -677,6 +802,9 @@
  2183.              printk ("VFS: Mounted root (%s filesystem)%s.\n",
  2184.                  fs_type->name,
  2185.                  (sb->s_flags & MS_RDONLY) ? " readonly" : "");
  2186. +            vfsmnt = add_vfsmnt(ROOT_DEV, "rootfs", "/");
  2187. +            vfsmnt->mnt_sb = sb;
  2188. +            vfsmnt->mnt_sem.count = 1;
  2189.              return;
  2190.          }
  2191.      }
  2192. diff -ru --new-file linux_1.1.54/ibcs/binfmt_coff.c linux_1.1.54_owld/ibcs/binfmt_coff.c
  2193. --- linux_1.1.54/ibcs/binfmt_coff.c    Wed Aug 10 23:29:32 1994
  2194. +++ linux_1.1.54_owld/ibcs/binfmt_coff.c    Wed Aug 10 23:30:10 1994
  2195. @@ -455,6 +455,8 @@
  2196.  /*
  2197.   *  Do the end processing once the stack has been constructed
  2198.   */
  2199. +            current->flags          &= ~PF_FORKNOEXEC; /* accounting flags */
  2200. +            current->io_usage        = 0;
  2201.          current->mm->start_code  = text_vaddr & PAGE_MASK;
  2202.          current->mm->end_code    = text_vaddr + text_size;
  2203.          current->mm->end_data    = data_vaddr + data_size;
  2204. diff -ru --new-file linux_1.1.54/include/linux/acct.h linux_1.1.54_owld/include/linux/acct.h
  2205. --- linux_1.1.54/include/linux/acct.h
  2206. +++ linux_1.1.54_owld/include/linux/acct.h    Wed May  4 17:34:46 1994
  2207. @@ -0,0 +1,28 @@
  2208. +#ifndef __LINUX_ACCT_H
  2209. +#define __LINUX_ACCT_H
  2210. +
  2211. +#define ACCT_COMM 16
  2212. +
  2213. +struct acct
  2214. +{
  2215. +   char          ac_comm[ACCT_COMM];    /* Accounting command name */
  2216. +   time_t        ac_utime;        /* Accounting user time */
  2217. +   time_t        ac_stime;        /* Accounting system time */
  2218. +   time_t        ac_etime;        /* Accounting elapsed time */
  2219. +   time_t        ac_btime;        /* Beginning time */
  2220. +   uid_t         ac_uid;        /* Accounting user ID */
  2221. +   gid_t         ac_gid;        /* Accounting group ID */
  2222. +   dev_t         ac_tty;        /* controlling tty */
  2223. +   char          ac_flag;        /* Accounting flag */
  2224. +   unsigned long ac_mem;        /* Pages of memory used */
  2225. +   unsigned long ac_io;            /* Number of bytes read/written */
  2226. +};
  2227. +
  2228. +#define AFORK    0001    /* has executed fork, but no exec */
  2229. +#define ASU    0002    /* used super-user privileges */
  2230. +#define ACORE    0004    /* dumped core */
  2231. +#define AXSIG    0010    /* killed by a signal */
  2232. +
  2233. +#define AHZ     100
  2234. +
  2235. +#endif
  2236. diff -ru --new-file linux_1.1.54/include/linux/fileio.h linux_1.1.54_owld/include/linux/fileio.h
  2237. --- linux_1.1.54/include/linux/fileio.h
  2238. +++ linux_1.1.54_owld/include/linux/fileio.h    Fri Aug 12 13:19:22 1994
  2239. @@ -0,0 +1,70 @@
  2240. +/*
  2241. + *
  2242. + * Simple VFS definitions for fileio.
  2243. + *
  2244. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  2245. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  2246. + *
  2247. + * Version: $Id: fileio.h,v 1.5 1994/05/30 18:39:42 mvw Exp mvw $
  2248. + *
  2249. + */
  2250. +#ifndef _LINUX_FILEIO_H
  2251. +#define _LINUX_FILEIO_H
  2252. +
  2253. +#include <linux/config.h>
  2254. +#include <linux/stat.h>
  2255. +
  2256. +#ifdef CONFIG_QUOTA
  2257. +
  2258. +int vfs_write(struct inode *ino, struct file *file, char *addr, size_t bytes);
  2259. +int vfs_create(struct inode *dir, const char *basename,
  2260. +               int namelen, int mode, struct inode **res_ino);
  2261. +int vfs_truncate(struct inode *ino, size_t lenght);
  2262. +int vfs_mknod(struct inode *dir, const char *basename,
  2263. +              int namelen, int mode, dev_t dev);
  2264. +int vfs_mkdir(struct inode *dir, const char *basename, int namelen, int mode);
  2265. +int vfs_rmdir(struct inode *dir, const char *basename, int namelen);
  2266. +int vfs_unlink(struct inode *dir, const char *basename, int namelen);
  2267. +int vfs_symlink(struct inode *dir, const char *basename,
  2268. +                int namelen, const char *oldname);
  2269. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid);
  2270. +int vfs_rename(struct inode *old_dir, const char *old_base, int old_len,
  2271. +               struct inode *new_dir, const char *mew_base, int new_len);
  2272. +void vfs_open(struct file *filp);
  2273. +void vfs_close(struct file *filp);
  2274. +
  2275. +#else /* CONFIG_QUOTA */
  2276. +
  2277. +#define vfs_write(ino, file, addr, bytes) \
  2278. +(file)->f_op->write((ino),(file),(addr),(bytes))
  2279. +
  2280. +#define vfs_create(dir, basename, namelen, mode, res_ino) \
  2281. +(dir)->i_op->create((dir),(basename),(namelen),(mode),(res_ino))
  2282. +
  2283. +int vfs_truncate(struct inode *ino, size_t lenght);
  2284. +
  2285. +#define vfs_mknod(dir, basename, namelen, mode, dev) \
  2286. +(dir)->i_op->mknod((dir),(basename),(namelen),(mode),(dev))
  2287. +
  2288. +#define vfs_mkdir(dir, basename, namelen, mode) \
  2289. +(dir)->i_op->mkdir((dir),(basename),(namelen),(mode))
  2290. +
  2291. +#define vfs_rmdir(dir, basename, namelen) \
  2292. +(dir)->i_op->rmdir((dir),(basename),(namelen))
  2293. +
  2294. +#define vfs_unlink(dir, basename, namelen) \
  2295. +(dir)->i_op->unlink((dir),(basename),(namelen))
  2296. +
  2297. +#define vfs_symlink(dir, basename, namelen, oldname) \
  2298. +(dir)->i_op->symlink((dir),(basename),(namelen),(oldname))
  2299. +
  2300. +int vfs_chown(struct inode *ino, uid_t uid, gid_t gid);
  2301. +
  2302. +#define vfs_rename(old_dir, old_base, old_len, new_dir, new_base, new_len) \
  2303. +(old_dir)->i_op->rename((old_dir),(old_base),(old_len),(new_dir),(new_base),(new_len))
  2304. +
  2305. +void vfs_open(struct file *filp);
  2306. +void vfs_close(struct file *filp);
  2307. +
  2308. +#endif /* CONFIG_QUOTA */
  2309. +#endif /* _LINUX_FILEIO_H */
  2310. diff -ru --new-file linux_1.1.54/include/linux/fs.h linux_1.1.54_owld/include/linux/fs.h
  2311. --- linux_1.1.54/include/linux/fs.h    Fri Aug 19 18:59:33 1994
  2312. +++ linux_1.1.54_owld/include/linux/fs.h    Fri Aug 19 19:00:30 1994
  2313. @@ -171,6 +171,7 @@
  2314.  #include <linux/nfs_fs_i.h>
  2315.  #include <linux/xia_fs_i.h>
  2316.  #include <linux/sysv_fs_i.h>
  2317. +#include <linux/quota.h>
  2318.  
  2319.  #ifdef __KERNEL__
  2320.  
  2321. @@ -200,7 +201,9 @@
  2322.      struct inode * i_bound_to, * i_bound_by;
  2323.      struct inode * i_mount;
  2324.      struct socket * i_socket;
  2325. +    struct dquot * i_dquot[MAXQUOTAS];
  2326.      unsigned short i_count;
  2327. +    unsigned short i_writecount;
  2328.      unsigned short i_flags;
  2329.      unsigned char i_lock;
  2330.      unsigned char i_dirt;
  2331. diff -ru --new-file linux_1.1.54/include/linux/kernel.h linux_1.1.54_owld/include/linux/kernel.h
  2332. --- linux_1.1.54/include/linux/kernel.h    Fri Aug 12 13:00:28 1994
  2333. +++ linux_1.1.54_owld/include/linux/kernel.h    Fri Aug 12 13:01:20 1994
  2334. @@ -54,19 +54,6 @@
  2335.  asmlinkage int printk(const char * fmt, ...)
  2336.      __attribute__ ((format (printf, 1, 2)));
  2337.  
  2338. -/*
  2339. - * This is defined as a macro, but at some point this might become a
  2340. - * real subroutine that sets a flag if it returns true (to do
  2341. - * BSD-style accounting where the process is flagged if it uses root
  2342. - * privs).  The implication of this is that you should do normal
  2343. - * permissions checks first, and check suser() last.
  2344. - *
  2345. - * "suser()" checks against the effective user id, while "fsuser()"
  2346. - * is used for file permission checking and checks against the fsuid..
  2347. - */
  2348. -#define suser() (current->euid == 0)
  2349. -#define fsuser() (current->fsuid == 0)
  2350. -
  2351.  extern int splx (int new_ipl);
  2352.  #endif /* __KERNEL__ */
  2353.  
  2354. diff -ru --new-file linux_1.1.54/include/linux/mount.h linux_1.1.54_owld/include/linux/mount.h
  2355. --- linux_1.1.54/include/linux/mount.h
  2356. +++ linux_1.1.54_owld/include/linux/mount.h    Wed Sep  7 23:08:40 1994
  2357. @@ -0,0 +1,34 @@
  2358. +/*
  2359. + *
  2360. + * Definitions for mount interface. This describes the in the kernel build 
  2361. + * linkedlist with mounted filesystems.
  2362. + *
  2363. + * Authors: Marco van Wieringen <v892273@si.hhs.nl> <mvw@mcs.ow.org>
  2364. + *          Edvard Tuinder <v892231@si.hhs.nl> <ed@delirium.ow.org>
  2365. + *
  2366. + * Version: $Id: mount.h,v 1.3 1994/07/20 22:01:00 mvw Exp mvw $
  2367. + *
  2368. + */
  2369. +#ifndef _LINUX_MOUNT_H
  2370. +#define _LINUX_MOUNT_H
  2371. +
  2372. +#define QF_OPENING  0x01        /* Quotafile is in progress of being opened */
  2373. +#define QF_CLOSING  0x02        /* Quotafile is in progress of being closed */
  2374. +
  2375. +struct vfsmount
  2376. +{
  2377. +   dev_t mnt_dev;                      /* Device this applies to */
  2378. +   char *mnt_devname;                  /* Name of device e.g. /dev/dsk/hda1 */
  2379. +   char *mnt_dirname;                  /* Name of directory mounted on */
  2380. +   unsigned int mnt_flags;             /* Flags of this device see above */
  2381. +   struct semaphore mnt_sem;           /* lock device while I/O in progress */
  2382. +   struct super_block *mnt_sb;         /* pointer to superblock */
  2383. +   struct file *mnt_quotas[MAXQUOTAS]; /* fp's to quotafiles */
  2384. +   time_t mnt_iexp[MAXQUOTAS];         /* expiretime for inodes */
  2385. +   time_t mnt_bexp[MAXQUOTAS];         /* expiretime for blocks */
  2386. +   struct vfsmount *mnt_next;          /* pointer to next in linkedlist */
  2387. +};
  2388. +
  2389. +struct vfsmount *lookup_vfsmnt(dev_t dev);
  2390. +
  2391. +#endif /* _LINUX_MOUNT_H */
  2392. diff -ru --new-file linux_1.1.54/include/linux/quota.h linux_1.1.54_owld/include/linux/quota.h
  2393. --- linux_1.1.54/include/linux/quota.h
  2394. +++ linux_1.1.54_owld/include/linux/quota.h    Wed May  4 17:34:46 1994
  2395. @@ -0,0 +1,208 @@
  2396. +/*
  2397. + * Copyright (c) 1982, 1986 Regents of the University of California.
  2398. + * All rights reserved.
  2399. + *
  2400. + * This code is derived from software contributed to Berkeley by
  2401. + * Robert Elz at The University of Melbourne.
  2402. + *
  2403. + * Redistribution and use in source and binary forms, with or without
  2404. + * modification, are permitted provided that the following conditions
  2405. + * are met:
  2406. + * 1. Redistributions of source code must retain the above copyright
  2407. + *    notice, this list of conditions and the following disclaimer.
  2408. + * 2. Redistributions in binary form must reproduce the above copyright
  2409. + *    notice, this list of conditions and the following disclaimer in the
  2410. + *    documentation and/or other materials provided with the distribution.
  2411. + * 3. All advertising materials mentioning features or use of this software
  2412. + *    must display the following acknowledgement:
  2413. + *   This product includes software developed by the University of
  2414. + *   California, Berkeley and its contributors.
  2415. + * 4. Neither the name of the University nor the names of its contributors
  2416. + *    may be used to endorse or promote products derived from this software
  2417. + *    without specific prior written permission.
  2418. + *
  2419. + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  2420. + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  2421. + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  2422. + * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  2423. + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  2424. + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  2425. + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  2426. + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  2427. + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  2428. + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  2429. + * SUCH DAMAGE.
  2430. + *
  2431. + * Version: $Id: quota.h,v 1.5 1994/01/06 20:45:20 mvw Exp mvw $
  2432. + */
  2433. +
  2434. +#ifndef _LINUX_QUOTA_
  2435. +#define _LINUX_QUOTA_
  2436. +
  2437. +#include <linux/errno.h>
  2438. +
  2439. +/*
  2440. + * Convert diskblocks to blocks and the other way around.
  2441. + * currently only to fool the BSD source. :-)
  2442. + */
  2443. +#define dbtob(num) (num << 10)
  2444. +#define btodb(num) (num >> 10)
  2445. +
  2446. +/*
  2447. + * Definitions for disk quotas imposed on the average user
  2448. + * (big brother finally hits Linux).
  2449. + *
  2450. + * The following constants define the amount of time given a user
  2451. + * before the soft limits are treated as hard limits (usually resulting
  2452. + * in an allocation failure). The timer is started when the user crosses
  2453. + * their soft limit, it is reset when they go below their soft limit.
  2454. + */
  2455. +#define MAX_IQ_TIME  604800    /* (7*24*60*60) 1 week */
  2456. +#define MAX_DQ_TIME  604800    /* (7*24*60*60) 1 week */
  2457. +
  2458. +#define MAXQUOTAS 2
  2459. +#define USRQUOTA  0        /* element used for user quotas */
  2460. +#define GRPQUOTA  1        /* element used for group quotas */
  2461. +
  2462. +/*
  2463. + * Definitions for the default names of the quotas files.
  2464. + */
  2465. +#define INITQFNAMES { \
  2466. +   "user",      /* USRQUOTA */ \
  2467. +   "group",   /* GRPQUOTA */ \
  2468. +   "undefined", \
  2469. +};
  2470. +
  2471. +#define QUOTAFILENAME "quota"
  2472. +#define QUOTAGROUP "staff"
  2473. +
  2474. +#define NR_DQHASH 43            /* Just an arbitrary number any suggestions ? */
  2475. +#define NR_DQUOTS 256           /* Number of quotas active at one time */
  2476. +
  2477. +/*
  2478. + * Command definitions for the 'quotactl' system call.
  2479. + * The commands are broken into a main command defined below
  2480. + * and a subcommand that is used to convey the type of
  2481. + * quota that is being manipulated (see above).
  2482. + */
  2483. +#define SUBCMDMASK  0x00ff
  2484. +#define SUBCMDSHIFT 8
  2485. +#define QCMD(cmd, type)  (((cmd) << SUBCMDSHIFT) | ((type) & SUBCMDMASK))
  2486. +
  2487. +#define Q_QUOTAON  0x0100    /* enable quotas */
  2488. +#define Q_QUOTAOFF 0x0200    /* disable quotas */
  2489. +#define Q_GETQUOTA 0x0300    /* get limits and usage */
  2490. +#define Q_SETQUOTA 0x0400    /* set limits and usage */
  2491. +#define Q_SETUSE   0x0500    /* set usage */
  2492. +#define Q_SYNC     0x0600    /* sync disk copy of a filesystems quotas */
  2493. +#define Q_SETQLIM  0x0700    /* set limits */
  2494. +
  2495. +/*
  2496. + * The following structure defines the format of the disk quota file
  2497. + * (as it appears on disk) - the file is an array of these structures
  2498. + * indexed by user or group number.
  2499. + */
  2500. +struct dqblk
  2501. +  {
  2502. +    u_long dqb_bhardlimit;    /* absolute limit on disk blks alloc */
  2503. +    u_long dqb_bsoftlimit;    /* preferred limit on disk blks */
  2504. +    u_long dqb_curblocks;    /* current block count */
  2505. +    u_long dqb_ihardlimit;    /* maximum # allocated inodes */
  2506. +    u_long dqb_isoftlimit;    /* preferred inode limit */
  2507. +    u_long dqb_curinodes;    /* current # allocated inodes */
  2508. +    time_t dqb_btime;        /* time limit for excessive disk use */
  2509. +    time_t dqb_itime;        /* time limit for excessive files */
  2510. +  };
  2511. +
  2512. +/*
  2513. + * Shorthand notation.
  2514. + */
  2515. +#define    dq_bhardlimit    dq_dqb.dqb_bhardlimit
  2516. +#define    dq_bsoftlimit    dq_dqb.dqb_bsoftlimit
  2517. +#define    dq_curblocks    dq_dqb.dqb_curblocks
  2518. +#define    dq_ihardlimit    dq_dqb.dqb_ihardlimit
  2519. +#define    dq_isoftlimit    dq_dqb.dqb_isoftlimit
  2520. +#define    dq_curinodes    dq_dqb.dqb_curinodes
  2521. +#define    dq_btime    dq_dqb.dqb_btime
  2522. +#define    dq_itime    dq_dqb.dqb_itime
  2523. +
  2524. +#define dqoff(UID)      ((off_t)((UID) * sizeof (struct dqblk)))
  2525. +
  2526. +#ifdef __KERNEL__
  2527. +
  2528. +/*
  2529. + * Maximum lenght of a message generated in the quota system,
  2530. + * that needs to be kicked onto the tty.
  2531. + */
  2532. +#define MAX_QUOTA_MESSAGE 75
  2533. +
  2534. +#define DQ_LOCKED     0x01    /* locked for update */
  2535. +#define DQ_WANT       0x02    /* wanted for update */
  2536. +#define DQ_MOD        0x04    /* dquot modified since read */
  2537. +#define DQ_BLKS       0x10    /* uid/gid has been warned about blk limit */
  2538. +#define DQ_INODES     0x20    /* uid/gid has been warned about inode limit */
  2539. +#define DQ_FAKE       0x40    /* no limits only usage */
  2540. +
  2541. +struct dquot
  2542. +{
  2543. +   unsigned int dq_id;        /* id this applies to (uid, gid) */
  2544. +   short dq_type;        /* type of quota */
  2545. +   dev_t dq_dev;                /* Device this applies to */
  2546. +   short dq_flags;        /* see DQ_* */
  2547. +   short dq_count;        /* reference count */
  2548. +   struct vfsmount *dq_mnt;     /* vfsmountpoint this applies to */
  2549. +   struct dqblk dq_dqb;         /* diskquota usage */
  2550. +   struct wait_queue *dq_wait;    /* pointer to waitqueue */
  2551. +   struct dquot *dq_prev;    /* pointer to prev dquot */
  2552. +   struct dquot *dq_next;    /* pointer to next dquot */
  2553. +   struct dquot *dq_hash_prev;    /* pointer to prev dquot */
  2554. +   struct dquot *dq_hash_next;    /* pointer to next dquot */
  2555. +};
  2556. +
  2557. +#define NODQUOT (struct dquot *)NULL
  2558. +
  2559. +/*
  2560. + * Flags used for set_dqblk.
  2561. + */
  2562. +#define QUOTA_SYSCALL     0x01
  2563. +#define SET_QUOTA         0x02
  2564. +#define SET_USE           0x04
  2565. +#define SET_QLIMIT        0x08
  2566. +
  2567. +/*
  2568. + * Return values when requesting quota.
  2569. + */
  2570. +#define NO_QUOTA 0        /* no more quota available */
  2571. +#define QUOTA_OK 1        /* can allocate the space */
  2572. +
  2573. +/*
  2574. + * declaration of quota_function calls in kernel.
  2575. + */
  2576. +struct dquot *dqget (dev_t dev, unsigned int id, short type);
  2577. +void dqput (struct dquot *dquot);
  2578. +
  2579. +int quota_off (dev_t dev, short type);
  2580. +int sync_dquots (dev_t dev, short type);
  2581. +
  2582. +u_long isize_to_blocks (size_t isize, size_t blksize);
  2583. +size_t blocks_to_isize (u_long blocks, size_t blksize);
  2584. +
  2585. +void quota_remove (struct inode *inode, u_long inodes, u_long blocks);
  2586. +int quota_alloc (struct inode *inode, u_long wantedinodes,
  2587. +                 u_long wantedblocks, u_long * availblocks);
  2588. +int quota_transfer (struct inode *inode, uid_t newuid,
  2589. +                    gid_t newgid, u_long inodes, u_long blocks);
  2590. +
  2591. +void getinoquota (struct inode *inode, short type);
  2592. +void putinoquota (struct inode *inode);
  2593. +
  2594. +#else
  2595. +
  2596. +#include <sys/cdefs.h>
  2597. +
  2598. +__BEGIN_DECLS
  2599. +int quotactl __P ((int, const char *, int, caddr_t));
  2600. +__END_DECLS
  2601. +
  2602. +#endif /* __KERNEL__ */
  2603. +#endif /* _QUOTA_ */
  2604. diff -ru --new-file linux_1.1.54/include/linux/sched.h linux_1.1.54_owld/include/linux/sched.h
  2605. --- linux_1.1.54/include/linux/sched.h    Fri Aug 19 18:59:35 1994
  2606. +++ linux_1.1.54_owld/include/linux/sched.h    Fri Aug 19 19:00:31 1994
  2607. @@ -280,6 +280,7 @@
  2608.      long utime, stime, cutime, cstime, start_time;
  2609.      struct rlimit rlim[RLIM_NLIMITS]; 
  2610.      unsigned short used_math;
  2611. +    unsigned long io_usage; /* number of bytes read/written */
  2612.      char comm[16];
  2613.  /* virtual 86 mode stuff */
  2614.      struct vm86_struct * vm86_info;
  2615. @@ -310,6 +311,10 @@
  2616.                      /* Not implemented yet, only for 486*/
  2617.  #define PF_PTRACED    0x00000010    /* set if ptrace (0) has been called. */
  2618.  #define PF_TRACESYS    0x00000020    /* tracing system calls */
  2619. +#define PF_FORKNOEXEC    0x00000040    /* forked but didn't exec */
  2620. +#define PF_SUPERPREV    0x00000100    /* used super-user privileges */
  2621. +#define PF_DUMPCORE    0x00000200    /* dumped core */
  2622. +#define PF_SIGNALED    0x00000400    /* killed by a signal */
  2623.  
  2624.  /*
  2625.   * cloning flags:
  2626. @@ -340,6 +345,7 @@
  2627.            {LONG_MAX, LONG_MAX}, {LONG_MAX, LONG_MAX},  \
  2628.            {       0, LONG_MAX}, {LONG_MAX, LONG_MAX}}, \
  2629.  /* math */    0, \
  2630. +/* io_usage */  0, \
  2631.  /* comm */    "swapper", \
  2632.  /* vm86_info */    NULL, 0, 0, 0, 0, \
  2633.  /* fs info */    0,NULL, \
  2634. @@ -450,6 +456,29 @@
  2635.  #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , base )
  2636.  #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , (limit-1)>>12 )
  2637.  
  2638. +/*
  2639. + * This has now become a routine instead of a macro, it sets a flag if
  2640. + * it returns true (to do BSD-style accounting where the process is flagged
  2641. + * if it uses root privs). The implication of this is that you should do
  2642. + * normal permissions checks first, and check suser() last.
  2643. + *
  2644. + * "suser()" checks against the effective user id, while "fsuser()"
  2645. + * is used for file permission checking and checks against the fsuid..
  2646. + */
  2647. +extern inline int suser(void)
  2648. +{
  2649. +    if (current->euid == 0)
  2650. +        current->flags |= PF_SUPERPREV;
  2651. +    return (current->euid == 0);
  2652. +}
  2653. +
  2654. +extern inline int fsuser(void)
  2655. +{
  2656. +    if (current->fsuid == 0)
  2657. +        current->flags |= PF_SUPERPREV;
  2658. +    return (current->fsuid == 0);
  2659. +}
  2660. +
  2661.  /*
  2662.   * The wait-queues are circular lists, and you have to be *very* sure
  2663.   * to keep them correct. Use only these two functions to add/remove
  2664. diff -ru --new-file linux_1.1.54/include/linux/sys.h linux_1.1.54_owld/include/linux/sys.h
  2665. --- linux_1.1.54/include/linux/sys.h    Mon Apr 18 22:42:22 1994
  2666. +++ linux_1.1.54_owld/include/linux/sys.h    Wed May  4 17:34:46 1994
  2667. @@ -32,6 +32,5 @@
  2668.   * These are system calls that haven't been implemented yet
  2669.   * but have an entry in the table for future expansion..
  2670.   */
  2671. -#define _sys_quotactl    _sys_ni_syscall
  2672.  
  2673.  #endif
  2674. diff -ru --new-file linux_1.1.54/include/linux/tty.h linux_1.1.54_owld/include/linux/tty.h
  2675. --- linux_1.1.54/include/linux/tty.h    Sun Oct 16 00:26:32 1994
  2676. +++ linux_1.1.54_owld/include/linux/tty.h    Sun Oct 16 00:28:22 1994
  2677. @@ -291,6 +291,7 @@
  2678.  extern int tty_register_driver(struct tty_driver *driver);
  2679.  extern int tty_read_raw_data(struct tty_struct *tty, unsigned char *bufp,
  2680.                   int buflen);
  2681. +extern void tty_write_message(struct tty_struct *tty, char *msg);
  2682.  
  2683.  extern int is_orphaned_pgrp(int pgrp);
  2684.  extern int is_ignored(int sig);
  2685. diff -ru --new-file linux_1.1.54/init/main.c linux_1.1.54_owld/init/main.c
  2686. --- linux_1.1.54/init/main.c    Fri Aug 26 23:07:32 1994
  2687. +++ linux_1.1.54_owld/init/main.c    Fri Aug 26 23:09:11 1994
  2688. @@ -103,6 +103,9 @@
  2689.  #ifdef CONFIG_SYSVIPC
  2690.  extern void ipc_init(void);
  2691.  #endif
  2692. +#ifdef CONFIG_QUOTA
  2693. +extern void quota_init(void);
  2694. +#endif
  2695.  #ifdef CONFIG_SCSI
  2696.  extern unsigned long scsi_dev_init(unsigned long, unsigned long);
  2697.  #endif
  2698. @@ -458,6 +461,9 @@
  2699.  #ifdef CONFIG_SYSVIPC
  2700.      ipc_init();
  2701.  #endif
  2702. +#ifdef CONFIG_QUOTA
  2703. +    quota_init();
  2704. +#endif
  2705.      sti();
  2706.      
  2707.      /*
  2708. diff -ru --new-file linux_1.1.54/kernel/exit.c linux_1.1.54_owld/kernel/exit.c
  2709. --- linux_1.1.54/kernel/exit.c    Wed Aug 10 23:29:34 1994
  2710. +++ linux_1.1.54_owld/kernel/exit.c    Wed Aug 10 23:30:13 1994
  2711. @@ -19,6 +19,7 @@
  2712.  #include <asm/segment.h>
  2713.  extern void shm_exit (void);
  2714.  extern void sem_exit (void);
  2715. +extern void acct_process (void);
  2716.  
  2717.  int getrusage(struct task_struct *, int, struct rusage *);
  2718.  
  2719. @@ -411,6 +412,7 @@
  2720.          intr_count = 0;
  2721.      }
  2722.  fake_volatile:
  2723. +    acct_process();
  2724.      if (current->semun)
  2725.          sem_exit();
  2726.      if (current->shm)
  2727. diff -ru --new-file linux_1.1.54/kernel/fork.c linux_1.1.54_owld/kernel/fork.c
  2728. --- linux_1.1.54/kernel/fork.c    Thu Jul 28 12:37:51 1994
  2729. +++ linux_1.1.54_owld/kernel/fork.c    Thu Jul 28 12:45:27 1994
  2730. @@ -2,9 +2,7 @@
  2731.   *  linux/kernel/fork.c
  2732.   *
  2733.   *  Copyright (C) 1991, 1992  Linus Torvalds
  2734. - */
  2735. -
  2736. -/*
  2737. + *
  2738.   *  'fork.c' contains the help-routines for the 'fork' system call
  2739.   * (see also system_call.s).
  2740.   * Fork is rather simple, once you get the hang of it, but the memory
  2741. @@ -21,6 +19,7 @@
  2742.  #include <linux/ptrace.h>
  2743.  #include <linux/malloc.h>
  2744.  #include <linux/ldt.h>
  2745. +#include <linux/fileio.h>
  2746.  
  2747.  #include <asm/segment.h>
  2748.  #include <asm/system.h>
  2749. @@ -84,6 +83,7 @@
  2750.                  new_file->f_count = 0;
  2751.                  new_file = NULL;
  2752.              }
  2753. +            vfs_open(new_file);
  2754.          }
  2755.      }
  2756.      return new_file;
  2757. @@ -124,8 +124,10 @@
  2758.                  p->files->fd[i] = copy_fd(f);
  2759.      } else {
  2760.          for (i=0; i<NR_OPEN;i++)
  2761. -            if ((f = p->files->fd[i]) != NULL)
  2762. +            if ((f = p->files->fd[i]) != NULL) {
  2763.                  f->f_count++;
  2764. +                vfs_open(f);
  2765. +            }
  2766.      }
  2767.  }
  2768.  
  2769. @@ -188,7 +190,9 @@
  2770.      p->did_exec = 0;
  2771.      p->kernel_stack_page = 0;
  2772.      p->state = TASK_UNINTERRUPTIBLE;
  2773. -    p->flags &= ~(PF_PTRACED|PF_TRACESYS);
  2774. +    p->flags &= ~(PF_PTRACED|PF_TRACESYS|PF_SUPERPREV);
  2775. +    p->flags |= PF_FORKNOEXEC;
  2776. +    p->io_usage = 0; /* Child doesn't inherit parent's I/O usage */
  2777.      p->pid = last_pid;
  2778.      p->p_pptr = p->p_opptr = current;
  2779.      p->p_cptr = NULL;
  2780. diff -ru --new-file linux_1.1.54/kernel/printk.c linux_1.1.54_owld/kernel/printk.c
  2781. --- linux_1.1.54/kernel/printk.c    Sun Aug  7 20:54:32 1994
  2782. +++ linux_1.1.54_owld/kernel/printk.c    Sun Aug  7 20:56:05 1994
  2783. @@ -19,6 +19,8 @@
  2784.  #include <linux/errno.h>
  2785.  #include <linux/sched.h>
  2786.  #include <linux/kernel.h>
  2787. +#include <linux/tty.h>
  2788. +#include <linux/tty_driver.h>
  2789.  
  2790.  #define LOG_BUF_LEN    4096
  2791.  
  2792. @@ -227,3 +229,16 @@
  2793.          j = 0;
  2794.      }
  2795.  }
  2796. +
  2797. +/*
  2798. + * Write a message to a certain tty, not just the console. This is used for
  2799. + * messages that need to be redirected to a specific tty.
  2800. + * We don't put it into the syslog queue right now maybe in the future if
  2801. + * really needed.
  2802. + */
  2803. +void tty_write_message(struct tty_struct *tty, char *msg)
  2804. +{
  2805. +    if (tty && tty->driver.write)
  2806. +        tty->driver.write(tty, 0, msg, strlen(msg));
  2807. +    return;
  2808. +}
  2809. diff -ru --new-file linux_1.1.54/kernel/sys.c linux_1.1.54_owld/kernel/sys.c
  2810. --- linux_1.1.54/kernel/sys.c    Thu Oct  6 21:16:24 1994
  2811. +++ linux_1.1.54_owld/kernel/sys.c    Thu Oct  6 21:18:28 1994
  2812. @@ -17,6 +17,10 @@
  2813.  #include <linux/ptrace.h>
  2814.  #include <linux/stat.h>
  2815.  #include <linux/mman.h>
  2816. +#include <linux/tty.h>
  2817. +#include <linux/fcntl.h>
  2818. +#include <linux/acct.h>
  2819. +#include <linux/fileio.h>
  2820.  
  2821.  #include <asm/segment.h>
  2822.  #include <asm/io.h>
  2823. @@ -251,9 +255,128 @@
  2824.      return 0;
  2825.  }
  2826.  
  2827. -asmlinkage int sys_acct(void)
  2828. +static char acct_active = 0;
  2829. +static struct file *acct_file;
  2830. +#define    KSTK_ESP(stack)    (((unsigned long *) stack)[1022])
  2831. +
  2832. +int acct_process(void)
  2833. +{
  2834. +    struct acct ac;
  2835. +    unsigned short fs;
  2836. +    unsigned long vsize, esp;
  2837. +
  2838. +    if (acct_active) {
  2839. +        memset(&ac, 0, sizeof(struct acct));
  2840. +        strncpy(ac.ac_comm, current->comm, ACCT_COMM);
  2841. +        ac.ac_comm[ACCT_COMM] = '\0';
  2842. +        ac.ac_utime = current->utime;
  2843. +        ac.ac_stime = current->stime;
  2844. +        ac.ac_btime = CT_TO_SECS(current->start_time) + (xtime.tv_sec - (jiffies / HZ));
  2845. +        ac.ac_etime = CURRENT_TIME - ac.ac_btime;
  2846. +        ac.ac_uid   = current->uid;
  2847. +        ac.ac_gid   = current->gid;
  2848. +        ac.ac_tty   = (current->tty) ? MKDEV(4, current->tty->device) : MKDEV(4, -1);
  2849. +        ac.ac_flag  = 0;
  2850. +        if (current->flags & PF_FORKNOEXEC)
  2851. +            ac.ac_flag |= AFORK;
  2852. +        if (current->flags & PF_SUPERPREV)
  2853. +            ac.ac_flag |= ASU;
  2854. +        if (current->flags & PF_DUMPCORE)
  2855. +            ac.ac_flag |= ACORE;
  2856. +        if (current->flags & PF_SIGNALED)
  2857. +            ac.ac_flag |= AXSIG;
  2858. +        ac.ac_io    = current->io_usage;
  2859. +
  2860. +        /* Figure out the vsize of the current process and divide by the
  2861. +         * page size to calculate AC_MEM.  This is the approved method
  2862. +         * from the proc filesystem.
  2863. +         */
  2864. +        vsize = current->kernel_stack_page;
  2865. +        if (vsize) {
  2866. +            esp = KSTK_ESP(vsize);
  2867. +            vsize = current->mm->brk - current->mm->start_code + (PAGE_SIZE - 1);
  2868. +            if (esp)
  2869. +                vsize += TASK_SIZE - esp;
  2870. +        }
  2871. +        /* now vsize contains the number of bytes used -- we want to
  2872. +         * find out the number of pages, so divide it by the page size
  2873. +         * and round up.
  2874. +         */
  2875. +        ac.ac_mem = (vsize / PAGE_SIZE) + ((vsize % PAGE_SIZE) != 0);
  2876. +
  2877. +        /* Kernel segment override */
  2878. +        fs = get_fs();
  2879. +        set_fs(KERNEL_DS);
  2880. +
  2881. +        acct_file->f_op->write(acct_file->f_inode, acct_file,
  2882. +                      (char *)&ac, sizeof(struct acct));
  2883. +
  2884. +        set_fs(fs);
  2885. +    }
  2886. +    return 0;
  2887. +}
  2888. +
  2889. +extern void close_fp(struct file *, int);
  2890. +
  2891. +asmlinkage int sys_acct(const char *name)
  2892.  {
  2893. -    return -ENOSYS;
  2894. +    struct inode *inode = (struct inode *)0;
  2895. +    char *tmp;
  2896. +    int error;
  2897. +
  2898. +    if (!suser())
  2899. +        return -EPERM;
  2900. +
  2901. +    if (name == (char *)0) {
  2902. +        if (acct_active) {
  2903. +            acct_process(); 
  2904. +            acct_active = 0;
  2905. +            close_fp(acct_file, 0);
  2906. +        }
  2907. +        return 0;
  2908. +    } else {
  2909. +        if (!acct_active) {
  2910. +            if ((error = getname(name, &tmp)) != 0)
  2911. +                return (error);
  2912. +            error = open_namei(tmp, O_RDWR, 0600, &inode, 0);
  2913. +            putname(tmp);
  2914. +            if (error)
  2915. +                return (error);
  2916. +            if (!S_ISREG(inode->i_mode)) {
  2917. +                iput(inode);
  2918. +                return -EACCES;
  2919. +            }
  2920. +            if (!inode->i_op || !inode->i_op->default_file_ops || 
  2921. +                !inode->i_op->default_file_ops->write) {
  2922. +                iput(inode);
  2923. +                return -EIO;
  2924. +            }
  2925. +            if ((acct_file = get_empty_filp()) == (struct file *)0)
  2926. +                return -EUSERS;
  2927. +            acct_file->f_mode = (O_WRONLY + 1) & O_ACCMODE;
  2928. +            acct_file->f_flags = O_WRONLY;
  2929. +            acct_file->f_inode = inode;
  2930. +            acct_file->f_pos = inode->i_size;
  2931. +            acct_file->f_reada = 0;
  2932. +            acct_file->f_op = inode->i_op->default_file_ops;
  2933. +            if (acct_file->f_op->open)
  2934. +                if (acct_file->f_op->open(acct_file->f_inode, acct_file)) {
  2935. +                    iput(inode);
  2936. +                    return -EIO;
  2937. +                }
  2938. +
  2939. +            vfs_open(acct_file);
  2940. +            acct_active = 1;
  2941. +            return 0;
  2942. +        } else
  2943. +            return -EBUSY;
  2944. +    }
  2945. +}
  2946. +
  2947. +void acct_auto_close(dev_t dev)
  2948. +{
  2949. +    if (acct_active && acct_file && acct_file->f_inode->i_dev == dev)
  2950. +        sys_acct((char *)0);
  2951.  }
  2952.  
  2953.  asmlinkage int sys_phys(void)
  2954.