home *** CD-ROM | disk | FTP | other *** search
/ PC-Online 1996 May / PCOnline_05_1996.bin / linux / source / kernel-s / v1.1 / kdiffs-1.1 / kdiffs-1.1.92-quota+acct
Text File  |  1995-02-17  |  97KB  |  3,328 lines

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